Skip to content

Commit 766aa0e

Browse files
committed
Implement AIDL JamesDSP effect
1 parent a34d0c7 commit 766aa0e

File tree

3 files changed

+364
-0
lines changed

3 files changed

+364
-0
lines changed

Main/libjamesdsp/jni/jamesdsp/Android.bp

+22
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,25 @@ cc_library_shared {
149149
"jamesdsp.c",
150150
],
151151
}
152+
153+
cc_library_shared {
154+
name: "libjamesdspaidl",
155+
vendor: true,
156+
relative_install_path: "soundfx",
157+
defaults: [
158+
"aidlaudioeffectservice_defaults",
159+
"jdspEffectDefaults",
160+
],
161+
srcs: [
162+
"jamesdsp_aidl.cpp",
163+
// AOSP
164+
":effectCommonFile",
165+
],
166+
shared_libs: [
167+
"libbinder",
168+
],
169+
whole_static_libs: [
170+
"libaudio_aidl_conversion_common_ndk",
171+
"libstagefright_foundation",
172+
],
173+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
/*
2+
* Copyright (C) 2022 The Android Open Source Project
3+
* 2024 anonymix007
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include <algorithm>
19+
#include <cstddef>
20+
21+
#define LOG_TAG "JamesDSP_AIDL"
22+
#include <android-base/logging.h>
23+
#include <fmq/AidlMessageQueue.h>
24+
#include <system/audio_effects/effect_uuid.h>
25+
#include <aidl/android/hardware/audio/effect/DefaultExtension.h>
26+
#include <media/AidlConversionUtil.h>
27+
template <typename T>
28+
using ConversionResult = ::android::error::Result<T>;
29+
#include <media/AidlConversionNdk.h>
30+
31+
#include "jamesdsp_aidl.h"
32+
33+
using aidl::android::hardware::audio::effect::Descriptor;
34+
using aidl::android::hardware::audio::effect::DefaultExtension;
35+
using aidl::android::hardware::audio::effect::JamesDSPAIDL;
36+
using aidl::android::hardware::audio::effect::getEffectTypeUuidJDSP;
37+
using aidl::android::hardware::audio::effect::getEffectImplUuidJDSP;
38+
using aidl::android::hardware::audio::effect::getEffectUuidNull;
39+
using aidl::android::hardware::audio::effect::IEffect;
40+
using aidl::android::hardware::audio::effect::State;
41+
using aidl::android::hardware::audio::effect::VendorExtension;
42+
using aidl::android::media::audio::common::AudioUuid;
43+
44+
__attribute__((visibility("default"))) extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
45+
std::shared_ptr<IEffect>* instanceSpp) {
46+
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidJDSP()) {
47+
LOG(ERROR) << __func__ << "uuid not supported";
48+
return EX_ILLEGAL_ARGUMENT;
49+
}
50+
if (instanceSpp) {
51+
*instanceSpp = ndk::SharedRefBase::make<JamesDSPAIDL>();
52+
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
53+
return EX_NONE;
54+
} else {
55+
LOG(ERROR) << __func__ << " invalid input parameter!";
56+
return EX_ILLEGAL_ARGUMENT;
57+
}
58+
}
59+
60+
__attribute__((visibility("default"))) extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
61+
if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidJDSP()) {
62+
LOG(ERROR) << __func__ << "uuid not supported";
63+
return EX_ILLEGAL_ARGUMENT;
64+
}
65+
*_aidl_return = JamesDSPAIDL::kDesc;
66+
return EX_NONE;
67+
}
68+
69+
namespace aidl::android::hardware::audio::effect {
70+
71+
#if __aarch64__ == 1
72+
const std::string JamesDSPAIDL::kEffectName = "James Audio DSP arm64";
73+
#elif __ARM_ARCH_7A__ == 1
74+
const std::string JamesDSPAIDL::kEffectName = "James Audio DSP arm32";
75+
#elif __i386__ == 1
76+
const std::string JamesDSPAIDL::kEffectName = "James Audio DSP x86";
77+
#elif __x86_64__ == 1
78+
const std::string JamesDSPAIDL::kEffectName = "James Audio DSP x64";
79+
#endif
80+
81+
const Descriptor JamesDSPAIDL::kDesc = {.common = {.id = {.type = getEffectTypeUuidJDSP(),
82+
.uuid = getEffectImplUuidJDSP()},
83+
.flags = {.type = Flags::Type::INSERT,
84+
.insert = Flags::Insert::LAST,
85+
.volume = Flags::Volume::CTRL},
86+
.name = JamesDSPAIDL::kEffectName,
87+
.implementor = "James Fung"}};
88+
89+
ndk::ScopedAStatus JamesDSPAIDL::getDescriptor(Descriptor* _aidl_return) {
90+
LOG(DEBUG) << __func__ << kDesc.toString();
91+
*_aidl_return = kDesc;
92+
return ndk::ScopedAStatus::ok();
93+
}
94+
95+
ndk::ScopedAStatus JamesDSPAIDL::setParameterSpecific(const Parameter::Specific& specific) {
96+
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
97+
// TODO: Handle Parameter::Common (EFFECT_CMD_SET_CONFIG)
98+
RETURN_IF(Parameter::Specific::vendorEffect != specific.getTag(), EX_ILLEGAL_ARGUMENT, "EffectNotSupported");
99+
auto& vendorEffect = specific.get<Parameter::Specific::vendorEffect>();
100+
std::optional<DefaultExtension> defaultExt;
101+
RETURN_IF(STATUS_OK != vendorEffect.extension.getParcelable(&defaultExt), EX_ILLEGAL_ARGUMENT, "getParcelableFailed");
102+
RETURN_IF(!defaultExt.has_value(), EX_ILLEGAL_ARGUMENT, "parcelableNull");
103+
104+
int32_t ret = 0;
105+
uint32_t ret_size = sizeof(ret);
106+
RETURN_IF(mContext->handleCommand(EFFECT_CMD_SET_PARAM, defaultExt->bytes.size(), defaultExt->bytes.data(), &ret_size, &ret) != 0, EX_ILLEGAL_ARGUMENT, "handleCommandFailed");
107+
RETURN_IF(ret != 0, EX_ILLEGAL_ARGUMENT, "handleCommandInternalFailed");
108+
return ndk::ScopedAStatus::ok();
109+
}
110+
111+
ndk::ScopedAStatus JamesDSPAIDL::getParameterSpecific(const Parameter::Id& id,
112+
Parameter::Specific* specific) {
113+
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
114+
// TODO: Handle Parameter::Common (EFFECT_CMD_GET_CONFIG)
115+
RETURN_IF(Parameter::Id::vendorEffectTag != id.getTag(), EX_ILLEGAL_ARGUMENT, "wrongIdTag");
116+
auto extensionId = id.get<Parameter::Id::vendorEffectTag>();
117+
std::optional<DefaultExtension> defaultIdExt;
118+
RETURN_IF(STATUS_OK != extensionId.extension.getParcelable(&defaultIdExt), EX_ILLEGAL_ARGUMENT, "getIdParcelableFailed");
119+
RETURN_IF(!defaultIdExt.has_value(), EX_ILLEGAL_ARGUMENT, "parcelableIdNull");
120+
121+
VendorExtension extension;
122+
DefaultExtension defaultExt;
123+
defaultExt.bytes.resize(sizeof(effect_param_t));
124+
uint32_t data_size = defaultExt.bytes.size();
125+
RETURN_IF(mContext->handleCommand(EFFECT_CMD_GET_PARAM, defaultIdExt->bytes.size(), defaultIdExt->bytes.data(), &data_size, defaultExt.bytes.data()) != 0, EX_ILLEGAL_ARGUMENT, "handleCommandFailed");
126+
RETURN_IF(STATUS_OK != extension.extension.setParcelable(defaultExt), EX_ILLEGAL_ARGUMENT, "setParcelableFailed");
127+
specific->set<Parameter::Specific::vendorEffect>(extension);
128+
return ndk::ScopedAStatus::ok();
129+
}
130+
131+
std::shared_ptr<EffectContext> JamesDSPAIDL::createContext(const Parameter::Common& common) {
132+
if (mContext) {
133+
LOG(DEBUG) << __func__ << " context already exist";
134+
} else {
135+
mContext = std::make_shared<JamesDSPAIDLContext>(1 /* statusFmqDepth */, common);
136+
int32_t ret = 0;
137+
uint32_t ret_size = sizeof(ret);
138+
int32_t status = mContext->handleCommand(EFFECT_CMD_INIT, 0, NULL, &ret_size, &ret);
139+
if (status < 0) {
140+
LOG(ERROR) << __func__ << ": JamesDSPAIDLContext::handleCommand failed: " << status;
141+
mContext = nullptr;
142+
return mContext;
143+
}
144+
if (ret < 0) {
145+
LOG(ERROR) << __func__ << ": JamesDSPAIDLContext::handleCommand failed (internal): " << ret;
146+
mContext = nullptr;
147+
return mContext;
148+
}
149+
ret = 0;
150+
ret_size = sizeof(ret);
151+
effect_config_t conf = {};
152+
153+
154+
auto tmp = ::aidl::android::aidl2legacy_AudioConfig_buffer_config_t(common.input, true);
155+
if (tmp.ok()) {
156+
conf.inputCfg = tmp.value();
157+
} else {
158+
mContext = nullptr;
159+
return mContext;
160+
}
161+
162+
tmp = ::aidl::android::aidl2legacy_AudioConfig_buffer_config_t(common.output, false);
163+
if (tmp.ok()) {
164+
conf.outputCfg = tmp.value();
165+
} else {
166+
mContext = nullptr;
167+
return mContext;
168+
}
169+
170+
status = mContext->handleCommand(EFFECT_CMD_SET_CONFIG, sizeof(conf), &conf, &ret_size, &ret);
171+
if (status < 0) {
172+
LOG(ERROR) << __func__ << ": JamesDSPAIDLContext::handleCommand failed: " << status;
173+
mContext = nullptr;
174+
return mContext;
175+
}
176+
if (ret < 0) {
177+
LOG(ERROR) << __func__ << ": JamesDSPAIDLContext::handleCommand failed (internal): " << ret;
178+
mContext = nullptr;
179+
return mContext;
180+
}
181+
}
182+
183+
return mContext;
184+
}
185+
186+
ndk::ScopedAStatus JamesDSPAIDL::commandImpl(CommandId command) {
187+
RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext");
188+
int32_t ret = 0;
189+
uint32_t ret_size = sizeof(ret);
190+
switch (command) {
191+
case CommandId::START:
192+
RETURN_IF(mContext->handleCommand(EFFECT_CMD_ENABLE, 0, NULL, &ret_size, &ret) != 0, EX_ILLEGAL_ARGUMENT, "handleCommandFailed");
193+
RETURN_IF(ret != 0, EX_ILLEGAL_ARGUMENT, "handleCommandInternalFailed");
194+
break;
195+
case CommandId::STOP:
196+
RETURN_IF(mContext->handleCommand(EFFECT_CMD_DISABLE, 0, NULL, &ret_size, &ret) != 0, EX_ILLEGAL_ARGUMENT, "handleCommandFailed");
197+
RETURN_IF(ret != 0, EX_ILLEGAL_ARGUMENT, "handleCommandInternalFailed");
198+
break;
199+
case CommandId::RESET:
200+
mImplContext->resetBuffer();
201+
break;
202+
default:
203+
break;
204+
}
205+
return ndk::ScopedAStatus::ok();
206+
}
207+
208+
209+
RetCode JamesDSPAIDL::releaseContext() {
210+
if (mContext) {
211+
int32_t ret = 0;
212+
uint32_t ret_size = sizeof(ret);
213+
int32_t status = mContext->handleCommand(EFFECT_CMD_RESET, 0, NULL, &ret_size, &ret);
214+
if (status < 0) {
215+
LOG(ERROR) << __func__ << ": JamesDSPAIDLContext::handleCommand failed: " << status;
216+
return RetCode::ERROR_ILLEGAL_PARAMETER;
217+
}
218+
if (ret < 0) {
219+
LOG(ERROR) << __func__ << ": JamesDSPAIDLContext::handleCommand failed (internal): " << ret;
220+
return RetCode::ERROR_ILLEGAL_PARAMETER;
221+
}
222+
mContext.reset();
223+
}
224+
return RetCode::SUCCESS;
225+
}
226+
227+
// Processing method running in EffectWorker thread.
228+
IEffect::Status JamesDSPAIDL::effectProcessImpl(float* in_, float* out_, int samples) {
229+
audio_buffer_t in{static_cast<size_t>(samples), {in_}}, out{static_cast<size_t>(samples), {out_}};
230+
LOG(DEBUG) << __func__ << " in " << in_ << " out " << out_ << " samples " << samples;
231+
232+
switch(mContext->process(&in, &out)) {
233+
case 0:
234+
return {STATUS_OK, samples, samples};
235+
case -ENODATA:
236+
return {STATUS_NOT_ENOUGH_DATA, 0, 0};
237+
default:
238+
return {STATUS_INVALID_OPERATION, 0, 0};
239+
}
240+
}
241+
242+
} // namespace aidl::android::hardware::audio::effect
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright (C) 2022 The Android Open Source Project
3+
* 2024 anonymix007
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#pragma once
19+
20+
#include <aidl/android/hardware/audio/effect/BnEffect.h>
21+
#include <fmq/AidlMessageQueue.h>
22+
#include <cstdlib>
23+
#include <memory>
24+
25+
#include "effect-impl/EffectImpl.h"
26+
27+
#include "jdsp_impl.h"
28+
29+
namespace aidl::android::hardware::audio::effect {
30+
31+
class JamesDSPAIDLContext final : public EffectContext {
32+
public:
33+
JamesDSPAIDLContext(int statusDepth, const Parameter::Common& common)
34+
: EffectContext(statusDepth, common),
35+
e(std::make_unique<EffectDSPMain>()) {
36+
LOG(DEBUG) << __func__;
37+
EffectDSPMainConstructor(e.get());
38+
}
39+
~JamesDSPAIDLContext() {
40+
LOG(DEBUG) << __func__;
41+
EffectDSPMainDestructor(e.get());
42+
}
43+
44+
int32_t handleCommand(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize, void* pReplyData) {
45+
return EffectDSPMainCommand(e.get(), cmdCode, cmdSize, pCmdData, replySize, pReplyData);
46+
}
47+
48+
int32_t process(audio_buffer_t *in, audio_buffer_t *out) {
49+
return EffectDSPMainProcess(e.get(), in, out);
50+
}
51+
52+
private:
53+
std::unique_ptr<EffectDSPMain> e;
54+
};
55+
56+
class JamesDSPAIDL final : public EffectImpl {
57+
public:
58+
static const std::string kEffectName;
59+
static const Capability kEqCap;
60+
static const Descriptor kDesc;
61+
62+
JamesDSPAIDL() { LOG(DEBUG) << __func__; }
63+
~JamesDSPAIDL() {
64+
cleanUp();
65+
LOG(DEBUG) << __func__;
66+
}
67+
68+
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
69+
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
70+
REQUIRES(mImplMutex) override;
71+
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
72+
REQUIRES(mImplMutex) override;
73+
74+
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
75+
REQUIRES(mImplMutex) override;
76+
ndk::ScopedAStatus commandImpl(CommandId id) REQUIRES(mImplMutex);
77+
78+
RetCode releaseContext() REQUIRES(mImplMutex) override;
79+
80+
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
81+
REQUIRES(mImplMutex) override;
82+
std::string getEffectName() override { return kEffectName; }
83+
84+
private:
85+
std::shared_ptr<JamesDSPAIDLContext> mContext;
86+
};
87+
88+
constexpr char kEffectTypeUuidJDSP[] = "f27317f4-c984-4de6-9a90-545759495bf2";
89+
inline const AudioUuid& getEffectTypeUuidJDSP() {
90+
static const ::android::base::NoDestructor<AudioUuid> uuid(stringToUuid(kEffectTypeUuidJDSP));
91+
return *uuid;
92+
}
93+
94+
constexpr char kEffectImplUuidJDSP[] = "f27317f4-c984-4de6-9a90-545759495bf2";
95+
inline const AudioUuid& getEffectImplUuidJDSP() {
96+
static const ::android::base::NoDestructor<AudioUuid> uuid(stringToUuid(kEffectImplUuidJDSP));
97+
return *uuid;
98+
}
99+
100+
} // namespace aidl::android::hardware::audio::effect

0 commit comments

Comments
 (0)