• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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