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, 5> 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 AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 5, 0),
59 };
60
61 static const std::map<AudioHalVersionInfo::Type, InterfaceName> sDevicesHALInterfaces = {
62 {AudioHalVersionInfo::Type::AIDL, std::make_pair("android.hardware.audio.core", "IModule")},
63 {AudioHalVersionInfo::Type::HIDL,
64 std::make_pair("android.hardware.audio", "IDevicesFactory")},
65 };
66
67 static const std::map<AudioHalVersionInfo::Type, InterfaceName> sEffectsHALInterfaces = {
68 {AudioHalVersionInfo::Type::AIDL,
69 std::make_pair("android.hardware.audio.effect", "IFactory")},
70 {AudioHalVersionInfo::Type::HIDL,
71 std::make_pair("android.hardware.audio.effect", "IEffectsFactory")},
72 };
73
createHalService(const AudioHalVersionInfo & version,bool isDevice,void ** rawInterface)74 bool createHalService(const AudioHalVersionInfo& version, bool isDevice, void** rawInterface) {
75 const std::string libName = "libaudiohal@" + version.toVersionString() + ".so";
76 const std::string factoryFunctionName =
77 isDevice ? "createIDevicesFactory" : "createIEffectsFactory";
78 constexpr int dlMode = RTLD_LAZY;
79 void* handle = nullptr;
80 dlerror(); // clear
81 handle = dlopen(libName.c_str(), dlMode);
82 if (handle == nullptr) {
83 const char* error = dlerror();
84 ALOGE("Failed to dlopen %s: %s", libName.c_str(),
85 error != nullptr ? error : "unknown error");
86 return false;
87 }
88 void* (*factoryFunction)();
89 *(void **)(&factoryFunction) = dlsym(handle, factoryFunctionName.c_str());
90 if (!factoryFunction) {
91 const char* error = dlerror();
92 ALOGE("Factory function %s not found in library %s: %s",
93 factoryFunctionName.c_str(), libName.c_str(),
94 error != nullptr ? error : "unknown error");
95 dlclose(handle);
96 return false;
97 }
98 *rawInterface = (*factoryFunction)();
99 ALOGW_IF(!*rawInterface, "Factory function %s from %s returned nullptr",
100 factoryFunctionName.c_str(), libName.c_str());
101 return true;
102 }
103
hasAidlHalService(const InterfaceName & interface,const AudioHalVersionInfo & version)104 bool hasAidlHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
105 const std::string name = interface.first + "." + interface.second + "/default";
106 const bool isDeclared = AServiceManager_isDeclared(name.c_str());
107 if (!isDeclared) {
108 ALOGW("%s %s: false", __func__, name.c_str());
109 return false;
110 }
111 ALOGI("%s %s: true, version %s", __func__, name.c_str(), version.toString().c_str());
112 return true;
113 }
114
hasHidlHalService(const InterfaceName & interface,const AudioHalVersionInfo & version)115 bool hasHidlHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
116 using ::android::hidl::manager::V1_0::IServiceManager;
117 sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
118 if (!sm) {
119 ALOGW("Failed to obtain HIDL ServiceManager");
120 return false;
121 }
122 // Since audio HAL doesn't support multiple clients, avoid instantiating
123 // the interface right away. Instead, query the transport type for it.
124 using ::android::hardware::Return;
125 using Transport = IServiceManager::Transport;
126 const std::string fqName =
127 interface.first + "@" + version.toVersionString() + "::" + interface.second;
128 const std::string instance = "default";
129 Return<Transport> transport = sm->getTransport(fqName, instance);
130 if (!transport.isOk()) {
131 ALOGW("Failed to obtain transport type for %s/%s: %s",
132 fqName.c_str(), instance.c_str(), transport.description().c_str());
133 return false;
134 }
135 return transport != Transport::EMPTY;
136 }
137
hasHalService(const InterfaceName & interface,const AudioHalVersionInfo & version)138 bool hasHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
139 auto halType = version.getType();
140 if (halType == AudioHalVersionInfo::Type::AIDL) {
141 return hasAidlHalService(interface, version);
142 } else if (halType == AudioHalVersionInfo::Type::HIDL) {
143 return hasHidlHalService(interface, version);
144 } else {
145 ALOGE("HalType not supported %s", version.toString().c_str());
146 return false;
147 }
148 }
149
150 } // namespace
151
createPreferredImpl(bool isDevice)152 void *createPreferredImpl(bool isDevice) {
153 auto findMostRecentVersion = [](const auto& iMap) {
154 return std::find_if(sAudioHALVersions.begin(), sAudioHALVersions.end(),
155 [iMap](const auto& v) {
156 auto iface = iMap.find(v.getType());
157 return hasHalService(iface->second, v);
158 });
159 };
160
161 auto interfaceMap = isDevice ? sDevicesHALInterfaces : sEffectsHALInterfaces;
162 auto siblingInterfaceMap = isDevice ? sEffectsHALInterfaces : sDevicesHALInterfaces;
163 auto ifaceVersionIt = findMostRecentVersion(interfaceMap);
164 auto siblingVersionIt = findMostRecentVersion(siblingInterfaceMap);
165 if (ifaceVersionIt != sAudioHALVersions.end() && siblingVersionIt != sAudioHALVersions.end() &&
166 // same HAL type (HIDL/AIDL) and same major version
167 ifaceVersionIt->getType() == siblingVersionIt->getType() &&
168 ifaceVersionIt->getMajorVersion() == siblingVersionIt->getMajorVersion()) {
169 void* rawInterface;
170 if (createHalService(std::max(*ifaceVersionIt, *siblingVersionIt), isDevice,
171 &rawInterface)) {
172 return rawInterface;
173 } else {
174 ALOGE("Failed to create HAL services with major %s, sibling %s!",
175 ifaceVersionIt->toString().c_str(), siblingVersionIt->toString().c_str());
176 }
177 } else {
178 ALOGE("Found no HAL version, main(%s) %s %s!", isDevice ? "Device" : "Effect",
179 (ifaceVersionIt == sAudioHALVersions.end()) ? "null"
180 : ifaceVersionIt->toString().c_str(),
181 (siblingVersionIt == sAudioHALVersions.end()) ? "null"
182 : siblingVersionIt->toString().c_str());
183 }
184 return nullptr;
185 }
186
187 } // namespace android::detail
188