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
185 lines
7.2 KiB
C++
185 lines
7.2 KiB
C++
/*
|
|
* Copyright (C) 2022 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.
|
|
*/
|
|
|
|
#include <memory>
|
|
|
|
#define LOG_TAG "DevicesFactoryHalAidl"
|
|
//#define LOG_NDEBUG 0
|
|
|
|
#include <aidl/android/hardware/audio/core/IModule.h>
|
|
#include <android/binder_manager.h>
|
|
#include <binder/IServiceManager.h>
|
|
#include <media/AidlConversionNdkCpp.h>
|
|
#include <media/AidlConversionUtil.h>
|
|
#include <utils/Log.h>
|
|
|
|
#include "DeviceHalAidl.h"
|
|
#include "DevicesFactoryHalAidl.h"
|
|
|
|
using aidl::android::aidl_utils::statusTFromBinderStatus;
|
|
using aidl::android::hardware::audio::core::IConfig;
|
|
using aidl::android::hardware::audio::core::IModule;
|
|
using aidl::android::hardware::audio::core::SurroundSoundConfig;
|
|
using aidl::android::media::audio::common::AudioHalEngineConfig;
|
|
using aidl::android::media::audio::IHalAdapterVendorExtension;
|
|
using android::detail::AudioHalVersionInfo;
|
|
|
|
namespace android {
|
|
|
|
namespace {
|
|
|
|
ConversionResult<media::SurroundSoundConfig::SurroundFormatFamily>
|
|
ndk2cpp_SurroundSoundConfigFormatFamily(const SurroundSoundConfig::SurroundFormatFamily& ndk) {
|
|
media::SurroundSoundConfig::SurroundFormatFamily cpp;
|
|
cpp.primaryFormat = VALUE_OR_RETURN(ndk2cpp_AudioFormatDescription(ndk.primaryFormat));
|
|
cpp.subFormats = VALUE_OR_RETURN(::aidl::android::convertContainer<std::vector<
|
|
media::audio::common::AudioFormatDescription>>(ndk.subFormats,
|
|
ndk2cpp_AudioFormatDescription));
|
|
return cpp;
|
|
}
|
|
|
|
ConversionResult<media::SurroundSoundConfig>
|
|
ndk2cpp_SurroundSoundConfig(const SurroundSoundConfig& ndk) {
|
|
media::SurroundSoundConfig cpp;
|
|
cpp.formatFamilies = VALUE_OR_RETURN(::aidl::android::convertContainer<std::vector<
|
|
media::SurroundSoundConfig::SurroundFormatFamily>>(ndk.formatFamilies,
|
|
ndk2cpp_SurroundSoundConfigFormatFamily));
|
|
return cpp;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
DevicesFactoryHalAidl::DevicesFactoryHalAidl(std::shared_ptr<IConfig> config)
|
|
: mConfig(std::move(config)) {
|
|
}
|
|
|
|
status_t DevicesFactoryHalAidl::getDeviceNames(std::vector<std::string> *names) {
|
|
if (names == nullptr) {
|
|
return BAD_VALUE;
|
|
}
|
|
AServiceManager_forEachDeclaredInstance(IModule::descriptor, static_cast<void*>(names),
|
|
[](const char* instance, void* context) {
|
|
if (strcmp(instance, "default") == 0) instance = "primary";
|
|
static_cast<decltype(names)>(context)->push_back(instance);
|
|
});
|
|
return OK;
|
|
}
|
|
|
|
// Opens a device with the specified name. To close the device, it is
|
|
// necessary to release references to the returned object.
|
|
status_t DevicesFactoryHalAidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
|
|
if (name == nullptr || device == nullptr) {
|
|
return BAD_VALUE;
|
|
}
|
|
std::shared_ptr<IModule> service;
|
|
if (strcmp(name, "primary") == 0) name = "default";
|
|
auto serviceName = std::string(IModule::descriptor) + "/" + name;
|
|
service = IModule::fromBinder(
|
|
ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
|
|
if (service == nullptr) {
|
|
ALOGE("%s fromBinder %s failed", __func__, serviceName.c_str());
|
|
return NO_INIT;
|
|
}
|
|
*device = sp<DeviceHalAidl>::make(name, service, getVendorExtension());
|
|
return OK;
|
|
}
|
|
|
|
status_t DevicesFactoryHalAidl::getHalPids(std::vector<pid_t> *pids) {
|
|
if (pids == nullptr) {
|
|
return BAD_VALUE;
|
|
}
|
|
// The functionality for retrieving debug infos of services is not exposed via the NDK.
|
|
sp<IServiceManager> sm = defaultServiceManager();
|
|
if (sm == nullptr) {
|
|
return NO_INIT;
|
|
}
|
|
std::set<pid_t> pidsSet;
|
|
const auto moduleServiceName = std::string(IModule::descriptor) + "/";
|
|
auto debugInfos = sm->getServiceDebugInfo();
|
|
for (const auto& info : debugInfos) {
|
|
if (info.pid > 0 &&
|
|
info.name.size() > moduleServiceName.size() && // '>' as there must be instance name
|
|
info.name.substr(0, moduleServiceName.size()) == moduleServiceName) {
|
|
pidsSet.insert(info.pid);
|
|
}
|
|
}
|
|
*pids = {pidsSet.begin(), pidsSet.end()};
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t DevicesFactoryHalAidl::setCallbackOnce(sp<DevicesFactoryHalCallback> callback) {
|
|
// Dynamic registration of module instances is not supported. The functionality
|
|
// in the audio server which is related to this callback can be removed together
|
|
// with HIDL support.
|
|
ALOG_ASSERT(callback != nullptr);
|
|
if (callback != nullptr) {
|
|
callback->onNewDevicesAvailable();
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
|
|
AudioHalVersionInfo DevicesFactoryHalAidl::getHalVersion() const {
|
|
int32_t versionNumber = 0;
|
|
if (ndk::ScopedAStatus status = mConfig->getInterfaceVersion(&versionNumber); !status.isOk()) {
|
|
ALOGE("%s getInterfaceVersion failed: %s", __func__, status.getDescription().c_str());
|
|
}
|
|
// AIDL does not have minor version, fill 0 for all versions
|
|
return AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, versionNumber);
|
|
}
|
|
|
|
status_t DevicesFactoryHalAidl::getSurroundSoundConfig(media::SurroundSoundConfig *config) {
|
|
SurroundSoundConfig ndkConfig;
|
|
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mConfig->getSurroundSoundConfig(&ndkConfig)));
|
|
*config = VALUE_OR_RETURN_STATUS(ndk2cpp_SurroundSoundConfig(ndkConfig));
|
|
return OK;
|
|
}
|
|
|
|
status_t DevicesFactoryHalAidl::getEngineConfig(
|
|
media::audio::common::AudioHalEngineConfig *config) {
|
|
AudioHalEngineConfig ndkConfig;
|
|
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mConfig->getEngineConfig(&ndkConfig)));
|
|
*config = VALUE_OR_RETURN_STATUS(ndk2cpp_AudioHalEngineConfig(ndkConfig));
|
|
return OK;
|
|
}
|
|
|
|
std::shared_ptr<IHalAdapterVendorExtension> DevicesFactoryHalAidl::getVendorExtension() {
|
|
if (!mVendorExt.has_value()) {
|
|
auto serviceName = std::string(IHalAdapterVendorExtension::descriptor) + "/default";
|
|
if (AServiceManager_isDeclared(serviceName.c_str())) {
|
|
mVendorExt = std::shared_ptr<IHalAdapterVendorExtension>(
|
|
IHalAdapterVendorExtension::fromBinder(ndk::SpAIBinder(
|
|
AServiceManager_waitForService(serviceName.c_str()))));
|
|
} else {
|
|
mVendorExt = nullptr;
|
|
}
|
|
}
|
|
return mVendorExt.value();
|
|
}
|
|
|
|
// Main entry-point to the shared library.
|
|
extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
|
|
auto serviceName = std::string(IConfig::descriptor) + "/default";
|
|
auto service = IConfig::fromBinder(
|
|
ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
|
|
if (!service) {
|
|
ALOGE("%s binder service %s not exist", __func__, serviceName.c_str());
|
|
return nullptr;
|
|
}
|
|
return new DevicesFactoryHalAidl(service);
|
|
}
|
|
|
|
} // namespace android
|