Refine EffectProxy logic
To allow create multiple EffectProxy instances for same type
Implement dump with all sub-effects
Bug: 271500140
Test: Enable AIDL and flash to pixel
Test: Play Youtube music with effect on/off
Test: dumpsys media.audio_flinger
Change-Id: I468d7e8712d7b098d869f147a4b40881ef11cabb
Merged-In: I468d7e8712d7b098d869f147a4b40881ef11cabb
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 4c58fe9..8a582a5 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -194,11 +194,9 @@
statusTFromBinderStatus(mEffect->open(common, std::nullopt, &openReturn)));
if (mIsProxyEffect) {
- const auto& ret =
- std::static_pointer_cast<EffectProxy>(mEffect)->getEffectReturnParam();
- mStatusQ = std::make_shared<StatusMQ>(ret->statusMQ);
- mInputQ = std::make_shared<DataMQ>(ret->inputDataMQ);
- mOutputQ = std::make_shared<DataMQ>(ret->outputDataMQ);
+ mStatusQ = std::static_pointer_cast<EffectProxy>(mEffect)->getStatusMQ();
+ mInputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getInputMQ();
+ mOutputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getOutputMQ();
} else {
mStatusQ = std::make_shared<StatusMQ>(openReturn.statusMQ);
mInputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ);
@@ -206,6 +204,7 @@
}
if (status_t status = updateEventFlags(); status != OK) {
+ ALOGV("%s closing at status %d", __func__, status);
mEffect->close();
return status;
}
@@ -353,14 +352,15 @@
ALOGI("%s offload param offload %s ioHandle %d", __func__,
offload->isOffload ? "true" : "false", offload->ioHandle);
mCommon.ioHandle = offload->ioHandle;
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
- std::static_pointer_cast<EffectProxy>(mEffect)->setOffloadParam(offload)));
- // update FMQs
- const auto& ret = std::static_pointer_cast<EffectProxy>(mEffect)->getEffectReturnParam();
- mStatusQ = std::make_shared<StatusMQ>(ret->statusMQ);
- mInputQ = std::make_shared<DataMQ>(ret->inputDataMQ);
- mOutputQ = std::make_shared<DataMQ>(ret->outputDataMQ);
- RETURN_STATUS_IF_ERROR(updateEventFlags());
+ const auto& effectProxy = std::static_pointer_cast<EffectProxy>(mEffect);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(effectProxy->setOffloadParam(offload)));
+ // update FMQs if the effect instance already open
+ if (State state; effectProxy->getState(&state).isOk() && state != State::INIT) {
+ mStatusQ = effectProxy->getStatusMQ();
+ mInputQ = effectProxy->getInputMQ();
+ mOutputQ = effectProxy->getOutputMQ();
+ updateEventFlags();
+ }
}
return *static_cast<int32_t*>(pReplyData) = OK;
}
@@ -408,17 +408,27 @@
status_t EffectConversionHelperAidl::updateEventFlags() {
status_t status = BAD_VALUE;
EventFlag* efGroup = nullptr;
- if (mStatusQ->isValid()) {
+ if (mStatusQ && mStatusQ->isValid()) {
status = EventFlag::createEventFlag(mStatusQ->getEventFlagWord(), &efGroup);
if (status != OK || !efGroup) {
ALOGE("%s: create EventFlagGroup failed, ret %d, egGroup %p", __func__, status,
efGroup);
status = (status == OK) ? BAD_VALUE : status;
}
+ } else if (isBypassing()) {
+ // for effect with bypass (no processing) flag, it's okay to not have statusQ
+ return OK;
}
+
mEfGroup.reset(efGroup, EventFlagDeleter());
return status;
}
+bool EffectConversionHelperAidl::isBypassing() const {
+ return mEffect &&
+ (mDesc.common.flags.bypass ||
+ (mIsProxyEffect && std::static_pointer_cast<EffectProxy>(mEffect)->isBypassing()));
+}
+
} // namespace effect
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index e2cf87f..7c8f11b 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -41,6 +41,7 @@
std::shared_ptr<DataMQ> getInputMQ() { return mInputQ; }
std::shared_ptr<DataMQ> getOutputMQ() { return mOutputQ; }
std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
+ bool isBypassing() const;
protected:
const int32_t mSessionId;
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index a5f2c61..36abfa4 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -76,8 +76,11 @@
EffectHalAidl::~EffectHalAidl() {
if (mEffect) {
- mIsProxyEffect ? std::static_pointer_cast<EffectProxy>(mEffect)->destroy()
- : mFactory->destroyEffect(mEffect);
+ if (mIsProxyEffect) {
+ std::static_pointer_cast<EffectProxy>(mEffect)->destroy();
+ } else if (mFactory) {
+ mFactory->destroyEffect(mEffect);
+ }
}
}
@@ -167,6 +170,9 @@
auto inputQ = mConversion->getInputMQ();
auto outputQ = mConversion->getOutputMQ();
auto efGroup = mConversion->getEventFlagGroup();
+ if (mConversion->isBypassing()) {
+ return OK;
+ }
if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ ||
!outputQ->isValid() || !efGroup) {
ALOGE("%s invalid FMQ [Status %d I %d O %d] efGroup %p", __func__,
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index 3bb045b..fac03b7 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -15,9 +15,10 @@
*/
#include <algorithm>
+#include <iterator>
#include <memory>
#define LOG_TAG "EffectProxy"
-//#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
#include <fmq/AidlMessageQueue.h>
#include <system/audio_aidl_utils.h>
@@ -25,6 +26,7 @@
#include "EffectProxy.h"
+using ::aidl::android::hardware::audio::effect::Capability;
using ::aidl::android::hardware::audio::effect::CommandId;
using ::aidl::android::hardware::audio::effect::Descriptor;
using ::aidl::android::hardware::audio::effect::Flags;
@@ -33,19 +35,29 @@
using ::aidl::android::hardware::audio::effect::Parameter;
using ::aidl::android::hardware::audio::effect::State;
using ::aidl::android::media::audio::common::AudioUuid;
-using ::android::audio::utils::toString;
-namespace android {
-namespace effect {
+namespace android::effect {
-EffectProxy::EffectProxy(const Descriptor::Identity& id, const std::shared_ptr<IFactory>& factory)
- : mIdentity([](const Descriptor::Identity& subId) {
- // update EffectProxy implementation UUID to the sub-effect proxy UUID
- ALOG_ASSERT(subId.proxy.has_value(), "Sub-effect Identity must have valid proxy UUID");
- Descriptor::Identity tempId = subId;
- tempId.uuid = subId.proxy.value();
- return tempId;
- }(id)),
+EffectProxy::EffectProxy(const AudioUuid& uuid, const std::vector<Descriptor>& descriptors,
+ const std::shared_ptr<IFactory>& factory)
+ : mDescriptorCommon(buildDescriptorCommon(uuid, descriptors)),
+ mSubEffects(
+ [](const std::vector<Descriptor>& descs, const std::shared_ptr<IFactory>& factory) {
+ std::vector<SubEffect> subEffects;
+ ALOG_ASSERT(factory, "invalid EffectFactory handle");
+ ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
+ for (const auto& desc : descs) {
+ SubEffect sub({.descriptor = desc});
+ status = factory->createEffect(desc.common.id.uuid, &sub.handle);
+ if (!status.isOk() || !sub.handle) {
+ sub.handle = nullptr;
+ ALOGW("%s create sub-effect %s failed", __func__,
+ ::android::audio::utils::toString(desc.common.id.uuid).c_str());
+ }
+ subEffects.emplace_back(sub);
+ }
+ return subEffects;
+ }(descriptors, factory)),
mFactory(factory) {}
EffectProxy::~EffectProxy() {
@@ -54,68 +66,9 @@
mSubEffects.clear();
}
-// sub effect must have same proxy UUID as EffectProxy, and the type UUID must match.
-ndk::ScopedAStatus EffectProxy::addSubEffect(const Descriptor& sub) {
- ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
- if (0 != mSubEffects.count(sub.common.id) || !sub.common.id.proxy.has_value() ||
- sub.common.id.proxy.value() != mIdentity.uuid) {
- ALOGE("%s sub effect already exist or mismatch %s", __func__, sub.toString().c_str());
- return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
- "illegalSubEffect");
- }
-
- // not create sub-effect yet
- std::get<SubEffectTupleIndex::HANDLE>(mSubEffects[sub.common.id]) = nullptr;
- std::get<SubEffectTupleIndex::DESCRIPTOR>(mSubEffects[sub.common.id]) = sub;
- // set the last added sub-effect to active before setOffloadParam()
- mActiveSub = sub.common.id;
- ALOGI("%s add %s to proxy %s flag %s", __func__, mActiveSub.toString().c_str(),
- mIdentity.toString().c_str(), sub.common.flags.toString().c_str());
-
- if (sub.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL) {
- mSubFlags.hwAcceleratorMode = Flags::HardwareAccelerator::TUNNEL;
- }
-
- // initial flag values before we know which sub-effect to active (with setOffloadParam)
- // same as HIDL EffectProxy flags
- mSubFlags.type = Flags::Type::INSERT;
- mSubFlags.insert = Flags::Insert::LAST;
- mSubFlags.volume = Flags::Volume::CTRL;
-
- // set indication if any sub-effect indication was set
- mSubFlags.offloadIndication |= sub.common.flags.offloadIndication;
- mSubFlags.deviceIndication |= sub.common.flags.deviceIndication;
- mSubFlags.audioModeIndication |= sub.common.flags.audioModeIndication;
- mSubFlags.audioSourceIndication |= sub.common.flags.audioSourceIndication;
-
- // set bypass when all sub-effects are bypassing
- mSubFlags.bypass &= sub.common.flags.bypass;
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus EffectProxy::create() {
- ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
- ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
-
- for (auto& sub : mSubEffects) {
- auto& effectHandle = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
- ALOGI("%s sub-effect %s", __func__, toString(sub.first.uuid).c_str());
- status = mFactory->createEffect(sub.first.uuid, &effectHandle);
- if (!status.isOk() || !effectHandle) {
- ALOGE("%s sub-effect failed %s", __func__, toString(sub.first.uuid).c_str());
- break;
- }
- }
-
- // destroy all created effects if failure
- if (!status.isOk()) {
- destroy();
- }
- return status;
-}
-
ndk::ScopedAStatus EffectProxy::destroy() {
- ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
+ ALOGV("%s: %s", __func__,
+ ::android::audio::utils::toString(mDescriptorCommon.id.type).c_str());
return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
ndk::ScopedAStatus status = mFactory->destroyEffect(effect);
if (status.isOk()) {
@@ -125,28 +78,24 @@
});
}
-const IEffect::OpenEffectReturn* EffectProxy::getEffectReturnParam() {
- return &std::get<SubEffectTupleIndex::RETURN>(mSubEffects[mActiveSub]);
-}
-
ndk::ScopedAStatus EffectProxy::setOffloadParam(const effect_offload_param_t* offload) {
const auto& itor = std::find_if(mSubEffects.begin(), mSubEffects.end(), [&](const auto& sub) {
- const auto& desc = std::get<SubEffectTupleIndex::DESCRIPTOR>(sub.second);
- ALOGI("%s: isOffload %d sub-effect: %s, flags %s", __func__, offload->isOffload,
- toString(desc.common.id.uuid).c_str(), desc.common.flags.toString().c_str());
+ const auto& desc = sub.descriptor;
return offload->isOffload ==
(desc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL);
});
if (itor == mSubEffects.end()) {
ALOGE("%s no %soffload sub-effect found", __func__, offload->isOffload ? "" : "non-");
+ mActiveSubIdx = 0;
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
"noActiveEffctFound");
}
- mActiveSub = itor->first;
- ALOGI("%s: active %soffload sub-effect: %s, flags %s", __func__,
- offload->isOffload ? "" : "non-", toString(mActiveSub.uuid).c_str(),
- std::get<SubEffectTupleIndex::DESCRIPTOR>(itor->second).common.flags.toString().c_str());
+ mActiveSubIdx = std::distance(mSubEffects.begin(), itor);
+ ALOGV("%s: active %soffload sub-effect %zu descriptor: %s", __func__,
+ offload->isOffload ? "" : "non-", mActiveSubIdx,
+ ::android::audio::utils::toString(mSubEffects[mActiveSubIdx].descriptor.common.id.uuid)
+ .c_str());
return ndk::ScopedAStatus::ok();
}
@@ -154,20 +103,24 @@
ndk::ScopedAStatus EffectProxy::open(const Parameter::Common& common,
const std::optional<Parameter::Specific>& specific,
IEffect::OpenEffectReturn* ret __unused) {
- ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
ndk::ScopedAStatus status = ndk::ScopedAStatus::fromExceptionCodeWithMessage(
EX_ILLEGAL_ARGUMENT, "nullEffectHandle");
for (auto& sub : mSubEffects) {
- auto& effect = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
- auto& openRet = std::get<SubEffectTupleIndex::RETURN>(sub.second);
- if (!effect || !(status = effect->open(common, specific, &openRet)).isOk()) {
- ALOGE("%s: failed to open UUID %s", __func__, toString(sub.first.uuid).c_str());
+ IEffect::OpenEffectReturn openReturn;
+ if (!sub.handle || !(status = sub.handle->open(common, specific, &openReturn)).isOk()) {
+ ALOGE("%s: failed to open %p UUID %s", __func__, sub.handle.get(),
+ ::android::audio::utils::toString(sub.descriptor.common.id.uuid).c_str());
break;
}
+ sub.effectMq.statusQ = std::make_shared<StatusMQ>(openReturn.statusMQ);
+ sub.effectMq.inputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ);
+ sub.effectMq.outputQ = std::make_shared<DataMQ>(openReturn.outputDataMQ);
}
// close all opened effects if failure
if (!status.isOk()) {
+ ALOGE("%s: closing all sub-effects with error %s", __func__,
+ status.getDescription().c_str());
close();
}
@@ -175,38 +128,69 @@
}
ndk::ScopedAStatus EffectProxy::close() {
- ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
return effect->close();
});
}
ndk::ScopedAStatus EffectProxy::getDescriptor(Descriptor* desc) {
+ desc->common = mDescriptorCommon;
+ desc->capability = mSubEffects[mActiveSubIdx].descriptor.capability;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectProxy::buildDescriptor(const AudioUuid& uuid,
+ const std::vector<Descriptor>& subEffectDescs,
+ Descriptor* desc) {
if (!desc) {
- ALOGE("%s: nuull descriptor pointer", __func__);
+ ALOGE("%s: null descriptor pointer", __func__);
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER, "nullptr");
}
- auto& activeSubEffect = std::get<SubEffectTupleIndex::HANDLE>(mSubEffects[mActiveSub]);
- // return initial descriptor if no active sub-effect exist
- if (!activeSubEffect) {
- desc->common.id = mIdentity;
- desc->common.flags = mSubFlags;
- desc->common.name = "Proxy";
- desc->common.implementor = "AOSP";
- } else {
- *desc = std::get<SubEffectTupleIndex::DESCRIPTOR>(mSubEffects[mActiveSub]);
- desc->common.id = mIdentity;
+ if (subEffectDescs.size() < 2) {
+ ALOGE("%s: proxy need at least 2 sub-effects, got %zu", __func__, subEffectDescs.size());
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "needMoreSubEffects");
}
- ALOGI("%s with %s", __func__, desc->toString().c_str());
+ desc->common = buildDescriptorCommon(uuid, subEffectDescs);
return ndk::ScopedAStatus::ok();
}
+Descriptor::Common EffectProxy::buildDescriptorCommon(
+ const AudioUuid& uuid, const std::vector<Descriptor>& subEffectDescs) {
+ Descriptor::Common common;
+
+ for (const auto& desc : subEffectDescs) {
+ if (desc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL) {
+ common.flags.hwAcceleratorMode = Flags::HardwareAccelerator::TUNNEL;
+ }
+
+ // set indication if any sub-effect indication was set
+ common.flags.offloadIndication |= desc.common.flags.offloadIndication;
+ common.flags.deviceIndication |= desc.common.flags.deviceIndication;
+ common.flags.audioModeIndication |= desc.common.flags.audioModeIndication;
+ common.flags.audioSourceIndication |= desc.common.flags.audioSourceIndication;
+ }
+
+ // 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::CTRL;
+
+ // copy type UUID from any of sub-effects, all sub-effects should have same type
+ common.id.type = subEffectDescs[0].common.id.type;
+ // replace implementation UUID with proxy UUID.
+ common.id.uuid = uuid;
+ common.id.proxy = std::nullopt;
+ common.name = "Proxy";
+ common.implementor = "AOSP";
+ return common;
+}
+
// Handle with active sub-effect first, only send to other sub-effects when success
ndk::ScopedAStatus EffectProxy::command(CommandId id) {
- ALOGV("%s: %s, command %s", __func__, toString(mIdentity.type).c_str(),
- android::internal::ToString(id).c_str());
return runWithActiveSubEffectThenOthers(
[&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
return effect->command(id);
@@ -241,34 +225,30 @@
std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func) {
ndk::ScopedAStatus status = runWithActiveSubEffect(func);
if (!status.isOk()) {
- return status;
+ ALOGE("%s active sub-effect return error %s", __func__, status.getDescription().c_str());
}
- // proceed with others if active sub-effect success
- for (const auto& sub : mSubEffects) {
- auto& effect = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
- if (sub.first != mActiveSub) {
- if (!effect) {
- ALOGE("%s null sub-effect interface for %s", __func__,
- sub.first.toString().c_str());
- continue;
- }
- func(effect);
+ // proceed with others
+ for (size_t i = 0; i < mSubEffects.size() && i != mActiveSubIdx; i++) {
+ if (!mSubEffects[i].handle) {
+ ALOGE("%s null sub-effect interface for %s", __func__,
+ mSubEffects[i].descriptor.common.id.uuid.toString().c_str());
+ continue;
}
+ func(mSubEffects[i].handle);
}
return status;
}
ndk::ScopedAStatus EffectProxy::runWithActiveSubEffect(
std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func) {
- auto& effect = std::get<SubEffectTupleIndex::HANDLE>(mSubEffects[mActiveSub]);
- if (!effect) {
+ if (!mSubEffects[mActiveSubIdx].handle) {
ALOGE("%s null active sub-effect interface, active %s", __func__,
- mActiveSub.toString().c_str());
+ mSubEffects[mActiveSubIdx].descriptor.toString().c_str());
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
"activeSubEffectNull");
}
- return func(effect);
+ return func(mSubEffects[mActiveSubIdx].handle);
}
ndk::ScopedAStatus EffectProxy::runWithAllSubEffects(
@@ -276,12 +256,11 @@
ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
// proceed with others if active sub-effect success
for (auto& sub : mSubEffects) {
- auto& effect = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
- if (!effect) {
- ALOGW("%s null sub-effect interface for %s", __func__, sub.first.toString().c_str());
+ if (!sub.handle) {
+ ALOGW("%s null sub-effect interface %s", __func__, sub.descriptor.toString().c_str());
continue;
}
- ndk::ScopedAStatus temp = func(effect);
+ ndk::ScopedAStatus temp = func(sub.handle);
if (!temp.isOk()) {
status = ndk::ScopedAStatus::fromStatus(temp.getStatus());
}
@@ -289,5 +268,34 @@
return status;
}
-} // namespace effect
-} // namespace android
+bool EffectProxy::isBypassing() const {
+ return mSubEffects[mActiveSubIdx].descriptor.common.flags.bypass;
+}
+
+binder_status_t EffectProxy::dump(int fd, const char** args, uint32_t numArgs) {
+ const std::string dumpString = toString();
+ write(fd, dumpString.c_str(), dumpString.size());
+
+ return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
+ return ndk::ScopedAStatus::fromStatus(effect->dump(fd, args, numArgs));
+ })
+ .getStatus();
+}
+
+std::string EffectProxy::toString(size_t level) const {
+ std::string prefixSpace(level, ' ');
+ std::string ss = prefixSpace + "EffectProxy:\n";
+ prefixSpace += " ";
+ base::StringAppendF(&ss, "%sDescriptorCommon: %s\n", prefixSpace.c_str(),
+ mDescriptorCommon.toString().c_str());
+ base::StringAppendF(&ss, "%sActiveSubIdx: %zu\n", prefixSpace.c_str(), mActiveSubIdx);
+ base::StringAppendF(&ss, "%sAllSubEffects:\n", prefixSpace.c_str());
+ for (size_t i = 0; i < mSubEffects.size(); i++) {
+ base::StringAppendF(&ss, "%s[%zu] - Handle: %p, %s\n", prefixSpace.c_str(), i,
+ mSubEffects[i].handle.get(),
+ mSubEffects[i].descriptor.toString().c_str());
+ }
+ return ss;
+}
+
+} // namespace android::effect
diff --git a/media/libaudiohal/impl/EffectProxy.h b/media/libaudiohal/impl/EffectProxy.h
index ffb8a19..18e1567 100644
--- a/media/libaudiohal/impl/EffectProxy.h
+++ b/media/libaudiohal/impl/EffectProxy.h
@@ -40,27 +40,10 @@
*/
class EffectProxy final : public ::aidl::android::hardware::audio::effect::BnEffect {
public:
- EffectProxy(const ::aidl::android::hardware::audio::effect::Descriptor::Identity& id,
- const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory);
-
- /**
- * Add a sub effect into the proxy, the descriptor of candidate sub-effect need to have same
- * proxy UUID as mUuid.
- */
- ndk::ScopedAStatus addSubEffect(
- const ::aidl::android::hardware::audio::effect::Descriptor& sub);
-
- /**
- * Create all sub-effects via AIDL IFactory, always call create() after all sub-effects added
- * successfully with addSubEffect.
- */
- ndk::ScopedAStatus create();
-
- /**
- * Destroy all sub-effects via AIDL IFactory, always call create() after all sub-effects added
- * successfully with addSubEffect.
- */
- ndk::ScopedAStatus destroy();
+ EffectProxy(
+ const ::aidl::android::media::audio::common::AudioUuid& uuid,
+ const std::vector<::aidl::android::hardware::audio::effect::Descriptor>& descriptors,
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory);
/**
* Handle offload parameter setting from framework.
@@ -68,11 +51,9 @@
ndk::ScopedAStatus setOffloadParam(const effect_offload_param_t* offload);
/**
- * Get the const reference of the active sub-effect return parameters.
- * Always use this interface to get the effect open return parameters (FMQs) after a success
- * setOffloadParam() call.
+ * Destroy all sub-effects via AIDL IFactory.
*/
- const IEffect::OpenEffectReturn* getEffectReturnParam();
+ ndk::ScopedAStatus destroy();
// IEffect interfaces override
ndk::ScopedAStatus open(
@@ -91,25 +72,59 @@
const ::aidl::android::hardware::audio::effect::Parameter::Id& id,
::aidl::android::hardware::audio::effect::Parameter* param) override;
+ static ndk::ScopedAStatus buildDescriptor(
+ const ::aidl::android::media::audio::common::AudioUuid& uuid,
+ const std::vector<::aidl::android::hardware::audio::effect::Descriptor>& subEffectDescs,
+ ::aidl::android::hardware::audio::effect::Descriptor* desc);
+
+ /**
+ * Get the const reference of the active sub-effect return parameters.
+ * Always use this interface to get the effect open return parameters (FMQs) after a success
+ * setOffloadParam() call.
+ */
+ using StatusMQ = ::android::AidlMessageQueue<
+ ::aidl::android::hardware::audio::effect::IEffect::Status,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+ using DataMQ = ::android::AidlMessageQueue<
+ float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+ const std::shared_ptr<StatusMQ>& getStatusMQ() const {
+ return mSubEffects[mActiveSubIdx].effectMq.statusQ;
+ }
+ const std::shared_ptr<DataMQ>& getInputMQ() const {
+ return mSubEffects[mActiveSubIdx].effectMq.inputQ;
+ }
+ const std::shared_ptr<DataMQ>& getOutputMQ() const {
+ return mSubEffects[mActiveSubIdx].effectMq.outputQ;
+ }
+
+ bool isBypassing() const;
+
+ // call dump for all sub-effects
+ binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
+ std::string toString(size_t indent = 0) const;
+
private:
- // Proxy identity, copy from one sub-effect, and update the implementation UUID to proxy UUID
- const ::aidl::android::hardware::audio::effect::Descriptor::Identity mIdentity;
+ // Proxy descriptor common part, copy from one sub-effect, and update the implementation UUID to
+ // proxy UUID, proxy descriptor capability part comes from the active sub-effect capability
+ const ::aidl::android::hardware::audio::effect::Descriptor::Common mDescriptorCommon;
+
+ struct EffectMQ {
+ std::shared_ptr<StatusMQ> statusQ;
+ std::shared_ptr<DataMQ> inputQ, outputQ;
+ };
+ struct SubEffect {
+ const ::aidl::android::hardware::audio::effect::Descriptor descriptor;
+ std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> handle;
+ EffectMQ effectMq;
+ };
+ std::vector<SubEffect> mSubEffects;
+
const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory> mFactory;
- // A map of sub effects descriptor to the IEffect handle and return FMQ
- enum SubEffectTupleIndex { HANDLE, DESCRIPTOR, RETURN };
- using EffectProxySub =
- std::tuple<std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>,
- ::aidl::android::hardware::audio::effect::Descriptor,
- ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn>;
- std::map<const ::aidl::android::hardware::audio::effect::Descriptor::Identity, EffectProxySub>
- mSubEffects;
-
- // Descriptor of the only active effect in the mSubEffects map
- ::aidl::android::hardware::audio::effect::Descriptor::Identity mActiveSub;
-
- // keep the flag of sub-effects
- ::aidl::android::hardware::audio::effect::Flags mSubFlags;
+ // index of the active sub-effects, by default use the first one (index 0)
+ // It's safe to assume there will always at least two SubEffects in mSubEffects
+ size_t mActiveSubIdx = 0;
ndk::ScopedAStatus runWithActiveSubEffectThenOthers(
std::function<ndk::ScopedAStatus(
@@ -122,6 +137,12 @@
ndk::ScopedAStatus runWithAllSubEffects(
std::function<ndk::ScopedAStatus(std::shared_ptr<IEffect>&)> const& func);
+ // build Descriptor.Common with all sub-effect descriptors
+ static ::aidl::android::hardware::audio::effect::Descriptor::Common buildDescriptorCommon(
+ const ::aidl::android::media::audio::common::AudioUuid& uuid,
+ const std::vector<::aidl::android::hardware::audio::effect::Descriptor>&
+ subEffectDescs);
+
// close and release all sub-effects
~EffectProxy();
};
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index f278ca0..cf19dae 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -68,26 +68,28 @@
}
return list;
}()),
- mUuidProxyMap([this]() {
- std::map<AudioUuid, std::shared_ptr<EffectProxy>> proxyMap;
+ mProxyUuidDescriptorMap([this]() {
+ std::map<AudioUuid, std::vector<Descriptor>> proxyUuidMap;
for (const auto& desc : mHalDescList) {
- // create EffectProxy
if (desc.common.id.proxy.has_value()) {
const auto& uuid = desc.common.id.proxy.value();
- if (0 == proxyMap.count(uuid)) {
- proxyMap.insert({uuid, ndk::SharedRefBase::make<EffectProxy>(desc.common.id,
- mFactory)});
+ if (proxyUuidMap.count(uuid) == 0) {
+ proxyUuidMap.insert({uuid, {desc}});
+ } else {
+ proxyUuidMap[uuid].emplace_back(desc);
}
- proxyMap[uuid]->addSubEffect(desc);
- ALOGI("%s addSubEffect %s", __func__, desc.common.toString().c_str());
}
}
- return proxyMap;
+ return proxyUuidMap;
}()),
mProxyDescList([this]() {
std::vector<Descriptor> list;
- for (const auto& proxy : mUuidProxyMap) {
- if (Descriptor desc; proxy.second && proxy.second->getDescriptor(&desc).isOk()) {
+ for (const auto& proxy : mProxyUuidDescriptorMap) {
+ if (Descriptor desc;
+ EffectProxy::buildDescriptor(proxy.first /* uuid */,
+ proxy.second /* sub-effect descriptor list */,
+ &desc /* proxy descriptor */)
+ .isOk()) {
list.emplace_back(std::move(desc));
}
}
@@ -118,7 +120,8 @@
}
*pNumEffects = mEffectCount;
- ALOGI("%s %d", __func__, *pNumEffects);
+ ALOGD("%s %u non %zu proxyMap %zu proxyDesc %zu", __func__, *pNumEffects,
+ mNonProxyDescList.size(), mProxyUuidDescriptorMap.size(), mProxyDescList.size());
return OK;
}
@@ -183,8 +186,10 @@
// Use EffectProxy interface instead of IFactory to create
const bool isProxy = isProxyEffect(aidlUuid);
if (isProxy) {
- aidlEffect = mUuidProxyMap.at(aidlUuid);
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mUuidProxyMap.at(aidlUuid)->create()));
+ aidlEffect = ndk::SharedRefBase::make<EffectProxy>(
+ aidlUuid, mProxyUuidDescriptorMap.at(aidlUuid) /* sub-effect descriptor list */,
+ mFactory);
+ mProxyList.emplace_back(std::static_pointer_cast<EffectProxy>(aidlEffect));
} else {
RETURN_STATUS_IF_ERROR(
statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect)));
@@ -209,12 +214,11 @@
status_t EffectsFactoryHalAidl::dumpEffects(int fd) {
status_t ret = OK;
+ std::lock_guard lg(mLock);
// record the error ret and continue dump as many effects as possible
- for (const auto& proxy : mUuidProxyMap) {
- if (proxy.second) {
- if (status_t temp = proxy.second->dump(fd, nullptr, 0); temp != OK) {
- ret = temp;
- }
+ for (const auto& proxy : mProxyList) {
+ if (status_t temp = BAD_VALUE; proxy && (temp = proxy->dump(fd, nullptr, 0)) != OK) {
+ ret = temp;
}
}
RETURN_STATUS_IF_ERROR(mFactory->dump(fd, nullptr, 0));
@@ -280,7 +284,7 @@
}
bool EffectsFactoryHalAidl::isProxyEffect(const AudioUuid& uuid) const {
- return 0 != mUuidProxyMap.count(uuid);
+ return 0 != mProxyUuidDescriptorMap.count(uuid);
}
std::shared_ptr<const effectsConfig::Processings> EffectsFactoryHalAidl::getProcessings() const {
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
index 39beea2..b900cb4 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -17,6 +17,7 @@
#pragma once
#include <cstddef>
+#include <list>
#include <memory>
#include <mutex>
@@ -72,10 +73,9 @@
const detail::AudioHalVersionInfo mHalVersion;
// Full list of HAL effect descriptors
const std::vector<Descriptor> mHalDescList;
- // Map of proxy UUID (key) to the proxy object
- const std::map<::aidl::android::media::audio::common::AudioUuid /* proxy impl UUID */,
- std::shared_ptr<EffectProxy>>
- mUuidProxyMap;
+ // Map of proxy UUID (key) to the Descriptor of sub-effects
+ const std::map<::aidl::android::media::audio::common::AudioUuid, std::vector<Descriptor>>
+ mProxyUuidDescriptorMap;
// List of effect proxy, initialize after mUuidProxyMap because it need to have all sub-effects
const std::vector<Descriptor> mProxyDescList;
// List of non-proxy effects
@@ -85,16 +85,19 @@
// Query result of pre and post processing from effect factory
const std::vector<Processing> mAidlProcessings;
+ // list of the EffectProxy instances
+ std::list<std::shared_ptr<EffectProxy>> mProxyList;
+
std::mutex mLock;
uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0; // Align with HIDL (0 is INVALID_ID)
virtual ~EffectsFactoryHalAidl() = default;
status_t getHalDescriptorWithImplUuid(
- const aidl::android::media::audio::common::AudioUuid& uuid,
+ const ::aidl::android::media::audio::common::AudioUuid& uuid,
effect_descriptor_t* pDescriptor);
status_t getHalDescriptorWithTypeUuid(
- const aidl::android::media::audio::common::AudioUuid& type,
+ const ::aidl::android::media::audio::common::AudioUuid& type,
std::vector<effect_descriptor_t>* descriptors);
bool isProxyEffect(const aidl::android::media::audio::common::AudioUuid& uuid) const;
diff --git a/media/libaudiohal/tests/EffectProxy_test.cpp b/media/libaudiohal/tests/EffectProxy_test.cpp
index 92e3dce..8668e85 100644
--- a/media/libaudiohal/tests/EffectProxy_test.cpp
+++ b/media/libaudiohal/tests/EffectProxy_test.cpp
@@ -60,7 +60,7 @@
mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &mDescs);
for (const auto& desc : mDescs) {
if (desc.common.id.proxy.has_value()) {
- mProxyDescs.insert({desc.common.id, desc});
+ mProxyDescs[desc.common.id.proxy.value()].emplace_back(desc);
}
}
}
@@ -96,44 +96,24 @@
return common;
}
- static bool isFlagSet(const ::aidl::android::hardware::audio::effect::Descriptor& desc,
- Flags::HardwareAccelerator flag) {
- return desc.common.flags.hwAcceleratorMode == flag;
- }
-
enum TupleIndex { HANDLE, DESCRIPTOR };
using EffectProxyTuple = std::tuple<std::shared_ptr<EffectProxy>, std::vector<Descriptor>>;
std::map<AudioUuid, EffectProxyTuple> createAllProxies() {
std::map<AudioUuid, EffectProxyTuple> proxyMap;
for (const auto& itor : mProxyDescs) {
- const auto& uuid = itor.first.proxy.value();
+ const auto& uuid = itor.first;
if (proxyMap.end() == proxyMap.find(uuid)) {
std::get<TupleIndex::HANDLE>(proxyMap[uuid]) =
- ndk::SharedRefBase::make<EffectProxy>(itor.first, mFactory);
+ ndk::SharedRefBase::make<EffectProxy>(itor.first, itor.second, mFactory);
}
}
return proxyMap;
}
- bool addAllSubEffects(std::map<AudioUuid, EffectProxyTuple> proxyMap) {
- for (auto& itor : mProxyDescs) {
- const auto& uuid = itor.first.proxy.value();
- if (proxyMap.end() == proxyMap.find(uuid)) {
- return false;
- }
- auto& proxy = std::get<TupleIndex::HANDLE>(proxyMap[uuid]);
- if (!proxy->addSubEffect(itor.second).isOk()) {
- return false;
- }
- std::get<TupleIndex::DESCRIPTOR>(proxyMap[uuid]).emplace_back(itor.second);
- }
- return true;
- }
-
std::shared_ptr<IFactory> mFactory;
std::vector<Descriptor> mDescs;
- std::map<Descriptor::Identity, Descriptor> mProxyDescs;
+ std::map<const AudioUuid, std::vector<Descriptor>> mProxyDescs;
};
TEST_F(EffectProxyTest, createProxy) {
@@ -144,24 +124,20 @@
TEST_F(EffectProxyTest, addSubEffectsCreateAndDestroy) {
auto proxyMap = createAllProxies();
- ASSERT_TRUE(addAllSubEffects(proxyMap));
for (const auto& itor : proxyMap) {
auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
- EXPECT_TRUE(proxy->create().isOk());
EXPECT_TRUE(proxy->destroy().isOk());
}
}
TEST_F(EffectProxyTest, addSubEffectsCreateOpenCloseDestroy) {
auto proxyMap = createAllProxies();
- EXPECT_TRUE(addAllSubEffects(proxyMap));
Parameter::Common common = createParamCommon();
IEffect::OpenEffectReturn ret;
for (const auto& itor : proxyMap) {
auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
- EXPECT_TRUE(proxy->create().isOk());
EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
EXPECT_TRUE(proxy->close().isOk());
EXPECT_TRUE(proxy->destroy().isOk());
@@ -171,33 +147,23 @@
// Add sub-effects, set active sub-effect with different checkers
TEST_F(EffectProxyTest, setOffloadParam) {
auto proxyMap = createAllProxies();
- EXPECT_TRUE(addAllSubEffects(proxyMap));
// Any flag exist should be able to set successfully
- bool isNoneExist = false, isSimpleExist = false, isTunnelExist = false;
- for (const auto& itor : mProxyDescs) {
- isNoneExist = isNoneExist || isFlagSet(itor.second, Flags::HardwareAccelerator::NONE);
- isSimpleExist = isSimpleExist || isFlagSet(itor.second, Flags::HardwareAccelerator::SIMPLE);
- isTunnelExist = isTunnelExist || isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL);
- }
-
Parameter::Common common = createParamCommon();
IEffect::OpenEffectReturn ret;
for (const auto& itor : proxyMap) {
auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
- EXPECT_TRUE(proxy->create().isOk());
EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
effect_offload_param_t offloadParam{false, 0};
- EXPECT_EQ(isNoneExist || isSimpleExist, proxy->setOffloadParam(&offloadParam).isOk());
+ EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
offloadParam.isOffload = true;
- EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk());
+ EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
EXPECT_TRUE(proxy->close().isOk());
EXPECT_TRUE(proxy->destroy().isOk());
}
}
TEST_F(EffectProxyTest, destroyWithoutCreate) {
auto proxyMap = createAllProxies();
- ASSERT_TRUE(addAllSubEffects(proxyMap));
for (const auto& itor : proxyMap) {
auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
@@ -207,11 +173,9 @@
TEST_F(EffectProxyTest, closeWithoutOpen) {
auto proxyMap = createAllProxies();
- ASSERT_TRUE(addAllSubEffects(proxyMap));
for (const auto& itor : proxyMap) {
auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
- EXPECT_TRUE(proxy->create().isOk());
EXPECT_TRUE(proxy->close().isOk());
EXPECT_TRUE(proxy->destroy().isOk());
@@ -221,16 +185,6 @@
// Add sub-effects, set active sub-effect, create, open, and send command, expect success handling
TEST_F(EffectProxyTest, normalSequency) {
auto proxyMap = createAllProxies();
- ASSERT_TRUE(addAllSubEffects(proxyMap));
-
- bool isTunnelExist = [&]() {
- for (const auto& itor : mProxyDescs) {
- if (isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL)) {
- return true;
- }
- }
- return false;
- }();
Parameter::Common common = createParamCommon();
IEffect::OpenEffectReturn ret;
@@ -242,14 +196,14 @@
Parameter expect;
auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
effect_offload_param_t offloadParam{true, 0};
- EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk());
+ EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
- EXPECT_TRUE(proxy->create().isOk());
EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
EXPECT_TRUE(proxy->setParameter(param).isOk());
EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
- EXPECT_EQ(expect, param);
+ EXPECT_EQ(expect, param) << " EXPECTED: " << expect.toString()
+ << "\nACTUAL: " << param.toString();
EXPECT_TRUE(proxy->command(CommandId::START).isOk());
EXPECT_TRUE(proxy->getState(&state).isOk());
@@ -267,14 +221,6 @@
// setParameter, change active sub-effect, verify with getParameter
TEST_F(EffectProxyTest, changeActiveSubAndVerifyParameter) {
auto proxyMap = createAllProxies();
- EXPECT_TRUE(addAllSubEffects(proxyMap));
-
- bool isNoneExist = false, isSimpleExist = false, isTunnelExist = false;
- for (const auto& itor : mProxyDescs) {
- isNoneExist = isNoneExist || isFlagSet(itor.second, Flags::HardwareAccelerator::NONE);
- isSimpleExist = isSimpleExist || isFlagSet(itor.second, Flags::HardwareAccelerator::SIMPLE);
- isTunnelExist = isTunnelExist || isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL);
- }
Parameter::Common common = createParamCommon();
IEffect::OpenEffectReturn ret;
@@ -284,19 +230,18 @@
for (const auto& itor : proxyMap) {
Parameter expect;
auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
- EXPECT_TRUE(proxy->create().isOk());
EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
EXPECT_TRUE(proxy->setParameter(param).isOk());
EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
EXPECT_EQ(expect, param);
effect_offload_param_t offloadParam{false, 0};
- EXPECT_EQ(isNoneExist || isSimpleExist, proxy->setOffloadParam(&offloadParam).isOk());
+ EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
EXPECT_EQ(expect, param);
offloadParam.isOffload = true;
- EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk());
+ EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
EXPECT_EQ(expect, param);
@@ -308,14 +253,6 @@
// send command, change active sub-effect, then verify the state with getState
TEST_F(EffectProxyTest, changeActiveSubAndVerifyState) {
auto proxyMap = createAllProxies();
- ASSERT_TRUE(addAllSubEffects(proxyMap));
-
- bool isNoneExist = false, isSimpleExist = false, isTunnelExist = false;
- for (const auto& itor : mProxyDescs) {
- isNoneExist = isNoneExist || isFlagSet(itor.second, Flags::HardwareAccelerator::NONE);
- isSimpleExist = isSimpleExist || isFlagSet(itor.second, Flags::HardwareAccelerator::SIMPLE);
- isTunnelExist = isTunnelExist || isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL);
- }
Parameter::Common common = createParamCommon();
IEffect::OpenEffectReturn ret;
@@ -323,7 +260,6 @@
for (const auto& itor : proxyMap) {
Parameter expect;
auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
- EXPECT_TRUE(proxy->create().isOk());
EXPECT_TRUE(proxy->getState(&state).isOk());
EXPECT_EQ(State::INIT, state);
EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
@@ -334,12 +270,12 @@
EXPECT_EQ(State::PROCESSING, state);
effect_offload_param_t offloadParam{false, 0};
- EXPECT_EQ(isNoneExist || isSimpleExist, proxy->setOffloadParam(&offloadParam).isOk());
+ EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
EXPECT_TRUE(proxy->getState(&state).isOk());
EXPECT_EQ(State::PROCESSING, state);
offloadParam.isOffload = true;
- EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk());
+ EXPECT_TRUE(proxy->setOffloadParam(&offloadParam).isOk());
EXPECT_TRUE(proxy->getState(&state).isOk());
EXPECT_EQ(State::PROCESSING, state);