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