xref: /aosp_15_r20/frameworks/av/media/libaudiohal/FactoryHal.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #include <map>
18*ec779b8eSAndroid Build Coastguard Worker #include <memory>
19*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "FactoryHal"
20*ec779b8eSAndroid Build Coastguard Worker 
21*ec779b8eSAndroid Build Coastguard Worker #include <algorithm>
22*ec779b8eSAndroid Build Coastguard Worker #include <array>
23*ec779b8eSAndroid Build Coastguard Worker #include <cstddef>
24*ec779b8eSAndroid Build Coastguard Worker #include <dlfcn.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <utility>
26*ec779b8eSAndroid Build Coastguard Worker 
27*ec779b8eSAndroid Build Coastguard Worker #include <android/binder_manager.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <android/hidl/manager/1.0/IServiceManager.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <hidl/ServiceManagement.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <hidl/Status.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
32*ec779b8eSAndroid Build Coastguard Worker 
33*ec779b8eSAndroid Build Coastguard Worker #include "include/media/audiohal/AudioHalVersionInfo.h"
34*ec779b8eSAndroid Build Coastguard Worker #include "include/media/audiohal/FactoryHal.h"
35*ec779b8eSAndroid Build Coastguard Worker 
36*ec779b8eSAndroid Build Coastguard Worker namespace android::detail {
37*ec779b8eSAndroid Build Coastguard Worker 
38*ec779b8eSAndroid Build Coastguard Worker namespace {
39*ec779b8eSAndroid Build Coastguard Worker 
40*ec779b8eSAndroid Build Coastguard Worker using ::android::detail::AudioHalVersionInfo;
41*ec779b8eSAndroid Build Coastguard Worker 
42*ec779b8eSAndroid Build Coastguard Worker // The pair of the interface's package name and the interface name,
43*ec779b8eSAndroid Build Coastguard Worker // e.g. <"android.hardware.audio", "IDevicesFactory"> for HIDL, <"android.hardware.audio.core",
44*ec779b8eSAndroid Build Coastguard Worker // "IModule"> for AIDL.
45*ec779b8eSAndroid Build Coastguard Worker // Splitting is used for easier construction of versioned names (FQNs).
46*ec779b8eSAndroid Build Coastguard Worker using InterfaceName = std::pair<std::string, std::string>;
47*ec779b8eSAndroid Build Coastguard Worker 
48*ec779b8eSAndroid Build Coastguard Worker /**
49*ec779b8eSAndroid Build Coastguard Worker  * Supported HAL versions, from most recent to least recent.
50*ec779b8eSAndroid Build Coastguard Worker  * This list need to keep sync with AudioHalVersionInfo.VERSIONS in
51*ec779b8eSAndroid Build Coastguard Worker  * media/java/android/media/AudioHalVersionInfo.java.
52*ec779b8eSAndroid Build Coastguard Worker  */
53*ec779b8eSAndroid Build Coastguard Worker static const std::array<AudioHalVersionInfo, 4> sAudioHALVersions = {
54*ec779b8eSAndroid Build Coastguard Worker     AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, 1, 0),
55*ec779b8eSAndroid Build Coastguard Worker     AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 1),
56*ec779b8eSAndroid Build Coastguard Worker     AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 0),
57*ec779b8eSAndroid Build Coastguard Worker     AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0),
58*ec779b8eSAndroid Build Coastguard Worker };
59*ec779b8eSAndroid Build Coastguard Worker 
60*ec779b8eSAndroid Build Coastguard Worker static const std::map<AudioHalVersionInfo::Type, InterfaceName> sDevicesHALInterfaces = {
61*ec779b8eSAndroid Build Coastguard Worker         {AudioHalVersionInfo::Type::AIDL, std::make_pair("android.hardware.audio.core", "IModule")},
62*ec779b8eSAndroid Build Coastguard Worker         {AudioHalVersionInfo::Type::HIDL,
63*ec779b8eSAndroid Build Coastguard Worker          std::make_pair("android.hardware.audio", "IDevicesFactory")},
64*ec779b8eSAndroid Build Coastguard Worker };
65*ec779b8eSAndroid Build Coastguard Worker 
66*ec779b8eSAndroid Build Coastguard Worker static const std::map<AudioHalVersionInfo::Type, InterfaceName> sEffectsHALInterfaces = {
67*ec779b8eSAndroid Build Coastguard Worker         {AudioHalVersionInfo::Type::AIDL,
68*ec779b8eSAndroid Build Coastguard Worker          std::make_pair("android.hardware.audio.effect", "IFactory")},
69*ec779b8eSAndroid Build Coastguard Worker         {AudioHalVersionInfo::Type::HIDL,
70*ec779b8eSAndroid Build Coastguard Worker          std::make_pair("android.hardware.audio.effect", "IEffectsFactory")},
71*ec779b8eSAndroid Build Coastguard Worker };
72*ec779b8eSAndroid Build Coastguard Worker 
createHalService(const AudioHalVersionInfo & version,bool isDevice,void ** rawInterface)73*ec779b8eSAndroid Build Coastguard Worker bool createHalService(const AudioHalVersionInfo& version, bool isDevice, void** rawInterface) {
74*ec779b8eSAndroid Build Coastguard Worker     const std::string libName = "libaudiohal@" + version.toVersionString() + ".so";
75*ec779b8eSAndroid Build Coastguard Worker     const std::string factoryFunctionName =
76*ec779b8eSAndroid Build Coastguard Worker             isDevice ? "createIDevicesFactory" : "createIEffectsFactory";
77*ec779b8eSAndroid Build Coastguard Worker     constexpr int dlMode = RTLD_LAZY;
78*ec779b8eSAndroid Build Coastguard Worker     void* handle = nullptr;
79*ec779b8eSAndroid Build Coastguard Worker     dlerror(); // clear
80*ec779b8eSAndroid Build Coastguard Worker     handle = dlopen(libName.c_str(), dlMode);
81*ec779b8eSAndroid Build Coastguard Worker     if (handle == nullptr) {
82*ec779b8eSAndroid Build Coastguard Worker         const char* error = dlerror();
83*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Failed to dlopen %s: %s", libName.c_str(),
84*ec779b8eSAndroid Build Coastguard Worker                 error != nullptr ? error : "unknown error");
85*ec779b8eSAndroid Build Coastguard Worker         return false;
86*ec779b8eSAndroid Build Coastguard Worker     }
87*ec779b8eSAndroid Build Coastguard Worker     void* (*factoryFunction)();
88*ec779b8eSAndroid Build Coastguard Worker     *(void **)(&factoryFunction) = dlsym(handle, factoryFunctionName.c_str());
89*ec779b8eSAndroid Build Coastguard Worker     if (!factoryFunction) {
90*ec779b8eSAndroid Build Coastguard Worker         const char* error = dlerror();
91*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Factory function %s not found in library %s: %s",
92*ec779b8eSAndroid Build Coastguard Worker                 factoryFunctionName.c_str(), libName.c_str(),
93*ec779b8eSAndroid Build Coastguard Worker                 error != nullptr ? error : "unknown error");
94*ec779b8eSAndroid Build Coastguard Worker         dlclose(handle);
95*ec779b8eSAndroid Build Coastguard Worker         return false;
96*ec779b8eSAndroid Build Coastguard Worker     }
97*ec779b8eSAndroid Build Coastguard Worker     *rawInterface = (*factoryFunction)();
98*ec779b8eSAndroid Build Coastguard Worker     ALOGW_IF(!*rawInterface, "Factory function %s from %s returned nullptr",
99*ec779b8eSAndroid Build Coastguard Worker             factoryFunctionName.c_str(), libName.c_str());
100*ec779b8eSAndroid Build Coastguard Worker     return true;
101*ec779b8eSAndroid Build Coastguard Worker }
102*ec779b8eSAndroid Build Coastguard Worker 
hasAidlHalService(const InterfaceName & interface,const AudioHalVersionInfo & version)103*ec779b8eSAndroid Build Coastguard Worker bool hasAidlHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
104*ec779b8eSAndroid Build Coastguard Worker     const std::string name = interface.first + "." + interface.second + "/default";
105*ec779b8eSAndroid Build Coastguard Worker     const bool isDeclared = AServiceManager_isDeclared(name.c_str());
106*ec779b8eSAndroid Build Coastguard Worker     if (!isDeclared) {
107*ec779b8eSAndroid Build Coastguard Worker         ALOGW("%s %s: false", __func__, name.c_str());
108*ec779b8eSAndroid Build Coastguard Worker         return false;
109*ec779b8eSAndroid Build Coastguard Worker     }
110*ec779b8eSAndroid Build Coastguard Worker     ALOGI("%s %s: true, version %s", __func__, name.c_str(), version.toString().c_str());
111*ec779b8eSAndroid Build Coastguard Worker     return true;
112*ec779b8eSAndroid Build Coastguard Worker }
113*ec779b8eSAndroid Build Coastguard Worker 
hasHidlHalService(const InterfaceName & interface,const AudioHalVersionInfo & version)114*ec779b8eSAndroid Build Coastguard Worker bool hasHidlHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
115*ec779b8eSAndroid Build Coastguard Worker     using ::android::hidl::manager::V1_0::IServiceManager;
116*ec779b8eSAndroid Build Coastguard Worker     sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
117*ec779b8eSAndroid Build Coastguard Worker     if (!sm) {
118*ec779b8eSAndroid Build Coastguard Worker         ALOGW("Failed to obtain HIDL ServiceManager");
119*ec779b8eSAndroid Build Coastguard Worker         return false;
120*ec779b8eSAndroid Build Coastguard Worker     }
121*ec779b8eSAndroid Build Coastguard Worker     // Since audio HAL doesn't support multiple clients, avoid instantiating
122*ec779b8eSAndroid Build Coastguard Worker     // the interface right away. Instead, query the transport type for it.
123*ec779b8eSAndroid Build Coastguard Worker     using ::android::hardware::Return;
124*ec779b8eSAndroid Build Coastguard Worker     using Transport = IServiceManager::Transport;
125*ec779b8eSAndroid Build Coastguard Worker     const std::string fqName =
126*ec779b8eSAndroid Build Coastguard Worker             interface.first + "@" + version.toVersionString() + "::" + interface.second;
127*ec779b8eSAndroid Build Coastguard Worker     const std::string instance = "default";
128*ec779b8eSAndroid Build Coastguard Worker     Return<Transport> transport = sm->getTransport(fqName, instance);
129*ec779b8eSAndroid Build Coastguard Worker     if (!transport.isOk()) {
130*ec779b8eSAndroid Build Coastguard Worker         ALOGW("Failed to obtain transport type for %s/%s: %s",
131*ec779b8eSAndroid Build Coastguard Worker               fqName.c_str(), instance.c_str(), transport.description().c_str());
132*ec779b8eSAndroid Build Coastguard Worker         return false;
133*ec779b8eSAndroid Build Coastguard Worker     }
134*ec779b8eSAndroid Build Coastguard Worker     return transport != Transport::EMPTY;
135*ec779b8eSAndroid Build Coastguard Worker }
136*ec779b8eSAndroid Build Coastguard Worker 
hasHalService(const InterfaceName & interface,const AudioHalVersionInfo & version)137*ec779b8eSAndroid Build Coastguard Worker bool hasHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
138*ec779b8eSAndroid Build Coastguard Worker     auto halType = version.getType();
139*ec779b8eSAndroid Build Coastguard Worker     if (halType == AudioHalVersionInfo::Type::AIDL) {
140*ec779b8eSAndroid Build Coastguard Worker         return hasAidlHalService(interface, version);
141*ec779b8eSAndroid Build Coastguard Worker     } else if (halType == AudioHalVersionInfo::Type::HIDL) {
142*ec779b8eSAndroid Build Coastguard Worker         return hasHidlHalService(interface, version);
143*ec779b8eSAndroid Build Coastguard Worker     } else {
144*ec779b8eSAndroid Build Coastguard Worker         ALOGE("HalType not supported %s", version.toString().c_str());
145*ec779b8eSAndroid Build Coastguard Worker         return false;
146*ec779b8eSAndroid Build Coastguard Worker     }
147*ec779b8eSAndroid Build Coastguard Worker }
148*ec779b8eSAndroid Build Coastguard Worker 
149*ec779b8eSAndroid Build Coastguard Worker }  // namespace
150*ec779b8eSAndroid Build Coastguard Worker 
createPreferredImpl(bool isDevice)151*ec779b8eSAndroid Build Coastguard Worker void *createPreferredImpl(bool isDevice) {
152*ec779b8eSAndroid Build Coastguard Worker     auto findMostRecentVersion = [](const auto& iMap) {
153*ec779b8eSAndroid Build Coastguard Worker         return std::find_if(sAudioHALVersions.begin(), sAudioHALVersions.end(),
154*ec779b8eSAndroid Build Coastguard Worker                             [iMap](const auto& v) {
155*ec779b8eSAndroid Build Coastguard Worker                                 auto iface = iMap.find(v.getType());
156*ec779b8eSAndroid Build Coastguard Worker                                 return hasHalService(iface->second, v);
157*ec779b8eSAndroid Build Coastguard Worker                             });
158*ec779b8eSAndroid Build Coastguard Worker     };
159*ec779b8eSAndroid Build Coastguard Worker 
160*ec779b8eSAndroid Build Coastguard Worker     auto interfaceMap = isDevice ? sDevicesHALInterfaces : sEffectsHALInterfaces;
161*ec779b8eSAndroid Build Coastguard Worker     auto siblingInterfaceMap = isDevice ? sEffectsHALInterfaces : sDevicesHALInterfaces;
162*ec779b8eSAndroid Build Coastguard Worker     auto ifaceVersionIt = findMostRecentVersion(interfaceMap);
163*ec779b8eSAndroid Build Coastguard Worker     auto siblingVersionIt = findMostRecentVersion(siblingInterfaceMap);
164*ec779b8eSAndroid Build Coastguard Worker     if (ifaceVersionIt != sAudioHALVersions.end() && siblingVersionIt != sAudioHALVersions.end() &&
165*ec779b8eSAndroid Build Coastguard Worker         // same HAL type (HIDL/AIDL) and same major version
166*ec779b8eSAndroid Build Coastguard Worker         ifaceVersionIt->getType() == siblingVersionIt->getType() &&
167*ec779b8eSAndroid Build Coastguard Worker         ifaceVersionIt->getMajorVersion() == siblingVersionIt->getMajorVersion()) {
168*ec779b8eSAndroid Build Coastguard Worker         void* rawInterface;
169*ec779b8eSAndroid Build Coastguard Worker         if (createHalService(std::max(*ifaceVersionIt, *siblingVersionIt), isDevice,
170*ec779b8eSAndroid Build Coastguard Worker                              &rawInterface)) {
171*ec779b8eSAndroid Build Coastguard Worker             return rawInterface;
172*ec779b8eSAndroid Build Coastguard Worker         } else {
173*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Failed to create HAL services with major %s, sibling %s!",
174*ec779b8eSAndroid Build Coastguard Worker                   ifaceVersionIt->toString().c_str(), siblingVersionIt->toString().c_str());
175*ec779b8eSAndroid Build Coastguard Worker         }
176*ec779b8eSAndroid Build Coastguard Worker     } else {
177*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Found no HAL version, main(%s) %s %s!", isDevice ? "Device" : "Effect",
178*ec779b8eSAndroid Build Coastguard Worker               (ifaceVersionIt == sAudioHALVersions.end()) ? "null"
179*ec779b8eSAndroid Build Coastguard Worker                                                           : ifaceVersionIt->toString().c_str(),
180*ec779b8eSAndroid Build Coastguard Worker               (siblingVersionIt == sAudioHALVersions.end()) ? "null"
181*ec779b8eSAndroid Build Coastguard Worker                                                             : siblingVersionIt->toString().c_str());
182*ec779b8eSAndroid Build Coastguard Worker     }
183*ec779b8eSAndroid Build Coastguard Worker     return nullptr;
184*ec779b8eSAndroid Build Coastguard Worker }
185*ec779b8eSAndroid Build Coastguard Worker 
186*ec779b8eSAndroid Build Coastguard Worker }  // namespace android::detail
187