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