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