A mechanism for handling vendor parameters of the Core Audio HAL is introduced. It is realized by means of a system side interface 'IHalAdapterVendorExtension' which can be implemented by the vendor in order to provide bidirectional translation between raw key-value pairs and structured VendorParameter parcelables. If an instance of 'IHalAdapterVendorExtension' is provided (for example, via a system ext partition), the audio framework will use it in order to process parameters that do not map to methods and fields of AOSP Core Audio HAL interfaces, and call 'IModule|IStreamCommon.get|setVendorParameters'. Bug: 274433842 Bug: 278976019 Test: atest CoreAudioHalAidlTest Change-Id: I8e77238d85cfa91bd7b53e20ad42bd195160fb04
126 lines
5.4 KiB
C++
126 lines
5.4 KiB
C++
/*
|
|
* Copyright (C) 2023 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "ConversionHelperAidl"
|
|
|
|
#include <memory>
|
|
|
|
#include <media/AidlConversionUtil.h>
|
|
#include <utils/Log.h>
|
|
|
|
#include "ConversionHelperAidl.h"
|
|
|
|
using aidl::android::aidl_utils::statusTFromBinderStatus;
|
|
using aidl::android::hardware::audio::core::VendorParameter;
|
|
using aidl::android::media::audio::IHalAdapterVendorExtension;
|
|
|
|
namespace android {
|
|
|
|
status_t parseAndGetVendorParameters(
|
|
std::shared_ptr<IHalAdapterVendorExtension> vendorExt,
|
|
const VendorParametersRecipient& recipient,
|
|
const AudioParameter& parameterKeys,
|
|
String8* values) {
|
|
using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
|
|
if (parameterKeys.size() == 0) return OK;
|
|
const String8 rawKeys = parameterKeys.keysToString();
|
|
if (vendorExt == nullptr) {
|
|
ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeys.c_str());
|
|
return OK;
|
|
}
|
|
|
|
std::vector<std::string> parameterIds;
|
|
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameterIds(
|
|
ParameterScope(recipient.index()),
|
|
std::string(rawKeys.c_str()), ¶meterIds)));
|
|
if (parameterIds.empty()) return OK;
|
|
|
|
std::vector<VendorParameter> parameters;
|
|
if (recipient.index() == static_cast<int>(ParameterScope::MODULE)) {
|
|
auto module = std::get<static_cast<int>(ParameterScope::MODULE)>(recipient);
|
|
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->getVendorParameters(
|
|
parameterIds, ¶meters)));
|
|
} else if (recipient.index() == static_cast<int>(ParameterScope::STREAM)) {
|
|
auto stream = std::get<static_cast<int>(ParameterScope::STREAM)>(recipient);
|
|
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->getVendorParameters(
|
|
parameterIds, ¶meters)));
|
|
} else {
|
|
LOG_ALWAYS_FATAL("%s: unexpected recipient variant index: %zu",
|
|
__func__, recipient.index());
|
|
}
|
|
if (!parameters.empty()) {
|
|
std::string vendorParameters;
|
|
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->processVendorParameters(
|
|
ParameterScope(recipient.index()),
|
|
parameters, &vendorParameters)));
|
|
// Re-parse the vendor-provided string to ensure that it is correct.
|
|
AudioParameter reparse(String8(vendorParameters.c_str()));
|
|
if (reparse.size() != 0) {
|
|
if (!values->empty()) {
|
|
values->append(";");
|
|
}
|
|
values->append(reparse.toString().c_str());
|
|
}
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
status_t parseAndSetVendorParameters(
|
|
std::shared_ptr<IHalAdapterVendorExtension> vendorExt,
|
|
const VendorParametersRecipient& recipient,
|
|
const AudioParameter& parameters) {
|
|
using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
|
|
if (parameters.size() == 0) return OK;
|
|
const String8 rawKeysAndValues = parameters.toString();
|
|
if (vendorExt == nullptr) {
|
|
ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeysAndValues.c_str());
|
|
return OK;
|
|
}
|
|
|
|
std::vector<VendorParameter> syncParameters, asyncParameters;
|
|
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameters(
|
|
ParameterScope(recipient.index()),
|
|
std::string(rawKeysAndValues.c_str()),
|
|
&syncParameters, &asyncParameters)));
|
|
if (recipient.index() == static_cast<int>(ParameterScope::MODULE)) {
|
|
auto module = std::get<static_cast<int>(ParameterScope::MODULE)>(recipient);
|
|
if (!syncParameters.empty()) {
|
|
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->setVendorParameters(
|
|
syncParameters, false /*async*/)));
|
|
}
|
|
if (!asyncParameters.empty()) {
|
|
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->setVendorParameters(
|
|
asyncParameters, true /*async*/)));
|
|
}
|
|
} else if (recipient.index() == static_cast<int>(ParameterScope::STREAM)) {
|
|
auto stream = std::get<static_cast<int>(ParameterScope::STREAM)>(recipient);
|
|
if (!syncParameters.empty()) {
|
|
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->setVendorParameters(
|
|
syncParameters, false /*async*/)));
|
|
}
|
|
if (!asyncParameters.empty()) {
|
|
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->setVendorParameters(
|
|
asyncParameters, true /*async*/)));
|
|
}
|
|
} else {
|
|
LOG_ALWAYS_FATAL("%s: unexpected recipient variant index: %zu",
|
|
__func__, recipient.index());
|
|
}
|
|
return OK;
|
|
}
|
|
|
|
} // namespace android
|