• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 #define LOG_TAG "StreamHAL"
18 
19 #include "core/default/Stream.h"
20 #include "common/all-versions/HidlSupport.h"
21 #include "common/all-versions/default/EffectMap.h"
22 #include "core/default/Util.h"
23 
24 #include <inttypes.h>
25 
26 #include <HidlUtils.h>
27 #include <android/log.h>
28 #include <hardware/audio.h>
29 #include <hardware/audio_effect.h>
30 #include <media/AudioContainers.h>
31 #include <media/TypeConverter.h>
32 #include <util/CoreUtils.h>
33 
34 namespace android {
35 namespace hardware {
36 namespace audio {
37 namespace CPP_VERSION {
38 namespace implementation {
39 
40 using ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::implementation::HidlUtils;
41 using ::android::hardware::audio::common::utils::splitString;
42 using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::CoreUtils;
43 namespace util {
44 using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION::implementation::util;
45 }
46 
Stream(bool isInput,audio_stream_t * stream)47 Stream::Stream(bool isInput, audio_stream_t* stream) : mIsInput(isInput), mStream(stream) {
48     (void)mIsInput;  // prevent 'unused field' warnings in pre-V7 versions.
49 }
50 
~Stream()51 Stream::~Stream() {
52     mStream = nullptr;
53 }
54 
55 // static
analyzeStatus(const char * funcName,int status)56 Result Stream::analyzeStatus(const char* funcName, int status) {
57     return util::analyzeStatus("stream", funcName, status);
58 }
59 
60 // static
analyzeStatus(const char * funcName,int status,const std::vector<int> & ignoreErrors)61 Result Stream::analyzeStatus(const char* funcName, int status,
62                              const std::vector<int>& ignoreErrors) {
63     return util::analyzeStatus("stream", funcName, status, ignoreErrors);
64 }
65 
halGetParameters(const char * keys)66 char* Stream::halGetParameters(const char* keys) {
67     return mStream->get_parameters(mStream, keys);
68 }
69 
halSetParameters(const char * keysAndValues)70 int Stream::halSetParameters(const char* keysAndValues) {
71     return mStream->set_parameters(mStream, keysAndValues);
72 }
73 
74 // Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
getFrameSize()75 Return<uint64_t> Stream::getFrameSize() {
76     // Needs to be implemented by interface subclasses. But can't be declared as pure virtual,
77     // since interface subclasses implementation do not inherit from this class.
78     LOG_ALWAYS_FATAL("Stream::getFrameSize is pure abstract");
79     return uint64_t{};
80 }
81 
getFrameCount()82 Return<uint64_t> Stream::getFrameCount() {
83     int halFrameCount;
84     Result retval = getParam(AudioParameter::keyFrameCount, &halFrameCount);
85     return retval == Result::OK ? halFrameCount : 0;
86 }
87 
getBufferSize()88 Return<uint64_t> Stream::getBufferSize() {
89     return mStream->get_buffer_size(mStream);
90 }
91 
92 #if MAJOR_VERSION <= 6
getSampleRate()93 Return<uint32_t> Stream::getSampleRate() {
94     return mStream->get_sample_rate(mStream);
95 }
96 
97 #if MAJOR_VERSION == 2
getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)98 Return<void> Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
99     return getSupportedSampleRates(getFormat(), _hidl_cb);
100 }
getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)101 Return<void> Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
102     return getSupportedChannelMasks(getFormat(), _hidl_cb);
103 }
104 #endif
105 
getSupportedSampleRates(AudioFormat format,getSupportedSampleRates_cb _hidl_cb)106 Return<void> Stream::getSupportedSampleRates(AudioFormat format,
107                                              getSupportedSampleRates_cb _hidl_cb) {
108     AudioParameter context;
109     context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
110     String8 halListValue;
111     Result result =
112         getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue, context);
113     hidl_vec<uint32_t> sampleRates;
114     SampleRateSet halSampleRates;
115     if (result == Result::OK) {
116         halSampleRates =
117             samplingRatesFromString(halListValue.string(), AudioParameter::valueListSeparator);
118         sampleRates = hidl_vec<uint32_t>(halSampleRates.begin(), halSampleRates.end());
119         // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
120         // Note that this method must succeed (non empty list) if the format is supported.
121         if (sampleRates.size() == 0) {
122             result = Result::NOT_SUPPORTED;
123         }
124     }
125 #if MAJOR_VERSION == 2
126     _hidl_cb(sampleRates);
127 #elif MAJOR_VERSION >= 4
128     _hidl_cb(result, sampleRates);
129 #endif
130     return Void();
131 }
132 
getSupportedChannelMasks(AudioFormat format,getSupportedChannelMasks_cb _hidl_cb)133 Return<void> Stream::getSupportedChannelMasks(AudioFormat format,
134                                               getSupportedChannelMasks_cb _hidl_cb) {
135     AudioParameter context;
136     context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
137     String8 halListValue;
138     Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue, context);
139     hidl_vec<AudioChannelBitfield> channelMasks;
140     ChannelMaskSet halChannelMasks;
141     if (result == Result::OK) {
142         halChannelMasks =
143             channelMasksFromString(halListValue.string(), AudioParameter::valueListSeparator);
144         channelMasks.resize(halChannelMasks.size());
145         size_t i = 0;
146         for (auto channelMask : halChannelMasks) {
147             channelMasks[i++] = AudioChannelBitfield(channelMask);
148         }
149         // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
150         // Note that this method must succeed (non empty list) if the format is supported.
151         if (channelMasks.size() == 0) {
152             result = Result::NOT_SUPPORTED;
153         }
154     }
155 #if MAJOR_VERSION == 2
156     _hidl_cb(channelMasks);
157 #elif MAJOR_VERSION >= 4
158     _hidl_cb(result, channelMasks);
159 #endif
160     return Void();
161 }
162 
setSampleRate(uint32_t sampleRateHz)163 Return<Result> Stream::setSampleRate(uint32_t sampleRateHz) {
164     return setParam(AudioParameter::keySamplingRate, static_cast<int>(sampleRateHz));
165 }
166 
getChannelMask()167 Return<AudioChannelBitfield> Stream::getChannelMask() {
168     return AudioChannelBitfield(mStream->get_channels(mStream));
169 }
170 
setChannelMask(AudioChannelBitfield mask)171 Return<Result> Stream::setChannelMask(AudioChannelBitfield mask) {
172     return setParam(AudioParameter::keyChannels, static_cast<int>(mask));
173 }
174 
getFormat()175 Return<AudioFormat> Stream::getFormat() {
176     return AudioFormat(mStream->get_format(mStream));
177 }
178 
getSupportedFormats(getSupportedFormats_cb _hidl_cb)179 Return<void> Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
180     String8 halListValue;
181     Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue);
182     hidl_vec<AudioFormat> formats;
183     FormatVector halFormats;
184     if (result == Result::OK) {
185         halFormats = formatsFromString(halListValue.string(), AudioParameter::valueListSeparator);
186         formats.resize(halFormats.size());
187         for (size_t i = 0; i < halFormats.size(); ++i) {
188             formats[i] = AudioFormat(halFormats[i]);
189         }
190         // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
191         // Note that the method must not return an empty list if this capability is supported.
192         if (formats.size() == 0) {
193             result = Result::NOT_SUPPORTED;
194         }
195     }
196 #if MAJOR_VERSION <= 5
197     _hidl_cb(formats);
198 #elif MAJOR_VERSION >= 6
199     _hidl_cb(result, formats);
200 #endif
201     return Void();
202 }
203 
setFormat(AudioFormat format)204 Return<Result> Stream::setFormat(AudioFormat format) {
205     return setParam(AudioParameter::keyFormat, static_cast<int>(format));
206 }
207 
getAudioProperties(getAudioProperties_cb _hidl_cb)208 Return<void> Stream::getAudioProperties(getAudioProperties_cb _hidl_cb) {
209     uint32_t halSampleRate = mStream->get_sample_rate(mStream);
210     audio_channel_mask_t halMask = mStream->get_channels(mStream);
211     audio_format_t halFormat = mStream->get_format(mStream);
212     _hidl_cb(halSampleRate, AudioChannelBitfield(halMask), AudioFormat(halFormat));
213     return Void();
214 }
215 
216 #else  // MAJOR_VERSION <= 6
217 
getSupportedProfiles(getSupportedProfiles_cb _hidl_cb)218 Return<void> Stream::getSupportedProfiles(getSupportedProfiles_cb _hidl_cb) {
219     String8 halListValue;
220     Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue);
221     hidl_vec<AudioProfile> profiles;
222     if (result != Result::OK) {
223         _hidl_cb(result, profiles);
224         return Void();
225     }
226     // Ensure that the separator is one character, despite that it's defined as a C string.
227     static_assert(sizeof(AUDIO_PARAMETER_VALUE_LIST_SEPARATOR) == 2);
228     std::vector<std::string> halFormats =
229             splitString(halListValue.string(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
230     hidl_vec<AudioFormat> formats;
231     (void)HidlUtils::audioFormatsFromHal(halFormats, &formats);
232     std::vector<AudioProfile> tempProfiles;
233     for (const auto& format : formats) {
234         audio_format_t halFormat;
235         if (status_t status = HidlUtils::audioFormatToHal(format, &halFormat); status != NO_ERROR) {
236             continue;
237         }
238         AudioParameter context;
239         context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(halFormat));
240         // Query supported sample rates for the format.
241         result = getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue, context);
242         if (result != Result::OK) break;
243         std::vector<std::string> halSampleRates =
244                 splitString(halListValue.string(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
245         hidl_vec<uint32_t> sampleRates;
246         sampleRates.resize(halSampleRates.size());
247         for (size_t i = 0; i < sampleRates.size(); ++i) {
248             sampleRates[i] = std::stoi(halSampleRates[i]);
249         }
250         // Query supported channel masks for the format.
251         result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue, context);
252         if (result != Result::OK) break;
253         std::vector<std::string> halChannelMasks =
254                 splitString(halListValue.string(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
255         hidl_vec<AudioChannelMask> channelMasks;
256         (void)HidlUtils::audioChannelMasksFromHal(halChannelMasks, &channelMasks);
257         // Create a profile.
258         if (channelMasks.size() != 0 && sampleRates.size() != 0) {
259             tempProfiles.push_back({.format = format,
260                                     .sampleRates = std::move(sampleRates),
261                                     .channelMasks = std::move(channelMasks)});
262         }
263     }
264     // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
265     // Note that the method must not return an empty list if this capability is supported.
266     if (!tempProfiles.empty()) {
267         profiles = tempProfiles;
268     } else {
269         result = Result::NOT_SUPPORTED;
270     }
271     _hidl_cb(result, profiles);
272     return Void();
273 }
274 
getAudioProperties(getAudioProperties_cb _hidl_cb)275 Return<void> Stream::getAudioProperties(getAudioProperties_cb _hidl_cb) {
276     audio_config_base_t halConfigBase = {mStream->get_sample_rate(mStream),
277                                          mStream->get_channels(mStream),
278                                          mStream->get_format(mStream)};
279     AudioConfigBase configBase = {};
280     status_t status = HidlUtils::audioConfigBaseFromHal(halConfigBase, mIsInput, &configBase);
281     _hidl_cb(Stream::analyzeStatus("get_audio_properties", status), configBase);
282     return Void();
283 }
284 
setAudioProperties(const AudioConfigBaseOptional & config)285 Return<Result> Stream::setAudioProperties(const AudioConfigBaseOptional& config) {
286     audio_config_base_t halConfigBase = AUDIO_CONFIG_BASE_INITIALIZER;
287     bool formatSpecified, sRateSpecified, channelMaskSpecified;
288     status_t status = HidlUtils::audioConfigBaseOptionalToHal(
289             config, &halConfigBase, &formatSpecified, &sRateSpecified, &channelMaskSpecified);
290     if (status != NO_ERROR) {
291         return Stream::analyzeStatus("set_audio_properties", status);
292     }
293     if (sRateSpecified) {
294         if (Result result = setParam(AudioParameter::keySamplingRate,
295                                      static_cast<int>(halConfigBase.sample_rate));
296             result != Result::OK) {
297             return result;
298         }
299     }
300     if (channelMaskSpecified) {
301         if (Result result = setParam(AudioParameter::keyChannels,
302                                      static_cast<int>(halConfigBase.channel_mask));
303             result != Result::OK) {
304             return result;
305         }
306     }
307     if (formatSpecified) {
308         if (Result result =
309                     setParam(AudioParameter::keyFormat, static_cast<int>(halConfigBase.format));
310             result != Result::OK) {
311             return result;
312         }
313     }
314     return Result::OK;
315 }
316 
317 #endif  // MAJOR_VERSION <= 6
318 
addEffect(uint64_t effectId)319 Return<Result> Stream::addEffect(uint64_t effectId) {
320     effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
321     if (halEffect != NULL) {
322         return analyzeStatus("add_audio_effect", mStream->add_audio_effect(mStream, halEffect));
323     } else {
324         ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
325         return Result::INVALID_ARGUMENTS;
326     }
327 }
328 
removeEffect(uint64_t effectId)329 Return<Result> Stream::removeEffect(uint64_t effectId) {
330     effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
331     if (halEffect != NULL) {
332         return analyzeStatus("remove_audio_effect",
333                              mStream->remove_audio_effect(mStream, halEffect));
334     } else {
335         ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
336         return Result::INVALID_ARGUMENTS;
337     }
338 }
339 
standby()340 Return<Result> Stream::standby() {
341     return analyzeStatus("standby", mStream->standby(mStream));
342 }
343 
setHwAvSync(uint32_t hwAvSync)344 Return<Result> Stream::setHwAvSync(uint32_t hwAvSync) {
345     return setParam(AudioParameter::keyStreamHwAvSync, static_cast<int>(hwAvSync));
346 }
347 
348 #if MAJOR_VERSION == 2
getDevice()349 Return<AudioDevice> Stream::getDevice() {
350     int device = 0;
351     Result retval = getParam(AudioParameter::keyRouting, &device);
352     return retval == Result::OK ? static_cast<AudioDevice>(device) : AudioDevice::NONE;
353 }
354 
setDevice(const DeviceAddress & address)355 Return<Result> Stream::setDevice(const DeviceAddress& address) {
356     return setParam(AudioParameter::keyRouting, address);
357 }
358 
getParameters(const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)359 Return<void> Stream::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
360     getParametersImpl({} /* context */, keys, _hidl_cb);
361     return Void();
362 }
363 
setParameters(const hidl_vec<ParameterValue> & parameters)364 Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& parameters) {
365     return setParametersImpl({} /* context */, parameters);
366 }
367 
setConnectedState(const DeviceAddress & address,bool connected)368 Return<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected) {
369     return setParam(
370             connected ? AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect,
371             address);
372 }
373 #elif MAJOR_VERSION >= 4
getDevices(getDevices_cb _hidl_cb)374 Return<void> Stream::getDevices(getDevices_cb _hidl_cb) {
375     int halDevice = 0;
376     Result retval = getParam(AudioParameter::keyRouting, &halDevice);
377     hidl_vec<DeviceAddress> devices;
378     if (retval == Result::OK) {
379         devices.resize(1);
380         retval = Stream::analyzeStatus(
381                 "get_devices",
382                 CoreUtils::deviceAddressFromHal(static_cast<audio_devices_t>(halDevice), nullptr,
383                                                 &devices[0]));
384     }
385     _hidl_cb(retval, devices);
386     return Void();
387 }
388 
setDevices(const hidl_vec<DeviceAddress> & devices)389 Return<Result> Stream::setDevices(const hidl_vec<DeviceAddress>& devices) {
390     // FIXME: can the legacy API set multiple device with address ?
391     if (devices.size() > 1) {
392         return Result::NOT_SUPPORTED;
393     }
394     DeviceAddress address{};
395     if (devices.size() == 1) {
396         address = devices[0];
397     }
398     return setParam(AudioParameter::keyRouting, address);
399 }
400 
getParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)401 Return<void> Stream::getParameters(const hidl_vec<ParameterValue>& context,
402                                    const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
403     getParametersImpl(context, keys, _hidl_cb);
404     return Void();
405 }
406 
setParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<ParameterValue> & parameters)407 Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& context,
408                                      const hidl_vec<ParameterValue>& parameters) {
409     return setParametersImpl(context, parameters);
410 }
411 #endif
412 
start()413 Return<Result> Stream::start() {
414     return Result::NOT_SUPPORTED;
415 }
416 
stop()417 Return<Result> Stream::stop() {
418     return Result::NOT_SUPPORTED;
419 }
420 
createMmapBuffer(int32_t minSizeFrames __unused,createMmapBuffer_cb _hidl_cb)421 Return<void> Stream::createMmapBuffer(int32_t minSizeFrames __unused,
422                                       createMmapBuffer_cb _hidl_cb) {
423     Result retval(Result::NOT_SUPPORTED);
424     MmapBufferInfo info;
425     _hidl_cb(retval, info);
426     return Void();
427 }
428 
getMmapPosition(getMmapPosition_cb _hidl_cb)429 Return<void> Stream::getMmapPosition(getMmapPosition_cb _hidl_cb) {
430     Result retval(Result::NOT_SUPPORTED);
431     MmapPosition position;
432     _hidl_cb(retval, position);
433     return Void();
434 }
435 
close()436 Return<Result> Stream::close() {
437     return Result::NOT_SUPPORTED;
438 }
439 
debug(const hidl_handle & fd,const hidl_vec<hidl_string> &)440 Return<void> Stream::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
441     if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
442         analyzeStatus("dump", mStream->dump(mStream, fd->data[0]));
443     }
444     return Void();
445 }
446 
447 #if MAJOR_VERSION == 2
debugDump(const hidl_handle & fd)448 Return<void> Stream::debugDump(const hidl_handle& fd) {
449     return debug(fd, {} /* options */);
450 }
451 #endif
452 
453 }  // namespace implementation
454 }  // namespace CPP_VERSION
455 }  // namespace audio
456 }  // namespace hardware
457 }  // namespace android
458