1 /*
2 * Copyright 2023 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 <algorithm>
18 #include <memory>
19 #include <mutex>
20 #include <string>
21 #include <thread>
22 #include <vector>
23
24 #define LOG_TAG "CoreAudioHalAidlTest"
25 #include <gtest/gtest.h>
26
27 #include <DeviceHalAidl.h>
28 #include <Hal2AidlMapper.h>
29 #include <StreamHalAidl.h>
30 #include <aidl/android/hardware/audio/core/BnModule.h>
31 #include <aidl/android/hardware/audio/core/BnStreamCommon.h>
32 #include <aidl/android/hardware/audio/core/BnStreamOut.h>
33 #include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
34 #include <aidl/android/media/audio/common/AudioGainMode.h>
35 #include <aidl/android/media/audio/common/Int.h>
36 #include <utils/Log.h>
37
38 namespace {
39
40 using ::aidl::android::hardware::audio::core::AudioPatch;
41 using ::aidl::android::hardware::audio::core::AudioRoute;
42 using ::aidl::android::hardware::audio::core::VendorParameter;
43 using ::aidl::android::media::audio::common::AudioChannelLayout;
44 using ::aidl::android::media::audio::common::AudioConfig;
45 using ::aidl::android::media::audio::common::AudioDevice;
46 using ::aidl::android::media::audio::common::AudioDeviceDescription;
47 using ::aidl::android::media::audio::common::AudioDeviceType;
48 using ::aidl::android::media::audio::common::AudioFormatDescription;
49 using ::aidl::android::media::audio::common::AudioFormatType;
50 using ::aidl::android::media::audio::common::AudioGainConfig;
51 using ::aidl::android::media::audio::common::AudioGainMode;
52 using ::aidl::android::media::audio::common::AudioIoFlags;
53 using ::aidl::android::media::audio::common::AudioPort;
54 using ::aidl::android::media::audio::common::AudioPortConfig;
55 using ::aidl::android::media::audio::common::AudioPortDeviceExt;
56 using ::aidl::android::media::audio::common::AudioPortExt;
57 using ::aidl::android::media::audio::common::AudioPortMixExt;
58 using ::aidl::android::media::audio::common::AudioProfile;
59 using ::aidl::android::media::audio::common::AudioSource;
60 using ::aidl::android::media::audio::common::PcmType;
61
62 class VendorParameterMock {
63 public:
clearParameters()64 void clearParameters() {
65 mAsyncParameters.clear();
66 mSyncParameters.clear();
67 }
getRetrievedParameterIds() const68 const std::vector<std::string>& getRetrievedParameterIds() const { return mGetParameterIds; }
getAsyncParameters() const69 const std::vector<VendorParameter>& getAsyncParameters() const { return mAsyncParameters; }
getSyncParameters() const70 const std::vector<VendorParameter>& getSyncParameters() const { return mSyncParameters; }
71
72 protected:
getVendorParameters(const std::vector<std::string> & in_parameterIds)73 ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds) {
74 mGetParameterIds.insert(mGetParameterIds.end(), in_parameterIds.begin(),
75 in_parameterIds.end());
76 return ndk::ScopedAStatus::ok();
77 }
setVendorParameters(const std::vector<VendorParameter> & in_parameters,bool async)78 ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
79 bool async) {
80 if (async) {
81 mAsyncParameters.insert(mAsyncParameters.end(), in_parameters.begin(),
82 in_parameters.end());
83 } else {
84 mSyncParameters.insert(mSyncParameters.end(), in_parameters.begin(),
85 in_parameters.end());
86 }
87 return ndk::ScopedAStatus::ok();
88 }
89
90 private:
91 std::vector<std::string> mGetParameterIds;
92 std::vector<VendorParameter> mAsyncParameters;
93 std::vector<VendorParameter> mSyncParameters;
94 };
95
96 struct Configuration {
97 std::vector<AudioPort> ports;
98 std::vector<AudioPortConfig> portConfigs;
99 std::vector<AudioRoute> routes;
100 std::vector<AudioPatch> patches;
101 int32_t nextPortId = 1;
102 int32_t nextPatchId = 1;
103 };
104
fillProfile(AudioProfile * profile,const std::vector<int32_t> & channelLayouts,const std::vector<int32_t> & sampleRates)105 void fillProfile(AudioProfile* profile, const std::vector<int32_t>& channelLayouts,
106 const std::vector<int32_t>& sampleRates) {
107 for (auto layout : channelLayouts) {
108 profile->channelMasks.push_back(
109 AudioChannelLayout::make<AudioChannelLayout::layoutMask>(layout));
110 }
111 profile->sampleRates.insert(profile->sampleRates.end(), sampleRates.begin(), sampleRates.end());
112 }
113
createProfile(PcmType pcmType,const std::vector<int32_t> & channelLayouts,const std::vector<int32_t> & sampleRates)114 AudioProfile createProfile(PcmType pcmType, const std::vector<int32_t>& channelLayouts,
115 const std::vector<int32_t>& sampleRates) {
116 AudioProfile profile;
117 profile.format.type = AudioFormatType::PCM;
118 profile.format.pcm = pcmType;
119 fillProfile(&profile, channelLayouts, sampleRates);
120 return profile;
121 }
122
createPortDeviceExt(AudioDeviceType devType,int32_t flags,std::string connection="")123 AudioPortExt createPortDeviceExt(AudioDeviceType devType, int32_t flags,
124 std::string connection = "") {
125 AudioPortDeviceExt deviceExt;
126 deviceExt.device.type.type = devType;
127 if (devType == AudioDeviceType::IN_MICROPHONE && connection.empty()) {
128 deviceExt.device.address = "bottom";
129 } else if (devType == AudioDeviceType::IN_MICROPHONE_BACK && connection.empty()) {
130 deviceExt.device.address = "back";
131 }
132 deviceExt.device.type.connection = std::move(connection);
133 deviceExt.flags = flags;
134 return AudioPortExt::make<AudioPortExt::device>(deviceExt);
135 }
136
createPortMixExt(int32_t maxOpenStreamCount,int32_t maxActiveStreamCount)137 AudioPortExt createPortMixExt(int32_t maxOpenStreamCount, int32_t maxActiveStreamCount) {
138 AudioPortMixExt mixExt;
139 mixExt.maxOpenStreamCount = maxOpenStreamCount;
140 mixExt.maxActiveStreamCount = maxActiveStreamCount;
141 return AudioPortExt::make<AudioPortExt::mix>(mixExt);
142 }
143
createPort(int32_t id,const std::string & name,int32_t flags,bool isInput,const AudioPortExt & ext)144 AudioPort createPort(int32_t id, const std::string& name, int32_t flags, bool isInput,
145 const AudioPortExt& ext) {
146 AudioPort port;
147 port.id = id;
148 port.name = name;
149 port.flags = isInput ? AudioIoFlags::make<AudioIoFlags::input>(flags)
150 : AudioIoFlags::make<AudioIoFlags::output>(flags);
151 port.ext = ext;
152 return port;
153 }
154
createRoute(const std::vector<AudioPort> & sources,const AudioPort & sink)155 AudioRoute createRoute(const std::vector<AudioPort>& sources, const AudioPort& sink) {
156 AudioRoute route;
157 route.sinkPortId = sink.id;
158 std::transform(sources.begin(), sources.end(), std::back_inserter(route.sourcePortIds),
159 [](const auto& port) { return port.id; });
160 return route;
161 }
162
163 template <typename T>
findById(std::vector<T> & v,int32_t id)164 auto findById(std::vector<T>& v, int32_t id) {
165 return std::find_if(v.begin(), v.end(), [&](const auto& e) { return e.id == id; });
166 }
167
getTestConfiguration()168 Configuration getTestConfiguration() {
169 const std::vector<AudioProfile> standardPcmAudioProfiles = {
170 createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000})};
171 Configuration c;
172
173 AudioPort micInDevice =
174 createPort(c.nextPortId++, "Built-In Mic", 0, true,
175 createPortDeviceExt(AudioDeviceType::IN_MICROPHONE,
176 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE));
177 micInDevice.profiles = standardPcmAudioProfiles;
178 c.ports.push_back(micInDevice);
179
180 AudioPort micInBackDevice =
181 createPort(c.nextPortId++, "Built-In Back Mic", 0, true,
182 createPortDeviceExt(AudioDeviceType::IN_MICROPHONE_BACK, 0));
183 micInDevice.profiles = standardPcmAudioProfiles;
184 c.ports.push_back(micInBackDevice);
185
186 AudioPort primaryInMix =
187 createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(0, 1));
188 primaryInMix.profiles = standardPcmAudioProfiles;
189 c.ports.push_back(primaryInMix);
190
191 AudioPort speakerOutDevice = createPort(c.nextPortId++, "Speaker", 0, false,
192 createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0));
193 speakerOutDevice.profiles = standardPcmAudioProfiles;
194 c.ports.push_back(speakerOutDevice);
195
196 AudioPort primaryOutMix =
197 createPort(c.nextPortId++, "primary output", 0, false, createPortMixExt(1, 1));
198 primaryOutMix.profiles = standardPcmAudioProfiles;
199 c.ports.push_back(primaryOutMix);
200
201 AudioPort btOutDevice =
202 createPort(c.nextPortId++, "BT A2DP Out", 0, false,
203 createPortDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
204 AudioDeviceDescription::CONNECTION_BT_A2DP));
205 btOutDevice.profiles = standardPcmAudioProfiles;
206 c.ports.push_back(btOutDevice);
207
208 AudioPort btOutMix =
209 createPort(c.nextPortId++, "a2dp output", 0, false, createPortMixExt(1, 1));
210 btOutMix.profiles = standardPcmAudioProfiles;
211 c.ports.push_back(btOutMix);
212
213 c.routes.push_back(createRoute({micInDevice, micInBackDevice}, primaryInMix));
214 c.routes.push_back(createRoute({primaryOutMix}, speakerOutDevice));
215 c.routes.push_back(createRoute({btOutMix}, btOutDevice));
216
217 return c;
218 }
219
220 class StreamCommonMock : public ::aidl::android::hardware::audio::core::BnStreamCommon,
221 public VendorParameterMock {
close()222 ndk::ScopedAStatus close() override { return ndk::ScopedAStatus::ok(); }
prepareToClose()223 ndk::ScopedAStatus prepareToClose() override { return ndk::ScopedAStatus::ok(); }
updateHwAvSyncId(int32_t)224 ndk::ScopedAStatus updateHwAvSyncId(int32_t) override { return ndk::ScopedAStatus::ok(); }
getVendorParameters(const std::vector<std::string> & in_parameterIds,std::vector<VendorParameter> *)225 ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds,
226 std::vector<VendorParameter>*) override {
227 return VendorParameterMock::getVendorParameters(in_parameterIds);
228 }
setVendorParameters(const std::vector<VendorParameter> & in_parameters,bool async)229 ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
230 bool async) override {
231 return VendorParameterMock::setVendorParameters(in_parameters, async);
232 }
addEffect(const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> &)233 ndk::ScopedAStatus addEffect(
234 const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
235 return ndk::ScopedAStatus::ok();
236 }
removeEffect(const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> &)237 ndk::ScopedAStatus removeEffect(
238 const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
239 return ndk::ScopedAStatus::ok();
240 }
241 };
242
243 class StreamContext {
244 public:
245 using Descriptor = ::aidl::android::hardware::audio::core::StreamDescriptor;
246 typedef ::android::AidlMessageQueue<
247 Descriptor::Command, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
248 CommandMQ;
249 typedef ::android::AidlMessageQueue<
250 Descriptor::Reply, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
251 ReplyMQ;
252 typedef ::android::AidlMessageQueue<
253 int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
254 DataMQ;
255
256 StreamContext() = default;
StreamContext(std::unique_ptr<CommandMQ> commandMQ,std::unique_ptr<ReplyMQ> replyMQ,std::unique_ptr<DataMQ> dataMQ)257 StreamContext(std::unique_ptr<CommandMQ> commandMQ, std::unique_ptr<ReplyMQ> replyMQ,
258 std::unique_ptr<DataMQ> dataMQ)
259 : mCommandMQ(std::move(commandMQ)),
260 mReplyMQ(std::move(replyMQ)),
261 mDataMQ(std::move(dataMQ)) {}
fillDescriptor(Descriptor * desc)262 void fillDescriptor(Descriptor* desc) {
263 if (mCommandMQ) {
264 desc->command = mCommandMQ->dupeDesc();
265 }
266 if (mReplyMQ) {
267 desc->reply = mReplyMQ->dupeDesc();
268 }
269 if (mDataMQ) {
270 desc->frameSizeBytes = 2;
271 desc->bufferSizeFrames = 48;
272 desc->audio.set<Descriptor::AudioBuffer::Tag::fmq>(mDataMQ->dupeDesc());
273 }
274 }
275
276 private:
277 std::unique_ptr<CommandMQ> mCommandMQ =
278 std::make_unique<CommandMQ>(1, true /*configureEventFlagWord*/);
279 std::unique_ptr<ReplyMQ> mReplyMQ =
280 std::make_unique<ReplyMQ>(1, true /*configureEventFlagWord*/);
281 std::unique_ptr<DataMQ> mDataMQ = std::make_unique<DataMQ>(96);
282 };
283
284 class StreamOutMock : public ::aidl::android::hardware::audio::core::BnStreamOut {
285 public:
StreamOutMock(StreamContext && ctx)286 explicit StreamOutMock(StreamContext&& ctx) : mContext(std::move(ctx)) {}
287
288 private:
getStreamCommon(std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> * _aidl_return)289 ndk::ScopedAStatus getStreamCommon(
290 std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>* _aidl_return)
291 override {
292 if (!mCommon) {
293 mCommon = ndk::SharedRefBase::make<StreamCommonMock>();
294 }
295 *_aidl_return = mCommon;
296 return ndk::ScopedAStatus::ok();
297 }
updateMetadata(const::aidl::android::hardware::audio::common::SourceMetadata &)298 ndk::ScopedAStatus updateMetadata(
299 const ::aidl::android::hardware::audio::common::SourceMetadata&) override {
300 return ndk::ScopedAStatus::ok();
301 }
updateOffloadMetadata(const::aidl::android::hardware::audio::common::AudioOffloadMetadata &)302 ndk::ScopedAStatus updateOffloadMetadata(
303 const ::aidl::android::hardware::audio::common::AudioOffloadMetadata&) override {
304 return ndk::ScopedAStatus::ok();
305 }
getHwVolume(std::vector<float> *)306 ndk::ScopedAStatus getHwVolume(std::vector<float>*) override {
307 return ndk::ScopedAStatus::ok();
308 }
setHwVolume(const std::vector<float> &)309 ndk::ScopedAStatus setHwVolume(const std::vector<float>&) override {
310 return ndk::ScopedAStatus::ok();
311 }
getAudioDescriptionMixLevel(float *)312 ndk::ScopedAStatus getAudioDescriptionMixLevel(float*) override {
313 return ndk::ScopedAStatus::ok();
314 }
setAudioDescriptionMixLevel(float)315 ndk::ScopedAStatus setAudioDescriptionMixLevel(float) override {
316 return ndk::ScopedAStatus::ok();
317 }
getDualMonoMode(::aidl::android::media::audio::common::AudioDualMonoMode *)318 ndk::ScopedAStatus getDualMonoMode(
319 ::aidl::android::media::audio::common::AudioDualMonoMode*) override {
320 return ndk::ScopedAStatus::ok();
321 }
setDualMonoMode(::aidl::android::media::audio::common::AudioDualMonoMode)322 ndk::ScopedAStatus setDualMonoMode(
323 ::aidl::android::media::audio::common::AudioDualMonoMode) override {
324 return ndk::ScopedAStatus::ok();
325 }
getRecommendedLatencyModes(std::vector<::aidl::android::media::audio::common::AudioLatencyMode> *)326 ndk::ScopedAStatus getRecommendedLatencyModes(
327 std::vector<::aidl::android::media::audio::common::AudioLatencyMode>*) override {
328 return ndk::ScopedAStatus::ok();
329 }
setLatencyMode(::aidl::android::media::audio::common::AudioLatencyMode)330 ndk::ScopedAStatus setLatencyMode(
331 ::aidl::android::media::audio::common::AudioLatencyMode) override {
332 return ndk::ScopedAStatus::ok();
333 }
getPlaybackRateParameters(::aidl::android::media::audio::common::AudioPlaybackRate *)334 ndk::ScopedAStatus getPlaybackRateParameters(
335 ::aidl::android::media::audio::common::AudioPlaybackRate*) override {
336 return ndk::ScopedAStatus::ok();
337 }
setPlaybackRateParameters(const::aidl::android::media::audio::common::AudioPlaybackRate &)338 ndk::ScopedAStatus setPlaybackRateParameters(
339 const ::aidl::android::media::audio::common::AudioPlaybackRate&) override {
340 return ndk::ScopedAStatus::ok();
341 }
selectPresentation(int32_t,int32_t)342 ndk::ScopedAStatus selectPresentation(int32_t, int32_t) override {
343 return ndk::ScopedAStatus::ok();
344 }
345 StreamContext mContext;
346 std::shared_ptr<StreamCommonMock> mCommon;
347 };
348
349 class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule,
350 public VendorParameterMock {
351 public:
352 ModuleMock() = default;
ModuleMock(const Configuration & config)353 explicit ModuleMock(const Configuration& config) : mConfig(config) {}
isScreenTurnedOn() const354 bool isScreenTurnedOn() const { return mIsScreenTurnedOn; }
getScreenRotation() const355 ScreenRotation getScreenRotation() const { return mScreenRotation; }
getPatches()356 std::vector<AudioPatch> getPatches() {
357 std::vector<AudioPatch> result;
358 getAudioPatches(&result);
359 return result;
360 }
getPortConfig(int32_t id)361 std::optional<AudioPortConfig> getPortConfig(int32_t id) {
362 auto iter = findById<AudioPortConfig>(mConfig.portConfigs, id);
363 if (iter != mConfig.portConfigs.end()) {
364 return *iter;
365 }
366 return std::nullopt;
367 }
368
369 private:
setModuleDebug(const::aidl::android::hardware::audio::core::ModuleDebug &)370 ndk::ScopedAStatus setModuleDebug(
371 const ::aidl::android::hardware::audio::core::ModuleDebug&) override {
372 return ndk::ScopedAStatus::ok();
373 }
getTelephony(std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony> *)374 ndk::ScopedAStatus getTelephony(
375 std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony>*) override {
376 return ndk::ScopedAStatus::ok();
377 }
getBluetooth(std::shared_ptr<::aidl::android::hardware::audio::core::IBluetooth> *)378 ndk::ScopedAStatus getBluetooth(
379 std::shared_ptr<::aidl::android::hardware::audio::core::IBluetooth>*) override {
380 return ndk::ScopedAStatus::ok();
381 }
getBluetoothA2dp(std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothA2dp> *)382 ndk::ScopedAStatus getBluetoothA2dp(
383 std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothA2dp>*) override {
384 return ndk::ScopedAStatus::ok();
385 }
getBluetoothLe(std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothLe> *)386 ndk::ScopedAStatus getBluetoothLe(
387 std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothLe>*) override {
388 return ndk::ScopedAStatus::ok();
389 }
connectExternalDevice(const::aidl::android::media::audio::common::AudioPort & portIdAndData,::aidl::android::media::audio::common::AudioPort * port)390 ndk::ScopedAStatus connectExternalDevice(
391 const ::aidl::android::media::audio::common::AudioPort& portIdAndData,
392 ::aidl::android::media::audio::common::AudioPort* port) override {
393 auto src = portIdAndData; // Make a copy to mimic RPC behavior.
394 auto iter = findById<AudioPort>(mConfig.ports, src.id);
395 if (iter == mConfig.ports.end()) {
396 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
397 }
398 *port = *iter;
399 port->ext = src.ext;
400 port->id = mConfig.nextPortId++;
401 ALOGD("%s: returning %s", __func__, port->toString().c_str());
402 mConfig.ports.push_back(*port);
403 std::vector<AudioRoute> newRoutes;
404 for (auto& r : mConfig.routes) {
405 if (r.sinkPortId == src.id) {
406 newRoutes.push_back(AudioRoute{.sourcePortIds = r.sourcePortIds,
407 .sinkPortId = port->id,
408 .isExclusive = r.isExclusive});
409 } else if (std::find(r.sourcePortIds.begin(), r.sourcePortIds.end(), src.id) !=
410 r.sourcePortIds.end()) {
411 r.sourcePortIds.push_back(port->id);
412 }
413 }
414 mConfig.routes.insert(mConfig.routes.end(), newRoutes.begin(), newRoutes.end());
415 return ndk::ScopedAStatus::ok();
416 }
disconnectExternalDevice(int32_t portId)417 ndk::ScopedAStatus disconnectExternalDevice(int32_t portId) override {
418 auto iter = findById<AudioPort>(mConfig.ports, portId);
419 if (iter == mConfig.ports.end()) {
420 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
421 }
422 mConfig.ports.erase(iter);
423 for (auto it = mConfig.routes.begin(); it != mConfig.routes.end();) {
424 if (it->sinkPortId == portId) {
425 it = mConfig.routes.erase(it);
426 } else {
427 if (auto srcIt =
428 std::find(it->sourcePortIds.begin(), it->sourcePortIds.end(), portId);
429 srcIt != it->sourcePortIds.end()) {
430 it->sourcePortIds.erase(srcIt);
431 }
432 ++it;
433 }
434 }
435 return ndk::ScopedAStatus::ok();
436 }
getAudioPatches(std::vector<::aidl::android::hardware::audio::core::AudioPatch> * patches)437 ndk::ScopedAStatus getAudioPatches(
438 std::vector<::aidl::android::hardware::audio::core::AudioPatch>* patches) override {
439 *patches = mConfig.patches;
440 return ndk::ScopedAStatus::ok();
441 }
getAudioPort(int32_t portId,::aidl::android::media::audio::common::AudioPort * port)442 ndk::ScopedAStatus getAudioPort(
443 int32_t portId, ::aidl::android::media::audio::common::AudioPort* port) override {
444 auto iter = findById<AudioPort>(mConfig.ports, portId);
445 if (iter == mConfig.ports.end()) {
446 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
447 }
448 *port = *iter;
449 return ndk::ScopedAStatus::ok();
450 }
getAudioPortConfigs(std::vector<::aidl::android::media::audio::common::AudioPortConfig> * configs)451 ndk::ScopedAStatus getAudioPortConfigs(
452 std::vector<::aidl::android::media::audio::common::AudioPortConfig>* configs) override {
453 *configs = mConfig.portConfigs;
454 return ndk::ScopedAStatus::ok();
455 }
getAudioPorts(std::vector<::aidl::android::media::audio::common::AudioPort> * ports)456 ndk::ScopedAStatus getAudioPorts(
457 std::vector<::aidl::android::media::audio::common::AudioPort>* ports) override {
458 *ports = mConfig.ports;
459 return ndk::ScopedAStatus::ok();
460 }
getAudioRoutes(std::vector<::aidl::android::hardware::audio::core::AudioRoute> * routes)461 ndk::ScopedAStatus getAudioRoutes(
462 std::vector<::aidl::android::hardware::audio::core::AudioRoute>* routes) override {
463 *routes = mConfig.routes;
464 return ndk::ScopedAStatus::ok();
465 }
getAudioRoutesForAudioPort(int32_t portId,std::vector<::aidl::android::hardware::audio::core::AudioRoute> * routes)466 ndk::ScopedAStatus getAudioRoutesForAudioPort(
467 int32_t portId,
468 std::vector<::aidl::android::hardware::audio::core::AudioRoute>* routes) override {
469 for (auto& r : mConfig.routes) {
470 const auto& srcs = r.sourcePortIds;
471 if (r.sinkPortId == portId ||
472 std::find(srcs.begin(), srcs.end(), portId) != srcs.end()) {
473 routes->push_back(r);
474 }
475 }
476 return ndk::ScopedAStatus::ok();
477 }
openInputStream(const OpenInputStreamArguments &,OpenInputStreamReturn *)478 ndk::ScopedAStatus openInputStream(const OpenInputStreamArguments&,
479 OpenInputStreamReturn*) override {
480 return ndk::ScopedAStatus::ok();
481 }
openOutputStream(const OpenOutputStreamArguments &,OpenOutputStreamReturn * _aidl_return)482 ndk::ScopedAStatus openOutputStream(const OpenOutputStreamArguments&,
483 OpenOutputStreamReturn* _aidl_return) override {
484 StreamContext context;
485 context.fillDescriptor(&_aidl_return->desc);
486 _aidl_return->stream = ndk::SharedRefBase::make<StreamOutMock>(std::move(context));
487 return ndk::ScopedAStatus::ok();
488 }
getSupportedPlaybackRateFactors(SupportedPlaybackRateFactors *)489 ndk::ScopedAStatus getSupportedPlaybackRateFactors(SupportedPlaybackRateFactors*) override {
490 return ndk::ScopedAStatus::ok();
491 }
setAudioPatch(const::aidl::android::hardware::audio::core::AudioPatch & requested,::aidl::android::hardware::audio::core::AudioPatch * patch)492 ndk::ScopedAStatus setAudioPatch(
493 const ::aidl::android::hardware::audio::core::AudioPatch& requested,
494 ::aidl::android::hardware::audio::core::AudioPatch* patch) override {
495 if (requested.id == 0) {
496 *patch = requested;
497 patch->id = mConfig.nextPatchId++;
498 patch->latenciesMs.push_back(100);
499 mConfig.patches.push_back(*patch);
500 ALOGD("%s: returning %s", __func__, patch->toString().c_str());
501 } else {
502 auto iter = findById<AudioPatch>(mConfig.patches, requested.id);
503 if (iter == mConfig.patches.end()) {
504 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
505 }
506 *iter = *patch = requested;
507 ALOGD("%s: updated %s", __func__, patch->toString().c_str());
508 }
509 return ndk::ScopedAStatus::ok();
510 }
setAudioPortConfig(const::aidl::android::media::audio::common::AudioPortConfig & requested,::aidl::android::media::audio::common::AudioPortConfig * config,bool * applied)511 ndk::ScopedAStatus setAudioPortConfig(
512 const ::aidl::android::media::audio::common::AudioPortConfig& requested,
513 ::aidl::android::media::audio::common::AudioPortConfig* config,
514 bool* applied) override {
515 *applied = false;
516 auto src = requested; // Make a copy to mimic RPC behavior.
517 if (src.id == 0) {
518 *config = src;
519 if (config->ext.getTag() == AudioPortExt::unspecified) {
520 auto iter = findById<AudioPort>(mConfig.ports, src.portId);
521 if (iter == mConfig.ports.end()) {
522 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
523 }
524 config->ext = iter->ext;
525 }
526 config->id = mConfig.nextPortId++;
527 mConfig.portConfigs.push_back(*config);
528 ALOGD("%s: returning %s", __func__, config->toString().c_str());
529 } else {
530 auto iter = findById<AudioPortConfig>(mConfig.portConfigs, src.id);
531 if (iter == mConfig.portConfigs.end()) {
532 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
533 }
534 *iter = *config = src;
535 ALOGD("%s: updated %s", __func__, config->toString().c_str());
536 }
537 *applied = true;
538 return ndk::ScopedAStatus::ok();
539 }
resetAudioPatch(int32_t patchId)540 ndk::ScopedAStatus resetAudioPatch(int32_t patchId) override {
541 auto iter = findById<AudioPatch>(mConfig.patches, patchId);
542 if (iter == mConfig.patches.end()) {
543 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
544 }
545 mConfig.patches.erase(iter);
546 return ndk::ScopedAStatus::ok();
547 }
resetAudioPortConfig(int32_t portConfigId)548 ndk::ScopedAStatus resetAudioPortConfig(int32_t portConfigId) override {
549 auto iter = findById<AudioPortConfig>(mConfig.portConfigs, portConfigId);
550 if (iter == mConfig.portConfigs.end()) {
551 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
552 }
553 mConfig.portConfigs.erase(iter);
554 return ndk::ScopedAStatus::ok();
555 }
getMasterMute(bool *)556 ndk::ScopedAStatus getMasterMute(bool*) override { return ndk::ScopedAStatus::ok(); }
setMasterMute(bool)557 ndk::ScopedAStatus setMasterMute(bool) override { return ndk::ScopedAStatus::ok(); }
getMasterVolume(float *)558 ndk::ScopedAStatus getMasterVolume(float*) override { return ndk::ScopedAStatus::ok(); }
setMasterVolume(float)559 ndk::ScopedAStatus setMasterVolume(float) override { return ndk::ScopedAStatus::ok(); }
getMicMute(bool *)560 ndk::ScopedAStatus getMicMute(bool*) override { return ndk::ScopedAStatus::ok(); }
setMicMute(bool)561 ndk::ScopedAStatus setMicMute(bool) override { return ndk::ScopedAStatus::ok(); }
getMicrophones(std::vector<::aidl::android::media::audio::common::MicrophoneInfo> *)562 ndk::ScopedAStatus getMicrophones(
563 std::vector<::aidl::android::media::audio::common::MicrophoneInfo>*) override {
564 return ndk::ScopedAStatus::ok();
565 }
updateAudioMode(::aidl::android::media::audio::common::AudioMode)566 ndk::ScopedAStatus updateAudioMode(::aidl::android::media::audio::common::AudioMode) override {
567 return ndk::ScopedAStatus::ok();
568 }
updateScreenRotation(ScreenRotation in_rotation)569 ndk::ScopedAStatus updateScreenRotation(ScreenRotation in_rotation) override {
570 mScreenRotation = in_rotation;
571 return ndk::ScopedAStatus::ok();
572 }
updateScreenState(bool in_isTurnedOn)573 ndk::ScopedAStatus updateScreenState(bool in_isTurnedOn) override {
574 mIsScreenTurnedOn = in_isTurnedOn;
575 return ndk::ScopedAStatus::ok();
576 }
getSoundDose(std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose> *)577 ndk::ScopedAStatus getSoundDose(
578 std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose>*)
579 override {
580 return ndk::ScopedAStatus::ok();
581 }
generateHwAvSyncId(int32_t *)582 ndk::ScopedAStatus generateHwAvSyncId(int32_t*) override { return ndk::ScopedAStatus::ok(); }
getVendorParameters(const std::vector<std::string> & in_parameterIds,std::vector<VendorParameter> *)583 ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds,
584 std::vector<VendorParameter>*) override {
585 return VendorParameterMock::getVendorParameters(in_parameterIds);
586 }
setVendorParameters(const std::vector<VendorParameter> & in_parameters,bool async)587 ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
588 bool async) override {
589 return VendorParameterMock::setVendorParameters(in_parameters, async);
590 }
addDeviceEffect(int32_t,const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> &)591 ndk::ScopedAStatus addDeviceEffect(
592 int32_t,
593 const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
594 return ndk::ScopedAStatus::ok();
595 }
removeDeviceEffect(int32_t,const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> &)596 ndk::ScopedAStatus removeDeviceEffect(
597 int32_t,
598 const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
599 return ndk::ScopedAStatus::ok();
600 }
getMmapPolicyInfos(::aidl::android::media::audio::common::AudioMMapPolicyType,std::vector<::aidl::android::media::audio::common::AudioMMapPolicyInfo> *)601 ndk::ScopedAStatus getMmapPolicyInfos(
602 ::aidl::android::media::audio::common::AudioMMapPolicyType,
603 std::vector<::aidl::android::media::audio::common::AudioMMapPolicyInfo>*) override {
604 return ndk::ScopedAStatus::ok();
605 }
supportsVariableLatency(bool *)606 ndk::ScopedAStatus supportsVariableLatency(bool*) override { return ndk::ScopedAStatus::ok(); }
getAAudioMixerBurstCount(int32_t *)607 ndk::ScopedAStatus getAAudioMixerBurstCount(int32_t*) override {
608 return ndk::ScopedAStatus::ok();
609 }
getAAudioHardwareBurstMinUsec(int32_t *)610 ndk::ScopedAStatus getAAudioHardwareBurstMinUsec(int32_t*) override {
611 return ndk::ScopedAStatus::ok();
612 }
prepareToDisconnectExternalDevice(int32_t)613 ndk::ScopedAStatus prepareToDisconnectExternalDevice(int32_t) override {
614 return ndk::ScopedAStatus::ok();
615 }
616
617 Configuration mConfig;
618 bool mIsScreenTurnedOn = false;
619 ScreenRotation mScreenRotation = ScreenRotation::DEG_0;
620 };
621
makeVendorParameter(const std::string & id,int value)622 VendorParameter makeVendorParameter(const std::string& id, int value) {
623 VendorParameter result{.id = id};
624 // Note: in real life, a parcelable type defined by vendor must be used,
625 // here we use Int just for test purposes.
626 ::aidl::android::media::audio::common::Int vendorValue{.value = value};
627 result.ext.setParcelable(std::move(vendorValue));
628 return result;
629 }
630
parseVendorParameter(const VendorParameter & param,int * value)631 android::status_t parseVendorParameter(const VendorParameter& param, int* value) {
632 std::optional<::aidl::android::media::audio::common::Int> vendorValue;
633 RETURN_STATUS_IF_ERROR(param.ext.getParcelable(&vendorValue));
634 if (!vendorValue.has_value()) return android::BAD_VALUE;
635 *value = vendorValue.value().value;
636 return android::OK;
637 }
638
639 class TestHalAdapterVendorExtension
640 : public ::aidl::android::media::audio::BnHalAdapterVendorExtension {
641 public:
642 static const std::string kLegacyParameterKey;
643 static const std::string kLegacyAsyncParameterKey;
644 static const std::string kModuleVendorParameterId;
645 static const std::string kStreamVendorParameterId;
646
647 private:
parseVendorParameterIds(ParameterScope in_scope,const std::string & in_rawKeys,std::vector<std::string> * _aidl_return)648 ndk::ScopedAStatus parseVendorParameterIds(ParameterScope in_scope,
649 const std::string& in_rawKeys,
650 std::vector<std::string>* _aidl_return) override {
651 android::AudioParameter keys(android::String8(in_rawKeys.c_str()));
652 for (size_t i = 0; i < keys.size(); ++i) {
653 android::String8 key;
654 if (android::status_t status = keys.getAt(i, key); status != android::OK) {
655 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
656 }
657 switch (in_scope) {
658 case ParameterScope::MODULE:
659 if (key == android::String8(kLegacyParameterKey.c_str()) ||
660 key == android::String8(kLegacyAsyncParameterKey.c_str())) {
661 _aidl_return->push_back(kModuleVendorParameterId);
662 } else {
663 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
664 }
665 break;
666 case ParameterScope::STREAM:
667 if (key == android::String8(kLegacyParameterKey.c_str()) ||
668 key == android::String8(kLegacyAsyncParameterKey.c_str())) {
669 _aidl_return->push_back(kStreamVendorParameterId);
670 } else {
671 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
672 }
673 break;
674 }
675 }
676 return ndk::ScopedAStatus::ok();
677 }
parseVendorParameters(ParameterScope in_scope,const std::string & in_rawKeysAndValues,std::vector<VendorParameter> * out_syncParameters,std::vector<VendorParameter> * out_asyncParameters)678 ndk::ScopedAStatus parseVendorParameters(
679 ParameterScope in_scope, const std::string& in_rawKeysAndValues,
680 std::vector<VendorParameter>* out_syncParameters,
681 std::vector<VendorParameter>* out_asyncParameters) override {
682 android::AudioParameter legacy(android::String8(in_rawKeysAndValues.c_str()));
683 for (size_t i = 0; i < legacy.size(); ++i) {
684 android::String8 key;
685 if (android::status_t status = legacy.getAt(i, key); status != android::OK) {
686 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
687 }
688 int value;
689 if (android::status_t status = legacy.getInt(key, value); status != android::OK) {
690 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
691 }
692 std::string parameterId;
693 switch (in_scope) {
694 case ParameterScope::MODULE:
695 parameterId = kModuleVendorParameterId;
696 break;
697 case ParameterScope::STREAM:
698 parameterId = kStreamVendorParameterId;
699 break;
700 }
701 if (key == android::String8(kLegacyParameterKey.c_str())) {
702 out_syncParameters->push_back(makeVendorParameter(parameterId, value));
703 } else if (key == android::String8(kLegacyAsyncParameterKey.c_str())) {
704 out_asyncParameters->push_back(makeVendorParameter(parameterId, value));
705 } else {
706 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
707 }
708 }
709 return ndk::ScopedAStatus::ok();
710 }
parseBluetoothA2dpReconfigureOffload(const std::string &,std::vector<VendorParameter> *)711 ndk::ScopedAStatus parseBluetoothA2dpReconfigureOffload(
712 const std::string&, std::vector<VendorParameter>*) override {
713 return ndk::ScopedAStatus::ok();
714 }
parseBluetoothLeReconfigureOffload(const std::string &,std::vector<VendorParameter> *)715 ndk::ScopedAStatus parseBluetoothLeReconfigureOffload(const std::string&,
716 std::vector<VendorParameter>*) override {
717 return ndk::ScopedAStatus::ok();
718 }
processVendorParameters(ParameterScope in_scope,const std::vector<VendorParameter> & in_parameters,std::string * _aidl_return)719 ndk::ScopedAStatus processVendorParameters(ParameterScope in_scope,
720 const std::vector<VendorParameter>& in_parameters,
721 std::string* _aidl_return) override {
722 android::AudioParameter legacy;
723 for (const auto& vendorParam : in_parameters) {
724 if ((in_scope == ParameterScope::MODULE &&
725 vendorParam.id == kModuleVendorParameterId) ||
726 (in_scope == ParameterScope::STREAM &&
727 vendorParam.id == kStreamVendorParameterId)) {
728 int value;
729 if (android::status_t status = parseVendorParameter(vendorParam, &value);
730 status != android::OK) {
731 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
732 }
733 legacy.addInt(android::String8(kLegacyParameterKey.c_str()), value);
734 }
735 }
736 *_aidl_return = legacy.toString().c_str();
737 return ndk::ScopedAStatus::ok();
738 }
739 };
740
741 const std::string TestHalAdapterVendorExtension::kLegacyParameterKey = "aosp_test_param";
742 const std::string TestHalAdapterVendorExtension::kLegacyAsyncParameterKey = "aosp_test_param_async";
743 // Note: in real life, there is no need to explicitly separate "module" and "stream"
744 // parameters, here it's done just for test purposes.
745 const std::string TestHalAdapterVendorExtension::kModuleVendorParameterId =
746 "aosp.test.module.parameter";
747 const std::string TestHalAdapterVendorExtension::kStreamVendorParameterId =
748 "aosp.test.stream.parameter";
749
createParameterString(const std::string & key,const std::string & value)750 android::String8 createParameterString(const std::string& key, const std::string& value) {
751 android::AudioParameter params;
752 params.add(android::String8(key.c_str()), android::String8(value.c_str()));
753 return params.toString();
754 }
755
createParameterString(const std::string & key,int value)756 android::String8 createParameterString(const std::string& key, int value) {
757 android::AudioParameter params;
758 params.addInt(android::String8(key.c_str()), value);
759 return params.toString();
760 }
761
762 template <typename>
763 struct mf_traits {};
764 template <class T, class U>
765 struct mf_traits<U T::*> {
766 using member_type = U;
767 };
768
769 } // namespace
770
771 // Provide value printers for types generated from AIDL
772 // They need to be in the same namespace as the types we intend to print
773 namespace aidl::android::hardware::audio::core {
774 template <typename P>
775 std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>,
776 std::ostream&>
operator <<(std::ostream & os,const P & p)777 operator<<(std::ostream& os, const P& p) {
778 return os << p.toString();
779 }
780 template <typename E>
operator <<(std::ostream & os,const E & e)781 std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) {
782 return os << toString(e);
783 }
784 } // namespace aidl::android::hardware::audio::core
785
786 namespace aidl::android::media::audio::common {
787 template <typename P>
788 std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>,
789 std::ostream&>
operator <<(std::ostream & os,const P & p)790 operator<<(std::ostream& os, const P& p) {
791 return os << p.toString();
792 }
793 template <typename E>
operator <<(std::ostream & os,const E & e)794 std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) {
795 return os << toString(e);
796 }
797 } // namespace aidl::android::media::audio::common
798
799 using namespace android;
800
801 namespace {
802
803 class StreamHalMock : public virtual StreamHalInterface {
804 public:
805 StreamHalMock() = default;
806 ~StreamHalMock() override = default;
getBufferSize(size_t *)807 status_t getBufferSize(size_t*) override { return OK; }
getAudioProperties(audio_config_base_t *)808 status_t getAudioProperties(audio_config_base_t*) override { return OK; }
setParameters(const String8 &)809 status_t setParameters(const String8&) override { return OK; }
getParameters(const String8 &,String8 *)810 status_t getParameters(const String8&, String8*) override { return OK; }
getFrameSize(size_t *)811 status_t getFrameSize(size_t*) override { return OK; }
addEffect(sp<EffectHalInterface>)812 status_t addEffect(sp<EffectHalInterface>) override { return OK; }
removeEffect(sp<EffectHalInterface>)813 status_t removeEffect(sp<EffectHalInterface>) override { return OK; }
standby()814 status_t standby() override { return OK; }
dump(int,const Vector<String16> &)815 status_t dump(int, const Vector<String16>&) override { return OK; }
start()816 status_t start() override { return OK; }
stop()817 status_t stop() override { return OK; }
createMmapBuffer(int32_t,struct audio_mmap_buffer_info *)818 status_t createMmapBuffer(int32_t, struct audio_mmap_buffer_info*) override { return OK; }
getMmapPosition(struct audio_mmap_position *)819 status_t getMmapPosition(struct audio_mmap_position*) override { return OK; }
setHalThreadPriority(int)820 status_t setHalThreadPriority(int) override { return OK; }
legacyCreateAudioPatch(const struct audio_port_config &,std::optional<audio_source_t>,audio_devices_t)821 status_t legacyCreateAudioPatch(const struct audio_port_config&, std::optional<audio_source_t>,
822 audio_devices_t) override {
823 return OK;
824 }
legacyReleaseAudioPatch()825 status_t legacyReleaseAudioPatch() override { return OK; }
826 };
827
828 } // namespace
829
830 class DeviceHalAidlTest : public testing::Test {
831 public:
SetUp()832 void SetUp() override {
833 mModule = ndk::SharedRefBase::make<ModuleMock>(getTestConfiguration());
834 mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
835 mDevice = sp<DeviceHalAidl>::make("test", mModule, mVendorExt);
836 }
TearDown()837 void TearDown() override {
838 mDevice.clear();
839 mVendorExt.reset();
840 mModule.reset();
841 }
842
843 protected:
844 std::shared_ptr<ModuleMock> mModule;
845 std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
846 sp<DeviceHalAidl> mDevice;
847 };
848
TEST_F(DeviceHalAidlTest,ScreenState)849 TEST_F(DeviceHalAidlTest, ScreenState) {
850 EXPECT_FALSE(mModule->isScreenTurnedOn());
851 EXPECT_EQ(OK, mDevice->setParameters(createParameterString(AudioParameter::keyScreenState,
852 AudioParameter::valueOn)));
853 EXPECT_TRUE(mModule->isScreenTurnedOn());
854 EXPECT_EQ(OK, mDevice->setParameters(createParameterString(AudioParameter::keyScreenState,
855 AudioParameter::valueOff)));
856 EXPECT_FALSE(mModule->isScreenTurnedOn());
857 // The adaptation layer only logs a warning.
858 EXPECT_EQ(OK, mDevice->setParameters(
859 createParameterString(AudioParameter::keyScreenState, "blah")));
860 EXPECT_FALSE(mModule->isScreenTurnedOn());
861 }
862
TEST_F(DeviceHalAidlTest,ScreenRotation)863 TEST_F(DeviceHalAidlTest, ScreenRotation) {
864 using ScreenRotation = ::aidl::android::hardware::audio::core::IModule::ScreenRotation;
865 EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
866 EXPECT_EQ(OK,
867 mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 90)));
868 EXPECT_EQ(ScreenRotation::DEG_90, mModule->getScreenRotation());
869 EXPECT_EQ(OK,
870 mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 0)));
871 EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
872 // The adaptation layer only logs a warning.
873 EXPECT_EQ(OK,
874 mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 42)));
875 EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
876 }
877
878 // See http://b/357487484#comment6
TEST_F(DeviceHalAidlTest,StreamReleaseOnMapperCleanup)879 TEST_F(DeviceHalAidlTest, StreamReleaseOnMapperCleanup) {
880 ASSERT_EQ(OK, mDevice->initCheck());
881 // Since the test is in effect probabilistic, try multiple times.
882 for (int i = 0; i < 100; ++i) {
883 sp<StreamOutHalInterface> stream1;
884 struct audio_config config = AUDIO_CONFIG_INITIALIZER;
885 config.sample_rate = 48000;
886 config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
887 config.format = AUDIO_FORMAT_PCM_16_BIT;
888 ASSERT_EQ(OK, mDevice->openOutputStream(42 /*handle*/, AUDIO_DEVICE_OUT_SPEAKER,
889 AUDIO_OUTPUT_FLAG_NONE, &config, "" /*address*/,
890 &stream1));
891 ASSERT_EQ(1, stream1->getStrongCount());
892 std::atomic<bool> stopReleaser = false;
893 // Try to catch the moment when Hal2AidlMapper promotes its wp<StreamHalInterface> to sp<>
894 // in Hal2AidlMapper::resetUnusedPatchesAndPortConfigs and release on our side in order to
895 // make Hal2AidlMapper the sole owner via a temporary sp and enforce destruction of the
896 // stream while the DeviceHalAidl::mLock is held.
897 std::thread releaser([&stream1, &stopReleaser]() {
898 while (!stopReleaser) {
899 if (stream1->getStrongCount() > 1) {
900 stream1.clear();
901 break;
902 }
903 std::this_thread::yield();
904 }
905 });
906 sp<StreamOutHalInterface> stream2;
907 // Opening another stream triggers a call to
908 // Hal2AidlMapper::resetUnusedPatchesAndPortConfigs. It must not cause a deadlock of the
909 // test (main) thread.
910 ASSERT_EQ(OK, mDevice->openOutputStream(43 /*handle*/, AUDIO_DEVICE_OUT_SPEAKER,
911 AUDIO_OUTPUT_FLAG_NONE, &config, "" /*address*/,
912 &stream2));
913 stopReleaser = true;
914 releaser.join();
915 }
916 }
917
918 class DeviceHalAidlVendorParametersTest : public testing::Test {
919 public:
SetUp()920 void SetUp() override {
921 mModule = ndk::SharedRefBase::make<ModuleMock>();
922 mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
923 mDevice = sp<DeviceHalAidl>::make("test", mModule, mVendorExt);
924 }
TearDown()925 void TearDown() override {
926 mDevice.clear();
927 mVendorExt.reset();
928 mModule.reset();
929 }
930
931 protected:
932 std::shared_ptr<ModuleMock> mModule;
933 std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
934 sp<DeviceHalAidl> mDevice;
935 };
936
TEST_F(DeviceHalAidlVendorParametersTest,GetVendorParameter)937 TEST_F(DeviceHalAidlVendorParametersTest, GetVendorParameter) {
938 EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
939 String8 values;
940 EXPECT_EQ(OK, mDevice->getParameters(
941 String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()),
942 &values));
943 EXPECT_EQ(1UL, mModule->getRetrievedParameterIds().size());
944 if (mModule->getRetrievedParameterIds().size() >= 1) {
945 EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
946 mModule->getRetrievedParameterIds()[0]);
947 }
948 }
949
TEST_F(DeviceHalAidlVendorParametersTest,SetVendorParameter)950 TEST_F(DeviceHalAidlVendorParametersTest, SetVendorParameter) {
951 EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
952 EXPECT_EQ(0UL, mModule->getSyncParameters().size());
953 EXPECT_EQ(OK, mDevice->setParameters(createParameterString(
954 TestHalAdapterVendorExtension::kLegacyParameterKey, 42)));
955 EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
956 EXPECT_EQ(1UL, mModule->getSyncParameters().size());
957 EXPECT_EQ(OK, mDevice->setParameters(createParameterString(
958 TestHalAdapterVendorExtension::kLegacyAsyncParameterKey, 43)));
959 EXPECT_EQ(1UL, mModule->getAsyncParameters().size());
960 EXPECT_EQ(1UL, mModule->getSyncParameters().size());
961 if (mModule->getSyncParameters().size() >= 1) {
962 EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
963 mModule->getSyncParameters()[0].id);
964 int value{};
965 EXPECT_EQ(android::OK, parseVendorParameter(mModule->getSyncParameters()[0], &value));
966 EXPECT_EQ(42, value);
967 }
968 if (mModule->getAsyncParameters().size() >= 1) {
969 EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
970 mModule->getAsyncParameters()[0].id);
971 int value{};
972 EXPECT_EQ(android::OK, parseVendorParameter(mModule->getAsyncParameters()[0], &value));
973 EXPECT_EQ(43, value);
974 }
975 }
976
TEST_F(DeviceHalAidlVendorParametersTest,SetInvalidVendorParameters)977 TEST_F(DeviceHalAidlVendorParametersTest, SetInvalidVendorParameters) {
978 android::AudioParameter legacy;
979 legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), 42);
980 legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyAsyncParameterKey.c_str()),
981 43);
982 legacy.addInt(android::String8("random_name"), 44);
983 EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
984 EXPECT_EQ(0UL, mModule->getSyncParameters().size());
985 // TestHalAdapterVendorExtension throws an error for unknown parameters.
986 EXPECT_EQ(android::BAD_VALUE, mDevice->setParameters(legacy.toString()));
987 EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
988 EXPECT_EQ(0UL, mModule->getSyncParameters().size());
989 }
990
991 class StreamHalAidlVendorParametersTest : public testing::Test {
992 public:
SetUp()993 void SetUp() override {
994 mStreamCommon = ndk::SharedRefBase::make<StreamCommonMock>();
995 mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
996 struct audio_config config = AUDIO_CONFIG_INITIALIZER;
997 ::aidl::android::hardware::audio::core::StreamDescriptor descriptor;
998 StreamContextAidl context(descriptor, false /*isAsynchronous*/, 0,
999 false /*hasClipTransitionSupport*/);
1000 mStream = sp<StreamHalAidl>::make("test", false /*isInput*/, config, 0 /*nominalLatency*/,
1001 std::move(context), mStreamCommon, mVendorExt);
1002 // The stream may check for some properties after creating.
1003 mStreamCommon->clearParameters();
1004 }
TearDown()1005 void TearDown() override {
1006 mStream.clear();
1007 mVendorExt.reset();
1008 mStreamCommon.reset();
1009 }
1010
1011 protected:
1012 std::shared_ptr<StreamCommonMock> mStreamCommon;
1013 std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
1014 sp<StreamHalAidl> mStream;
1015 };
1016
TEST_F(StreamHalAidlVendorParametersTest,GetVendorParameter)1017 TEST_F(StreamHalAidlVendorParametersTest, GetVendorParameter) {
1018 EXPECT_EQ(0UL, mStreamCommon->getRetrievedParameterIds().size());
1019 String8 values;
1020 EXPECT_EQ(OK, mStream->getParameters(
1021 String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()),
1022 &values));
1023 EXPECT_EQ(1UL, mStreamCommon->getRetrievedParameterIds().size());
1024 if (mStreamCommon->getRetrievedParameterIds().size() >= 1) {
1025 EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
1026 mStreamCommon->getRetrievedParameterIds()[0]);
1027 }
1028 }
1029
TEST_F(StreamHalAidlVendorParametersTest,SetVendorParameter)1030 TEST_F(StreamHalAidlVendorParametersTest, SetVendorParameter) {
1031 EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
1032 EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
1033 EXPECT_EQ(OK, mStream->setParameters(createParameterString(
1034 TestHalAdapterVendorExtension::kLegacyParameterKey, 42)));
1035 EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
1036 EXPECT_EQ(1UL, mStreamCommon->getSyncParameters().size());
1037 EXPECT_EQ(OK, mStream->setParameters(createParameterString(
1038 TestHalAdapterVendorExtension::kLegacyAsyncParameterKey, 43)));
1039 EXPECT_EQ(1UL, mStreamCommon->getAsyncParameters().size());
1040 EXPECT_EQ(1UL, mStreamCommon->getSyncParameters().size());
1041 if (mStreamCommon->getSyncParameters().size() >= 1) {
1042 EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
1043 mStreamCommon->getSyncParameters()[0].id);
1044 int value{};
1045 EXPECT_EQ(android::OK, parseVendorParameter(mStreamCommon->getSyncParameters()[0], &value));
1046 EXPECT_EQ(42, value);
1047 }
1048 if (mStreamCommon->getAsyncParameters().size() >= 1) {
1049 EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
1050 mStreamCommon->getAsyncParameters()[0].id);
1051 int value{};
1052 EXPECT_EQ(android::OK,
1053 parseVendorParameter(mStreamCommon->getAsyncParameters()[0], &value));
1054 EXPECT_EQ(43, value);
1055 }
1056 }
1057
TEST_F(StreamHalAidlVendorParametersTest,SetInvalidVendorParameters)1058 TEST_F(StreamHalAidlVendorParametersTest, SetInvalidVendorParameters) {
1059 android::AudioParameter legacy;
1060 legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), 42);
1061 legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyAsyncParameterKey.c_str()),
1062 43);
1063 legacy.addInt(android::String8("random_name"), 44);
1064 EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
1065 EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
1066 // TestHalAdapterVendorExtension throws an error for unknown parameters.
1067 EXPECT_EQ(android::BAD_VALUE, mStream->setParameters(legacy.toString()));
1068 EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
1069 EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
1070 }
1071
1072 class Hal2AidlMapperTest : public testing::Test {
1073 public:
SetUp()1074 void SetUp() override {
1075 mModule = ndk::SharedRefBase::make<ModuleMock>(getTestConfiguration());
1076 mMapper = std::make_unique<Hal2AidlMapper>("test", mModule);
1077 ASSERT_EQ(OK, mMapper->initialize());
1078
1079 mConnectedPort.ext = createPortDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
1080 AudioDeviceDescription::CONNECTION_BT_A2DP);
1081 mConnectedPort.ext.get<AudioPortExt::device>().device.address = "00:11:22:33:44:55";
1082 ASSERT_EQ(OK, mMapper->setDevicePortConnectedState(mConnectedPort, true /*connected*/));
1083
1084 std::mutex mutex; // Only needed for cleanups.
1085 auto mapperAccessor = std::make_unique<LockedAccessor<Hal2AidlMapper>>(*mMapper, mutex);
1086 Hal2AidlMapper::Cleanups cleanups(*mapperAccessor);
1087 AudioConfig config;
1088 config.base.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
1089 AudioChannelLayout::LAYOUT_STEREO);
1090 config.base.format =
1091 AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT};
1092 config.base.sampleRate = 48000;
1093 ASSERT_EQ(OK,
1094 mMapper->prepareToOpenStream(
1095 42 /*ioHandle*/, mConnectedPort.ext.get<AudioPortExt::device>().device,
1096 AudioIoFlags::make<AudioIoFlags::output>(0), AudioSource::DEFAULT,
1097 &cleanups, &config, &mMixPortConfig, &mPatch));
1098 cleanups.disarmAll();
1099 ASSERT_NE(0, mPatch.id);
1100 ASSERT_NE(0, mMixPortConfig.id);
1101 mStream = sp<StreamHalMock>::make();
1102 mMapper->addStream(mStream, mMixPortConfig.id, mPatch.id);
1103
1104 ASSERT_EQ(OK, mMapper->findPortConfig(mConnectedPort.ext.get<AudioPortExt::device>().device,
1105 &mDevicePortConfig));
1106 ASSERT_EQ(1UL, mPatch.sourcePortConfigIds.size());
1107 ASSERT_EQ(mMixPortConfig.id, mPatch.sourcePortConfigIds[0]);
1108 ASSERT_EQ(1UL, mPatch.sinkPortConfigIds.size());
1109 ASSERT_EQ(mDevicePortConfig.id, mPatch.sinkPortConfigIds[0]);
1110 }
1111
TearDown()1112 void TearDown() override {
1113 mStream.clear();
1114 mMapper.reset();
1115 mModule.reset();
1116 }
1117
1118 protected:
CloseDisconnectImpl()1119 void CloseDisconnectImpl() {
1120 mStream.clear();
1121 ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1122 }
1123
ConnectAnotherDevice()1124 void ConnectAnotherDevice() {
1125 mConnectedPort.ext.get<AudioPortExt::device>().device.address = "00:11:22:33:44:66";
1126 ASSERT_EQ(OK, mMapper->setDevicePortConnectedState(mConnectedPort, true /*connected*/));
1127 }
1128
CreateFwkPatch(int32_t * patchId)1129 void CreateFwkPatch(int32_t* patchId) {
1130 std::mutex mutex; // Only needed for cleanups.
1131 auto mapperAccessor = std::make_unique<LockedAccessor<Hal2AidlMapper>>(*mMapper, mutex);
1132 Hal2AidlMapper::Cleanups cleanups(*mapperAccessor);
1133 ASSERT_EQ(OK, mMapper->createOrUpdatePatch({mMixPortConfig}, {mDevicePortConfig}, patchId,
1134 &cleanups));
1135 cleanups.disarmAll();
1136 }
1137
DisconnectDevice()1138 void DisconnectDevice() {
1139 ASSERT_EQ(OK, mMapper->prepareToDisconnectExternalDevice(mConnectedPort));
1140 ASSERT_EQ(OK, mMapper->setDevicePortConnectedState(mConnectedPort, false /*connected*/));
1141 }
1142
ReleaseFwkOnlyPatch(int32_t patchId)1143 void ReleaseFwkOnlyPatch(int32_t patchId) {
1144 // The patch only exists for the framework.
1145 EXPECT_EQ(patchId, mMapper->findFwkPatch(patchId));
1146 ASSERT_EQ(BAD_VALUE, mMapper->releaseAudioPatch(patchId));
1147 mMapper->eraseFwkPatch(patchId);
1148 // The patch is now erased.
1149 EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1150 }
1151
1152 std::shared_ptr<ModuleMock> mModule;
1153 std::unique_ptr<Hal2AidlMapper> mMapper;
1154 AudioPort mConnectedPort;
1155 AudioPortConfig mMixPortConfig;
1156 AudioPortConfig mDevicePortConfig;
1157 AudioPatch mPatch;
1158 sp<StreamHalInterface> mStream;
1159 };
1160
1161 /**
1162 * External device connections and patches tests diagram.
1163 *
1164 * [Connect device] -> [Create Stream]
1165 * |-> [ (1) Close Stream] -> [Disconnect Device]
1166 * |-> [ (2) Disconnect Device]
1167 * | |-> [ (3) Close Stream]
1168 * | \-> [ (4) Connect Another Device]
1169 * | |-> (1)
1170 * | |-> (2) -> (3)
1171 * | \-> (5) -> (7)
1172 * \-> [ (5) Create/Update Fwk Patch]
1173 * |-> [(6) Release Fwk Patch]
1174 * | |-> (1)
1175 * | \-> (2) (including reconnection)
1176 * \-> [(7) Disconnect Device]
1177 * |-> [Release Fwk Patch] -> [Close Stream]
1178 * \-> (4) -> (5) -> (6) -> (1)
1179 *
1180 * Note that the test (acting on behalf of DeviceHalAidl) is responsible
1181 * for calling `eraseFwkPatch` and `updateFwkPatch` when needed.
1182 */
1183
1184 // (1)
TEST_F(Hal2AidlMapperTest,CloseDisconnect)1185 TEST_F(Hal2AidlMapperTest, CloseDisconnect) {
1186 ASSERT_NO_FATAL_FAILURE(CloseDisconnectImpl());
1187 // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1188 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1189 }
1190
1191 // (2) -> (3)
TEST_F(Hal2AidlMapperTest,DisconnectClose)1192 TEST_F(Hal2AidlMapperTest, DisconnectClose) {
1193 ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1194 // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1195 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1196 mStream.clear();
1197 }
1198
1199 // (2) -> (4) -> (1)
TEST_F(Hal2AidlMapperTest,DisconnectConnectCloseDisconnect)1200 TEST_F(Hal2AidlMapperTest, DisconnectConnectCloseDisconnect) {
1201 ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1202 // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1203 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1204 ASSERT_NO_FATAL_FAILURE(ConnectAnotherDevice());
1205 ASSERT_NO_FATAL_FAILURE(CloseDisconnectImpl());
1206 // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1207 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1208 }
1209
1210 // (2) -> (4) -> (2) -> (3)
TEST_F(Hal2AidlMapperTest,DisconnectConnectDisconnectClose)1211 TEST_F(Hal2AidlMapperTest, DisconnectConnectDisconnectClose) {
1212 ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1213 // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1214 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1215 ASSERT_NO_FATAL_FAILURE(ConnectAnotherDevice());
1216 ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1217 // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1218 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1219 mStream.clear();
1220 }
1221
1222 // (5) -> (6) -> (1)
TEST_F(Hal2AidlMapperTest,CreateFwkPatchReleaseCloseDisconnect)1223 TEST_F(Hal2AidlMapperTest, CreateFwkPatchReleaseCloseDisconnect) {
1224 int32_t patchId;
1225 ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&patchId));
1226 // Must be the patch created during stream opening.
1227 ASSERT_EQ(mPatch.id, patchId);
1228 // The patch was not reset by HAL, must not be listed under fwkPatches.
1229 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1230
1231 ASSERT_EQ(OK, mMapper->releaseAudioPatch(patchId));
1232 // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1233 EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1234 ASSERT_NO_FATAL_FAILURE(CloseDisconnectImpl());
1235 // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1236 EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1237 }
1238
1239 // (5) -> (6) -> (2) -> (3)
TEST_F(Hal2AidlMapperTest,CreateFwkPatchReleaseDisconnectClose)1240 TEST_F(Hal2AidlMapperTest, CreateFwkPatchReleaseDisconnectClose) {
1241 int32_t patchId;
1242 ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&patchId));
1243 // Must be the patch created during stream opening.
1244 ASSERT_EQ(mPatch.id, patchId);
1245 // The patch was not reset by HAL, must not be listed under fwkPatches.
1246 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1247
1248 ASSERT_EQ(OK, mMapper->releaseAudioPatch(patchId));
1249 // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1250 EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1251 ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1252 // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1253 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1254 mStream.clear();
1255 }
1256
1257 // (5) -> (6) -> (2) -> (4) -> (2) -> (3)
TEST_F(Hal2AidlMapperTest,CreateFwkPatchReleaseDisconnectConnectDisconnectClose)1258 TEST_F(Hal2AidlMapperTest, CreateFwkPatchReleaseDisconnectConnectDisconnectClose) {
1259 int32_t patchId;
1260 ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&patchId));
1261 // Must be the patch created during stream opening.
1262 ASSERT_EQ(mPatch.id, patchId);
1263 // The patch was not reset by HAL, must not be listed under fwkPatches.
1264 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1265
1266 ASSERT_EQ(OK, mMapper->releaseAudioPatch(patchId));
1267 // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1268 EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1269 ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1270 // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1271 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1272
1273 ASSERT_NO_FATAL_FAILURE(ConnectAnotherDevice());
1274 ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1275 // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1276 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1277 mStream.clear();
1278 }
1279
1280 // (5) -> (7) -> Release -> Close
TEST_F(Hal2AidlMapperTest,CreateFwkPatchDisconnectReleaseClose)1281 TEST_F(Hal2AidlMapperTest, CreateFwkPatchDisconnectReleaseClose) {
1282 int32_t patchId;
1283 ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&patchId));
1284 // Must be the patch created during stream opening.
1285 ASSERT_EQ(mPatch.id, patchId);
1286 // The patch was not reset by HAL, must not be listed under fwkPatches.
1287 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1288
1289 ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1290 ASSERT_NO_FATAL_FAILURE(ReleaseFwkOnlyPatch(patchId));
1291
1292 mStream.clear();
1293 EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1294 }
1295
1296 // (5) -> (7) -> (4) -> (5) -> (6) -> (1)
TEST_F(Hal2AidlMapperTest,CreateFwkPatchDisconnectConnectUpdateReleaseCloseDisconnect)1297 TEST_F(Hal2AidlMapperTest, CreateFwkPatchDisconnectConnectUpdateReleaseCloseDisconnect) {
1298 int32_t patchId;
1299 ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&patchId));
1300 // Must be the patch created during stream opening.
1301 ASSERT_EQ(mPatch.id, patchId);
1302 // The patch was not reset by HAL, must not be listed under fwkPatches.
1303 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1304
1305 ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1306 // The patch now only exists for the framework.
1307 EXPECT_EQ(mPatch.id, mMapper->findFwkPatch(mPatch.id));
1308
1309 ASSERT_NO_FATAL_FAILURE(ConnectAnotherDevice());
1310 // Change the device address locally, for patch update.
1311 mDevicePortConfig.ext.get<AudioPortExt::device>().device.address =
1312 mConnectedPort.ext.get<AudioPortExt::device>().device.address;
1313 int32_t newPatchId = patchId;
1314 ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&newPatchId));
1315 EXPECT_NE(patchId, newPatchId);
1316 mMapper->updateFwkPatch(patchId, newPatchId);
1317 EXPECT_EQ(newPatchId, mMapper->findFwkPatch(patchId));
1318 // Just in case, check that HAL patch ID is not listed as a fwk patch.
1319 EXPECT_EQ(0, mMapper->findFwkPatch(newPatchId));
1320 // Verify that device port config was updated.
1321 ASSERT_EQ(OK, mMapper->findPortConfig(mConnectedPort.ext.get<AudioPortExt::device>().device,
1322 &mDevicePortConfig));
1323
1324 ASSERT_EQ(OK, mMapper->releaseAudioPatch(newPatchId));
1325 // The patch does not exist both for the fwk and the HAL, must not be listed under fwkPatches.
1326 EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1327 // Just in case, check that HAL patch ID is not listed.
1328 EXPECT_EQ(0, mMapper->findFwkPatch(newPatchId));
1329
1330 ASSERT_NO_FATAL_FAILURE(CloseDisconnectImpl());
1331 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1332 EXPECT_EQ(0, mMapper->findFwkPatch(patchId));
1333 EXPECT_EQ(0, mMapper->findFwkPatch(newPatchId));
1334 }
1335
1336 // (2) -> (4) -> (5) -> (7) -> Release -> Close
TEST_F(Hal2AidlMapperTest,DisconnectConnectCreateFwkPatchDisconnectReleaseClose)1337 TEST_F(Hal2AidlMapperTest, DisconnectConnectCreateFwkPatchDisconnectReleaseClose) {
1338 const int32_t patchId = mPatch.id;
1339 ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1340 // The patch is owned by HAL, must not be listed under fwkPatches after disconnection.
1341 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1342
1343 ASSERT_NO_FATAL_FAILURE(ConnectAnotherDevice());
1344 // Change the device address locally, for patch update.
1345 mDevicePortConfig.ext.get<AudioPortExt::device>().device.address =
1346 mConnectedPort.ext.get<AudioPortExt::device>().device.address;
1347 int32_t newPatchId = 0; // Use 0 since the fwk does not know about the HAL patch.
1348 EXPECT_EQ(0, mMapper->findFwkPatch(newPatchId));
1349 ASSERT_NO_FATAL_FAILURE(CreateFwkPatch(&newPatchId));
1350 EXPECT_NE(0, newPatchId);
1351 EXPECT_NE(patchId, newPatchId);
1352 // Just in case, check that HAL patch ID is not listed as a fwk patch.
1353 EXPECT_EQ(0, mMapper->findFwkPatch(newPatchId));
1354 // Verify that device port config was updated.
1355 ASSERT_EQ(OK, mMapper->findPortConfig(mConnectedPort.ext.get<AudioPortExt::device>().device,
1356 &mDevicePortConfig));
1357
1358 ASSERT_NO_FATAL_FAILURE(DisconnectDevice());
1359 ASSERT_NO_FATAL_FAILURE(ReleaseFwkOnlyPatch(newPatchId));
1360
1361 mStream.clear();
1362 EXPECT_EQ(0, mMapper->findFwkPatch(mPatch.id));
1363 EXPECT_EQ(0, mMapper->findFwkPatch(newPatchId));
1364 }
1365
TEST_F(Hal2AidlMapperTest,ChangeTransientPatchDevice)1366 TEST_F(Hal2AidlMapperTest, ChangeTransientPatchDevice) {
1367 std::mutex mutex; // Only needed for cleanups.
1368 auto mapperAccessor = std::make_unique<LockedAccessor<Hal2AidlMapper>>(*mMapper, mutex);
1369 Hal2AidlMapper::Cleanups cleanups(*mapperAccessor);
1370 AudioConfig config;
1371 config.base.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
1372 AudioChannelLayout::LAYOUT_STEREO);
1373 config.base.format =
1374 AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT};
1375 config.base.sampleRate = 48000;
1376 AudioDevice defaultDevice;
1377 defaultDevice.type.type = AudioDeviceType::IN_DEFAULT;
1378 AudioPortConfig mixPortConfig;
1379 AudioPatch transientPatch;
1380 ASSERT_EQ(OK, mMapper->prepareToOpenStream(43 /*ioHandle*/, defaultDevice,
1381 AudioIoFlags::make<AudioIoFlags::input>(0),
1382 AudioSource::DEFAULT, &cleanups, &config,
1383 &mixPortConfig, &transientPatch));
1384 cleanups.disarmAll();
1385 ASSERT_NE(0, transientPatch.id);
1386 ASSERT_NE(0, mixPortConfig.id);
1387 sp<StreamHalInterface> stream = sp<StreamHalMock>::make();
1388 mMapper->addStream(stream, mixPortConfig.id, transientPatch.id);
1389
1390 AudioPatch patch{};
1391 int32_t patchId;
1392 AudioPortConfig backMicPortConfig;
1393 backMicPortConfig.channelMask = config.base.channelMask;
1394 backMicPortConfig.format = config.base.format;
1395 backMicPortConfig.sampleRate = aidl::android::media::audio::common::Int{config.base.sampleRate};
1396 backMicPortConfig.flags = AudioIoFlags::make<AudioIoFlags::input>(0);
1397 backMicPortConfig.ext = createPortDeviceExt(AudioDeviceType::IN_MICROPHONE_BACK, 0);
1398 ASSERT_EQ(OK, mMapper->createOrUpdatePatch({backMicPortConfig}, {mixPortConfig}, &patchId,
1399 &cleanups));
1400 cleanups.disarmAll();
1401 ASSERT_EQ(android::OK,
1402 mMapper->findPortConfig(backMicPortConfig.ext.get<AudioPortExt::device>().device,
1403 &backMicPortConfig));
1404 EXPECT_NE(0, backMicPortConfig.id);
1405
1406 EXPECT_EQ(transientPatch.id, patchId);
1407 auto patches = mModule->getPatches();
1408 auto patchIt = findById(patches, patchId);
1409 ASSERT_NE(patchIt, patches.end());
1410 EXPECT_EQ(std::vector<int32_t>{backMicPortConfig.id}, patchIt->sourcePortConfigIds);
1411 EXPECT_EQ(std::vector<int32_t>{mixPortConfig.id}, patchIt->sinkPortConfigIds);
1412 }
1413
TEST_F(Hal2AidlMapperTest,SetAudioPortConfigGainChangeExistingPortConfig)1414 TEST_F(Hal2AidlMapperTest, SetAudioPortConfigGainChangeExistingPortConfig) {
1415 // First set config, then update gain.
1416 AudioPortConfig speakerPortConfig;
1417 speakerPortConfig.ext = createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0);
1418 speakerPortConfig.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
1419 AudioChannelLayout::LAYOUT_STEREO);
1420 speakerPortConfig.format =
1421 AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT};
1422 speakerPortConfig.sampleRate = ::aidl::android::media::audio::common::Int(48000);
1423 AudioPortConfig resultingPortConfig;
1424 ASSERT_EQ(OK,
1425 mMapper->setPortConfig(speakerPortConfig, std::set<int32_t>(), &resultingPortConfig));
1426 EXPECT_NE(0, resultingPortConfig.id);
1427 EXPECT_NE(0, resultingPortConfig.portId);
1428
1429 AudioPortConfig gainUpdate;
1430 gainUpdate.ext = createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0);
1431 AudioGainConfig gainConfig{.index = -1,
1432 .mode = 1 << static_cast<int>(AudioGainMode::JOINT),
1433 .channelMask = AudioChannelLayout{},
1434 .values = std::vector<int32_t>{-3200},
1435 .rampDurationMs = 0};
1436 gainUpdate.gain = gainConfig;
1437 AudioPortConfig resultingGainUpdate;
1438 ASSERT_EQ(OK, mMapper->setPortConfig(gainUpdate, std::set<int32_t>(), &resultingGainUpdate));
1439 EXPECT_EQ(resultingPortConfig.id, resultingGainUpdate.id);
1440 auto updatedPortConfig = mModule->getPortConfig(resultingGainUpdate.id);
1441 ASSERT_TRUE(updatedPortConfig.has_value());
1442 ASSERT_TRUE(updatedPortConfig->gain.has_value());
1443 EXPECT_EQ(gainConfig, updatedPortConfig->gain);
1444 }
1445
TEST_F(Hal2AidlMapperTest,SetAudioPortConfigGainChangeFromScratch)1446 TEST_F(Hal2AidlMapperTest, SetAudioPortConfigGainChangeFromScratch) {
1447 // Set gain as the first operation, the HAL should suggest the rest of the configuration.
1448 AudioPortConfig gainSet;
1449 gainSet.ext = createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0);
1450 AudioGainConfig gainConfig{.index = -1,
1451 .mode = 1 << static_cast<int>(AudioGainMode::JOINT),
1452 .channelMask = AudioChannelLayout{},
1453 .values = std::vector<int32_t>{-3200},
1454 .rampDurationMs = 0};
1455 gainSet.gain = gainConfig;
1456 AudioPortConfig resultingPortConfig;
1457 ASSERT_EQ(OK, mMapper->setPortConfig(gainSet, std::set<int32_t>(), &resultingPortConfig));
1458 EXPECT_NE(0, resultingPortConfig.id);
1459 EXPECT_NE(0, resultingPortConfig.portId);
1460 auto portConfig = mModule->getPortConfig(resultingPortConfig.id);
1461 ASSERT_TRUE(portConfig.has_value());
1462 ASSERT_TRUE(portConfig->gain.has_value());
1463 EXPECT_EQ(gainConfig, portConfig->gain);
1464 }
1465