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