1 // Copyright (C) 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "DeviceImpl.h"
16
17 #include <android-base/logging.h>
18 #include <android-base/strings.h>
19 #include <system/audio-hal-enums.h>
20 #include <utils/RefBase.h>
21
22 #include <optional>
23
24 #include "AidlTypes.h"
25 #include "AudioUtil.h"
26 #include "BusOutputStream.h"
27 #include "BusStreamProvider.h"
28 #include "ServiceConfig.h"
29 #include "StreamOutImpl.h"
30
31 using namespace ::android::hardware::audio::common::CPP_VERSION;
32 using namespace ::android::hardware::audio::CPP_VERSION;
33
34 using ::android::wp;
35
36 namespace audio_proxy {
37 namespace service {
38 namespace {
39 AudioPatchHandle gNextAudioPatchHandle = 1;
40
41 #if MAJOR_VERSION >= 7
toAidlAudioConfig(const AudioConfigBase & hidl_config)42 std::optional<AidlAudioConfig> toAidlAudioConfig(
43 const AudioConfigBase& hidl_config) {
44 audio_format_t format = AUDIO_FORMAT_INVALID;
45 if (!audio_format_from_string(hidl_config.format.c_str(), &format)) {
46 return std::nullopt;
47 }
48
49 audio_channel_mask_t channelMask = AUDIO_CHANNEL_INVALID;
50 if (!audio_channel_mask_from_string(hidl_config.channelMask.c_str(),
51 &channelMask)) {
52 return std::nullopt;
53 }
54
55 AidlAudioConfig aidlConfig = {
56 .format = static_cast<AidlAudioFormat>(format),
57 .sampleRateHz = static_cast<int32_t>(hidl_config.sampleRateHz),
58 .channelMask = static_cast<AidlAudioChannelMask>(channelMask),
59 .bufferSizeBytes = 0,
60 .latencyMs = 0};
61
62 return aidlConfig;
63 }
64
toAidlAudioOutputFlags(const hidl_vec<AudioInOutFlag> & flags)65 std::optional<int32_t> toAidlAudioOutputFlags(
66 const hidl_vec<AudioInOutFlag>& flags) {
67 int32_t outputFlags = static_cast<int32_t>(AUDIO_OUTPUT_FLAG_NONE);
68 for (const auto& flag : flags) {
69 audio_output_flags_t outputFlag = AUDIO_OUTPUT_FLAG_NONE;
70 if (audio_output_flag_from_string(flag.c_str(), &outputFlag)) {
71 outputFlags |= static_cast<int32_t>(outputFlag);
72 } else {
73 return std::nullopt;
74 }
75 }
76
77 return outputFlags;
78 }
79
checkSourceMetadata(const SourceMetadata & metadata)80 bool checkSourceMetadata(const SourceMetadata& metadata) {
81 for (const auto& track : metadata.tracks) {
82 audio_usage_t usage;
83 if (!audio_usage_from_string(track.usage.c_str(), &usage)) {
84 return false;
85 }
86
87 audio_content_type_t contentType;
88 if (!audio_content_type_from_string(track.contentType.c_str(),
89 &contentType)) {
90 return false;
91 }
92
93 audio_channel_mask_t channelMask;
94 if (!audio_channel_mask_from_string(track.channelMask.c_str(),
95 &channelMask)) {
96 return false;
97 }
98
99 // From types.hal:
100 // Tags are set by vendor specific applications and must be prefixed by
101 // "VX_". Vendor must namespace their tag names to avoid conflicts. See
102 // 'vendorExtension' in audio_policy_configuration.xsd for a formal
103 // definition.
104 //
105 // From audio_policy_configuration.xsd:
106 // Vendor extension names must be prefixed by "VX_" to distinguish them from
107 // AOSP values. Vendors must namespace their names to avoid conflicts. The
108 // namespace part must only use capital latin characters and decimal digits
109 // and consist of at least 3 characters.
110 for (const auto& tag : track.tags) {
111 if (!android::base::StartsWith(tag.c_str(), "VX_")) {
112 return false;
113 }
114 }
115 }
116
117 return true;
118 }
119
checkAudioPortConfig(const AudioPortConfig & config)120 bool checkAudioPortConfig(const AudioPortConfig& config) {
121 if (config.base.format.getDiscriminator() ==
122 AudioConfigBaseOptional::Format::hidl_discriminator::value) {
123 audio_format_t format;
124 if (!audio_format_from_string(config.base.format.value().c_str(),
125 &format)) {
126 return false;
127 }
128 }
129
130 if (config.base.channelMask.getDiscriminator() ==
131 AudioConfigBaseOptional::ChannelMask::hidl_discriminator::value) {
132 audio_channel_mask_t channelMask;
133 if (!audio_channel_mask_from_string(config.base.channelMask.value().c_str(),
134 &channelMask)) {
135 return false;
136 }
137 }
138
139 if (config.gain.getDiscriminator() ==
140 AudioPortConfig::OptionalGain::hidl_discriminator::config) {
141 for (const auto& mode : config.gain.config().mode) {
142 audio_gain_mode_t gainMode;
143 if (!audio_gain_mode_from_string(mode.c_str(), &gainMode)) {
144 return false;
145 }
146 }
147
148 audio_channel_mask_t channelMask;
149 if (!audio_channel_mask_from_string(
150 config.gain.config().channelMask.c_str(), &channelMask)) {
151 return false;
152 }
153 }
154
155 if (config.ext.getDiscriminator() ==
156 AudioPortExtendedInfo::hidl_discriminator::device) {
157 audio_devices_t deviceType;
158 if (!audio_device_from_string(config.ext.device().deviceType.c_str(),
159 &deviceType)) {
160 return false;
161 }
162 }
163
164 if (config.ext.getDiscriminator() ==
165 AudioPortExtendedInfo::hidl_discriminator::mix) {
166 const auto& useCase = config.ext.mix().useCase;
167 if (useCase.getDiscriminator() == AudioPortExtendedInfo::AudioPortMixExt::
168 UseCase::hidl_discriminator::stream) {
169 audio_stream_type_t audioStreamType;
170 if (!audio_stream_type_from_string(useCase.stream().c_str(),
171 &audioStreamType)) {
172 return false;
173 }
174 } else {
175 audio_source_t audioSource;
176 if (!audio_source_from_string(useCase.source().c_str(), &audioSource)) {
177 return false;
178 }
179 }
180 }
181
182 return true;
183 }
184 #else
toAidlAudioConfig(const AudioConfig & hidl_config)185 AidlAudioConfig toAidlAudioConfig(const AudioConfig& hidl_config) {
186 AidlAudioConfig aidlConfig = {
187 .format = static_cast<AidlAudioFormat>(hidl_config.format),
188 .sampleRateHz = static_cast<int32_t>(hidl_config.sampleRateHz),
189 .channelMask = static_cast<AidlAudioChannelMask>(hidl_config.channelMask),
190 .bufferSizeBytes = 0,
191 .latencyMs = 0};
192
193 return aidlConfig;
194 }
195
196 // Before 7.0, the fields are using enum instead of string. There's no need to
197 // validate them.
checkAudioPortConfig(const AudioPortConfig & config)198 bool checkAudioPortConfig(const AudioPortConfig& config) { return true; }
199 #endif
200 } // namespace
201
DeviceImpl(BusStreamProvider & busStreamProvider,const ServiceConfig & serviceConfig)202 DeviceImpl::DeviceImpl(BusStreamProvider& busStreamProvider,
203 const ServiceConfig& serviceConfig)
204 : mBusStreamProvider(busStreamProvider), mServiceConfig(serviceConfig) {}
205
206 // Methods from ::android::hardware::audio::V5_0::IDevice follow.
initCheck()207 Return<Result> DeviceImpl::initCheck() { return Result::OK; }
208
setMasterVolume(float volume)209 Return<Result> DeviceImpl::setMasterVolume(float volume) {
210 // software mixer will emulate this ability
211 return Result::NOT_SUPPORTED;
212 }
213
getMasterVolume(getMasterVolume_cb _hidl_cb)214 Return<void> DeviceImpl::getMasterVolume(getMasterVolume_cb _hidl_cb) {
215 _hidl_cb(Result::NOT_SUPPORTED, 0.f);
216 return Void();
217 }
218
setMicMute(bool mute)219 Return<Result> DeviceImpl::setMicMute(bool mute) {
220 return Result::NOT_SUPPORTED;
221 }
222
getMicMute(getMicMute_cb _hidl_cb)223 Return<void> DeviceImpl::getMicMute(getMicMute_cb _hidl_cb) {
224 _hidl_cb(Result::NOT_SUPPORTED, false);
225 return Void();
226 }
227
setMasterMute(bool mute)228 Return<Result> DeviceImpl::setMasterMute(bool mute) {
229 return Result::NOT_SUPPORTED;
230 }
231
getMasterMute(getMasterMute_cb _hidl_cb)232 Return<void> DeviceImpl::getMasterMute(getMasterMute_cb _hidl_cb) {
233 _hidl_cb(Result::NOT_SUPPORTED, false);
234 return Void();
235 }
236
getInputBufferSize(const AudioConfig & config,getInputBufferSize_cb _hidl_cb)237 Return<void> DeviceImpl::getInputBufferSize(const AudioConfig& config,
238 getInputBufferSize_cb _hidl_cb) {
239 _hidl_cb(Result::NOT_SUPPORTED, 0);
240 return Void();
241 }
242
243 #if MAJOR_VERSION >= 7
244 template <typename CallbackType>
openOutputStreamImpl(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,const hidl_vec<AudioInOutFlag> & flags,const SourceMetadata & sourceMetadata,CallbackType _hidl_cb)245 Return<void> DeviceImpl::openOutputStreamImpl(
246 int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
247 const hidl_vec<AudioInOutFlag>& flags, const SourceMetadata& sourceMetadata,
248 CallbackType _hidl_cb) {
249 std::optional<AidlAudioConfig> aidlConfig = toAidlAudioConfig(config.base);
250 if (!aidlConfig) {
251 _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, {});
252 return Void();
253 }
254
255 std::optional<int32_t> outputFlags = toAidlAudioOutputFlags(flags);
256 if (!outputFlags) {
257 _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, {});
258 return Void();
259 }
260
261 if (!checkSourceMetadata(sourceMetadata)) {
262 _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, {});
263 return Void();
264 }
265
266 std::string address;
267
268 // Default device is used for VTS test.
269 if (device.deviceType == "AUDIO_DEVICE_OUT_DEFAULT") {
270 address = "default";
271 } else if (device.deviceType == "AUDIO_DEVICE_OUT_BUS") {
272 address = device.address.id();
273 } else {
274 _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, {});
275 return Void();
276 }
277
278 const auto configIt = mServiceConfig.streams.find(address);
279 if (configIt == mServiceConfig.streams.end()) {
280 _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, {});
281 return Void();
282 }
283
284 std::shared_ptr<BusOutputStream> busOutputStream =
285 mBusStreamProvider.openOutputStream(
286 address, *aidlConfig, *outputFlags,
287 computeBufferSizeBytes(*aidlConfig, configIt->second.bufferSizeMs),
288 configIt->second.latencyMs);
289 DCHECK(busOutputStream);
290 auto streamOut =
291 sp<StreamOutImpl>::make(std::move(busOutputStream), config.base);
292 mBusStreamProvider.onStreamOutCreated(streamOut);
293 _hidl_cb(Result::OK, streamOut, config);
294 return Void();
295 }
296
openOutputStream(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,const hidl_vec<AudioInOutFlag> & flags,const SourceMetadata & sourceMetadata,openOutputStream_cb _hidl_cb)297 Return<void> DeviceImpl::openOutputStream(int32_t ioHandle,
298 const DeviceAddress& device,
299 const AudioConfig& config,
300 const hidl_vec<AudioInOutFlag>& flags,
301 const SourceMetadata& sourceMetadata,
302 openOutputStream_cb _hidl_cb) {
303 return openOutputStreamImpl(ioHandle, device, config, flags, sourceMetadata,
304 _hidl_cb);
305 }
306
openInputStream(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,const hidl_vec<AudioInOutFlag> & flags,const SinkMetadata & sinkMetadata,openInputStream_cb _hidl_cb)307 Return<void> DeviceImpl::openInputStream(int32_t ioHandle,
308 const DeviceAddress& device,
309 const AudioConfig& config,
310 const hidl_vec<AudioInOutFlag>& flags,
311 const SinkMetadata& sinkMetadata,
312 openInputStream_cb _hidl_cb) {
313 _hidl_cb(Result::NOT_SUPPORTED, sp<IStreamIn>(), config);
314 return Void();
315 }
316 #else
openOutputStream(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,hidl_bitfield<AudioOutputFlag> flags,const SourceMetadata & sourceMetadata,openOutputStream_cb _hidl_cb)317 Return<void> DeviceImpl::openOutputStream(int32_t ioHandle,
318 const DeviceAddress& device,
319 const AudioConfig& config,
320 hidl_bitfield<AudioOutputFlag> flags,
321 const SourceMetadata& sourceMetadata,
322 openOutputStream_cb _hidl_cb) {
323 std::string address;
324 if (device.device == AudioDevice::OUT_DEFAULT) {
325 address = "default";
326 } else if (device.device == AudioDevice::OUT_BUS) {
327 address = device.busAddress;
328 } else {
329 _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, {});
330 return Void();
331 }
332
333 const auto configIt = mServiceConfig.streams.find(address);
334 if (configIt == mServiceConfig.streams.end()) {
335 _hidl_cb(Result::INVALID_ARGUMENTS, nullptr, {});
336 return Void();
337 }
338
339 auto aidlConfig = toAidlAudioConfig(config);
340 std::shared_ptr<BusOutputStream> busOutputStream =
341 mBusStreamProvider.openOutputStream(
342 address, aidlConfig, static_cast<int32_t>(flags),
343 computeBufferSizeBytes(aidlConfig, configIt->second.bufferSizeMs),
344 configIt->second.latencyMs);
345 DCHECK(busOutputStream);
346 auto streamOut = sp<StreamOutImpl>::make(std::move(busOutputStream), config);
347 mBusStreamProvider.onStreamOutCreated(streamOut);
348 _hidl_cb(Result::OK, streamOut, config);
349 return Void();
350 }
351
openInputStream(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,hidl_bitfield<AudioInputFlag> flags,const SinkMetadata & sinkMetadata,openInputStream_cb _hidl_cb)352 Return<void> DeviceImpl::openInputStream(int32_t ioHandle,
353 const DeviceAddress& device,
354 const AudioConfig& config,
355 hidl_bitfield<AudioInputFlag> flags,
356 const SinkMetadata& sinkMetadata,
357 openInputStream_cb _hidl_cb) {
358 _hidl_cb(Result::NOT_SUPPORTED, sp<IStreamIn>(), config);
359 return Void();
360 }
361 #endif
362
supportsAudioPatches()363 Return<bool> DeviceImpl::supportsAudioPatches() { return true; }
364
365 // Create a do-nothing audio patch.
createAudioPatch(const hidl_vec<AudioPortConfig> & sources,const hidl_vec<AudioPortConfig> & sinks,createAudioPatch_cb _hidl_cb)366 Return<void> DeviceImpl::createAudioPatch(
367 const hidl_vec<AudioPortConfig>& sources,
368 const hidl_vec<AudioPortConfig>& sinks, createAudioPatch_cb _hidl_cb) {
369 for (const auto& config : sources) {
370 if (!checkAudioPortConfig(config)) {
371 _hidl_cb(Result::INVALID_ARGUMENTS, 0);
372 return Void();
373 }
374 }
375
376 for (const auto& config : sinks) {
377 if (!checkAudioPortConfig(config)) {
378 _hidl_cb(Result::INVALID_ARGUMENTS, 0);
379 return Void();
380 }
381 }
382
383 AudioPatchHandle handle = gNextAudioPatchHandle++;
384 mAudioPatchHandles.insert(handle);
385 _hidl_cb(Result::OK, handle);
386 return Void();
387 }
388
releaseAudioPatch(AudioPatchHandle patch)389 Return<Result> DeviceImpl::releaseAudioPatch(AudioPatchHandle patch) {
390 size_t removed = mAudioPatchHandles.erase(patch);
391 return removed > 0 ? Result::OK : Result::INVALID_ARGUMENTS;
392 }
393
getAudioPort(const AudioPort & port,getAudioPort_cb _hidl_cb)394 Return<void> DeviceImpl::getAudioPort(const AudioPort& port,
395 getAudioPort_cb _hidl_cb) {
396 _hidl_cb(Result::NOT_SUPPORTED, port);
397 return Void();
398 }
399
setAudioPortConfig(const AudioPortConfig & config)400 Return<Result> DeviceImpl::setAudioPortConfig(const AudioPortConfig& config) {
401 return Result::NOT_SUPPORTED;
402 }
403
getHwAvSync(getHwAvSync_cb _hidl_cb)404 Return<void> DeviceImpl::getHwAvSync(getHwAvSync_cb _hidl_cb) {
405 _hidl_cb(Result::NOT_SUPPORTED, 0);
406 return Void();
407 }
408
setScreenState(bool turnedOn)409 Return<Result> DeviceImpl::setScreenState(bool turnedOn) {
410 return Result::NOT_SUPPORTED;
411 }
412
getParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)413 Return<void> DeviceImpl::getParameters(const hidl_vec<ParameterValue>& context,
414 const hidl_vec<hidl_string>& keys,
415 getParameters_cb _hidl_cb) {
416 _hidl_cb(Result::NOT_SUPPORTED, hidl_vec<ParameterValue>());
417 return Void();
418 }
419
setParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<ParameterValue> & parameters)420 Return<Result> DeviceImpl::setParameters(
421 const hidl_vec<ParameterValue>& context,
422 const hidl_vec<ParameterValue>& parameters) {
423 return Result::NOT_SUPPORTED;
424 }
425
getMicrophones(getMicrophones_cb _hidl_cb)426 Return<void> DeviceImpl::getMicrophones(getMicrophones_cb _hidl_cb) {
427 _hidl_cb(Result::NOT_SUPPORTED, hidl_vec<MicrophoneInfo>());
428 return Void();
429 }
430
setConnectedState(const DeviceAddress & address,bool connected)431 Return<Result> DeviceImpl::setConnectedState(const DeviceAddress& address,
432 bool connected) {
433 #if MAJOR_VERSION >= 7
434 audio_devices_t deviceType = AUDIO_DEVICE_NONE;
435 if (!audio_device_from_string(address.deviceType.c_str(), &deviceType)) {
436 return Result::INVALID_ARGUMENTS;
437 }
438
439 if (deviceType != AUDIO_DEVICE_OUT_BUS) {
440 return Result::NOT_SUPPORTED;
441 }
442
443 const auto& busAddress = address.address.id();
444 #else
445 if (address.device != AudioDevice::OUT_BUS) {
446 return Result::NOT_SUPPORTED;
447 }
448
449 const auto& busAddress = address.busAddress;
450 #endif
451
452 return mServiceConfig.streams.count(busAddress) > 0 ? Result::OK
453 : Result::NOT_SUPPORTED;
454 }
455
456 #if MAJOR_VERSION >= 6
updateAudioPatch(AudioPatchHandle previousPatch,const hidl_vec<AudioPortConfig> & sources,const hidl_vec<AudioPortConfig> & sinks,updateAudioPatch_cb _hidl_cb)457 Return<void> DeviceImpl::updateAudioPatch(
458 AudioPatchHandle previousPatch, const hidl_vec<AudioPortConfig>& sources,
459 const hidl_vec<AudioPortConfig>& sinks, updateAudioPatch_cb _hidl_cb) {
460 if (mAudioPatchHandles.erase(previousPatch) == 0) {
461 _hidl_cb(Result::INVALID_ARGUMENTS, 0);
462 return Void();
463 }
464 AudioPatchHandle newPatch = gNextAudioPatchHandle++;
465 mAudioPatchHandles.insert(newPatch);
466 _hidl_cb(Result::OK, newPatch);
467 return Void();
468 }
469
close()470 Return<Result> DeviceImpl::close() {
471 return mBusStreamProvider.cleanAndCountStreamOuts() == 0
472 ? Result::OK
473 : Result::INVALID_STATE;
474 }
475
addDeviceEffect(AudioPortHandle device,uint64_t effectId)476 Return<Result> DeviceImpl::addDeviceEffect(AudioPortHandle device,
477 uint64_t effectId) {
478 return Result::NOT_SUPPORTED;
479 }
480
removeDeviceEffect(AudioPortHandle device,uint64_t effectId)481 Return<Result> DeviceImpl::removeDeviceEffect(AudioPortHandle device,
482 uint64_t effectId) {
483 return Result::NOT_SUPPORTED;
484 }
485 #endif
486
487 #if MAJOR_VERSION == 7 && MINOR_VERSION == 1
openOutputStream_7_1(int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,const hidl_vec<AudioInOutFlag> & flags,const SourceMetadata & sourceMetadata,openOutputStream_7_1_cb _hidl_cb)488 Return<void> DeviceImpl::openOutputStream_7_1(
489 int32_t ioHandle, const DeviceAddress& device, const AudioConfig& config,
490 const hidl_vec<AudioInOutFlag>& flags, const SourceMetadata& sourceMetadata,
491 openOutputStream_7_1_cb _hidl_cb) {
492 return openOutputStreamImpl(ioHandle, device, config, flags, sourceMetadata,
493 _hidl_cb);
494 }
495
setConnectedState_7_1(const AudioPort & devicePort,bool connected)496 Return<Result> DeviceImpl::setConnectedState_7_1(const AudioPort& devicePort,
497 bool connected) {
498 return Result::OK;
499 }
500 #endif
501
502 } // namespace service
503 } // namespace audio_proxy
504