• 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 "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