1 /* 2 * Copyright (C) 2019 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 #pragma once 18 19 #include <unistd.h> 20 21 #include <map> 22 23 #include <android-base/logging.h> 24 #include <hwbinder/IPCThreadState.h> 25 #include <system/audio.h> 26 27 // clang-format off 28 #include PATH(android/hardware/audio/FILE_VERSION/IDevice.h) 29 #include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h) 30 #include PATH(android/hardware/audio/FILE_VERSION/IPrimaryDevice.h) 31 #include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/types.h) 32 #include PATH(android/hardware/audio/common/COMMON_TYPES_FILE_VERSION/types.h) 33 // clang-format on 34 35 #include "utility/ReturnIn.h" 36 37 using ::android::sp; 38 using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::Result; 39 using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION; 40 using namespace ::android::hardware::audio::common::test::utility; 41 using namespace ::android::hardware::audio::CPP_VERSION; 42 43 template <class Derived, class Key, class Interface> 44 class InterfaceManager { 45 public: getExisting(const Key & name)46 sp<Interface> getExisting(const Key& name) { 47 auto existing = instances.find(name); 48 return existing != instances.end() ? existing->second : sp<Interface>(); 49 } 50 get(const Key & name)51 sp<Interface> get(const Key& name) { 52 auto existing = instances.find(name); 53 if (existing != instances.end()) return existing->second; 54 auto [inserted, _] = instances.emplace(name, Derived::createInterfaceInstance(name)); 55 return inserted->second; 56 } 57 58 // The test must check that reset was successful. Reset failure means that the test code 59 // is holding a strong reference to the device. reset(const Key & name,bool waitForDestruction)60 bool reset(const Key& name, bool waitForDestruction) __attribute__((warn_unused_result)) { 61 auto iter = instances.find(name); 62 if (iter == instances.end()) return true; 63 ::android::wp<Interface> weak = iter->second; 64 instances.erase(iter); 65 if (weak.promote() != nullptr) return false; 66 if (waitForDestruction) { 67 waitForInstanceDestruction(); 68 } 69 return true; 70 } 71 waitForInstanceDestruction()72 static void waitForInstanceDestruction() { 73 // FIXME: there is no way to know when the remote IDevice is being destroyed 74 // Binder does not support testing if an object is alive, thus 75 // wait for 100ms to let the binder destruction propagates and 76 // the remote device has the time to be destroyed. 77 // flushCommand makes sure all local command are sent, thus should reduce 78 // the latency between local and remote destruction. 79 ::android::hardware::IPCThreadState::self()->flushCommands(); 80 usleep(100 * 1000); 81 } 82 83 protected: 84 std::map<Key, sp<Interface>> instances; 85 }; 86 87 class DevicesFactoryManager 88 : public InterfaceManager<DevicesFactoryManager, std::string, IDevicesFactory> { 89 public: getInstance()90 static DevicesFactoryManager& getInstance() { 91 static DevicesFactoryManager instance; 92 return instance; 93 } createInterfaceInstance(const std::string & name)94 static sp<IDevicesFactory> createInterfaceInstance(const std::string& name) { 95 return IDevicesFactory::getService(name); 96 } 97 }; 98 99 namespace impl { 100 101 class PrimaryDeviceManager 102 : public InterfaceManager<PrimaryDeviceManager, std::string, IPrimaryDevice> { 103 public: createInterfaceInstance(const std::string & factoryName)104 static sp<IPrimaryDevice> createInterfaceInstance(const std::string& factoryName) { 105 sp<IDevicesFactory> factory = DevicesFactoryManager::getInstance().get(factoryName); 106 return openPrimaryDevice(factory); 107 } 108 reset(const std::string & factoryName)109 bool reset(const std::string& factoryName) __attribute__((warn_unused_result)) { 110 #if MAJOR_VERSION <= 5 111 return InterfaceManager::reset(factoryName, true); 112 #elif MAJOR_VERSION >= 6 113 { 114 sp<IPrimaryDevice> device = getExisting(factoryName); 115 if (device != nullptr) { 116 auto ret = device->close(); 117 ALOGE_IF(!ret.isOk(), "PrimaryDevice %s close failed: %s", factoryName.c_str(), 118 ret.description().c_str()); 119 } 120 } 121 return InterfaceManager::reset(factoryName, false); 122 #endif 123 } 124 125 private: openPrimaryDevice(const sp<IDevicesFactory> & factory)126 static sp<IPrimaryDevice> openPrimaryDevice(const sp<IDevicesFactory>& factory) { 127 if (factory == nullptr) return {}; 128 Result result; 129 sp<IPrimaryDevice> primaryDevice; 130 #if !(MAJOR_VERSION == 7 && MINOR_VERSION == 1) 131 sp<IDevice> device; 132 #if MAJOR_VERSION == 2 133 auto ret = factory->openDevice(IDevicesFactory::Device::PRIMARY, returnIn(result, device)); 134 if (ret.isOk() && result == Result::OK && device != nullptr) { 135 primaryDevice = IPrimaryDevice::castFrom(device); 136 } 137 #elif MAJOR_VERSION >= 4 138 auto ret = factory->openPrimaryDevice(returnIn(result, device)); 139 if (ret.isOk() && result == Result::OK && device != nullptr) { 140 primaryDevice = IPrimaryDevice::castFrom(device); 141 } 142 #endif 143 if (!ret.isOk() || result != Result::OK || primaryDevice == nullptr) { 144 ALOGW("Primary device can not be opened, transaction: %s, result %d, device %p", 145 ret.description().c_str(), result, device.get()); 146 return nullptr; 147 } 148 #else // V7.1 149 auto ret = factory->openPrimaryDevice_7_1(returnIn(result, primaryDevice)); 150 if (!ret.isOk() || result != Result::OK) { 151 ALOGW("Primary device can not be opened, transaction: %s, result %d", 152 ret.description().c_str(), result); 153 return nullptr; 154 } 155 #endif 156 return primaryDevice; 157 } 158 }; 159 160 using FactoryAndDevice = std::tuple<std::string, std::string>; 161 class RegularDeviceManager 162 : public InterfaceManager<RegularDeviceManager, FactoryAndDevice, IDevice> { 163 public: createInterfaceInstance(const FactoryAndDevice & factoryAndDevice)164 static sp<IDevice> createInterfaceInstance(const FactoryAndDevice& factoryAndDevice) { 165 auto [factoryName, name] = factoryAndDevice; 166 sp<IDevicesFactory> factory = DevicesFactoryManager::getInstance().get(factoryName); 167 return openDevice(factory, name); 168 } 169 get(const std::string & factoryName,const std::string & name)170 sp<IDevice> get(const std::string& factoryName, const std::string& name) { 171 return InterfaceManager::get(std::make_tuple(factoryName, name)); 172 } 173 reset(const std::string & factoryName,const std::string & name)174 bool reset(const std::string& factoryName, const std::string& name) 175 __attribute__((warn_unused_result)) { 176 #if MAJOR_VERSION <= 5 177 return InterfaceManager::reset(std::make_tuple(factoryName, name), true); 178 #elif MAJOR_VERSION >= 6 179 { 180 sp<IDevice> device = getExisting(std::make_tuple(factoryName, name)); 181 if (device != nullptr) { 182 auto ret = device->close(); 183 ALOGE_IF(!ret.isOk(), "Device %s::%s close failed: %s", factoryName.c_str(), 184 name.c_str(), ret.description().c_str()); 185 } 186 } 187 return InterfaceManager::reset(std::make_tuple(factoryName, name), false); 188 #endif 189 } 190 191 private: openDevice(const sp<IDevicesFactory> & factory,const std::string & name)192 static sp<IDevice> openDevice(const sp<IDevicesFactory>& factory, const std::string& name) { 193 if (factory == nullptr) return nullptr; 194 Result result; 195 sp<IDevice> device; 196 #if MAJOR_VERSION == 2 197 IDevicesFactory::Device dev = IDevicesFactory::IDevicesFactory::Device(-1); 198 if (name == AUDIO_HARDWARE_MODULE_ID_A2DP) { 199 dev = IDevicesFactory::Device::A2DP; 200 } else if (name == AUDIO_HARDWARE_MODULE_ID_USB) { 201 dev = IDevicesFactory::Device::USB; 202 } else if (name == AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX) { 203 dev = IDevicesFactory::Device::R_SUBMIX; 204 } else if (name == AUDIO_HARDWARE_MODULE_ID_STUB) { 205 dev = IDevicesFactory::Device::STUB; 206 } 207 auto ret = factory->openDevice(dev, returnIn(result, device)); 208 #elif MAJOR_VERSION >= 4 && (MAJOR_VERSION < 7 || (MAJOR_VERSION == 7 && MINOR_VERSION == 0)) 209 auto ret = factory->openDevice(name, returnIn(result, device)); 210 #elif MAJOR_VERSION == 7 && MINOR_VERSION == 1 211 auto ret = factory->openDevice_7_1(name, returnIn(result, device)); 212 #endif 213 if (!ret.isOk() || result != Result::OK || device == nullptr) { 214 ALOGW("Device %s can not be opened, transaction: %s, result %d, device %p", 215 name.c_str(), ret.description().c_str(), result, device.get()); 216 return nullptr; 217 } 218 return device; 219 } 220 }; 221 222 } // namespace impl 223 224 class DeviceManager { 225 public: getInstance()226 static DeviceManager& getInstance() { 227 static DeviceManager instance; 228 return instance; 229 } 230 231 static constexpr const char* kPrimaryDevice = "primary"; 232 get(const std::string & factoryName,const std::string & name)233 sp<IDevice> get(const std::string& factoryName, const std::string& name) { 234 if (name == kPrimaryDevice) { 235 auto primary = getPrimary(factoryName); 236 return primary ? deviceFromPrimary(primary) : nullptr; 237 } 238 return mDevices.get(factoryName, name); 239 } 240 getPrimary(const std::string & factoryName)241 sp<IPrimaryDevice> getPrimary(const std::string& factoryName) { 242 return mPrimary.get(factoryName); 243 } 244 reset(const std::string & factoryName,const std::string & name)245 bool reset(const std::string& factoryName, const std::string& name) 246 __attribute__((warn_unused_result)) { 247 return name == kPrimaryDevice ? resetPrimary(factoryName) 248 : mDevices.reset(factoryName, name); 249 } 250 resetPrimary(const std::string & factoryName)251 bool resetPrimary(const std::string& factoryName) __attribute__((warn_unused_result)) { 252 return mPrimary.reset(factoryName); 253 } 254 waitForInstanceDestruction()255 static void waitForInstanceDestruction() { 256 // Does not matter which device manager to use. 257 impl::RegularDeviceManager::waitForInstanceDestruction(); 258 } 259 260 private: deviceFromPrimary(const sp<IPrimaryDevice> & primary)261 sp<IDevice> deviceFromPrimary(const sp<IPrimaryDevice>& primary) { 262 #if MAJOR_VERSION == 7 && MINOR_VERSION == 1 263 auto ret = primary->getDevice(); 264 if (ret.isOk()) { 265 return ret; 266 } else { 267 ALOGW("Error retrieving IDevice from primary: transaction: %s, primary %p", 268 ret.description().c_str(), primary.get()); 269 return nullptr; 270 } 271 #else 272 return primary; 273 #endif 274 } 275 276 impl::PrimaryDeviceManager mPrimary; 277 impl::RegularDeviceManager mDevices; 278 }; 279