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