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