1 /*
2 * Copyright (C) 2016 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 #include <inttypes.h>
18
19 #define LOG_TAG "StreamHAL"
20
21 #include <hardware/audio.h>
22 #include <hardware/audio_effect.h>
23 #include <media/TypeConverter.h>
24 #include <android/log.h>
25 #include <utils/SortedVector.h>
26 #include <utils/Vector.h>
27
28 #include "Conversions.h"
29 #include "EffectMap.h"
30 #include "Stream.h"
31
32 namespace android {
33 namespace hardware {
34 namespace audio {
35 namespace V2_0 {
36 namespace implementation {
37
Stream(audio_stream_t * stream)38 Stream::Stream(audio_stream_t* stream)
39 : mStream(stream) {
40 }
41
~Stream()42 Stream::~Stream() {
43 mStream = nullptr;
44 }
45
46 // static
analyzeStatus(const char * funcName,int status)47 Result Stream::analyzeStatus(const char* funcName, int status) {
48 static const std::vector<int> empty;
49 return analyzeStatus(funcName, status, empty);
50 }
51
52 template <typename T>
element_in(T e,const std::vector<T> & v)53 inline bool element_in(T e, const std::vector<T>& v) {
54 return std::find(v.begin(), v.end(), e) != v.end();
55 }
56
57 // static
analyzeStatus(const char * funcName,int status,const std::vector<int> & ignoreErrors)58 Result Stream::analyzeStatus(const char* funcName, int status,
59 const std::vector<int>& ignoreErrors) {
60 if (status != 0 && (ignoreErrors.empty() || !element_in(-status, ignoreErrors))) {
61 ALOGW("Error from HAL stream in function %s: %s", funcName, strerror(-status));
62 }
63 switch (status) {
64 case 0: return Result::OK;
65 case -EINVAL: return Result::INVALID_ARGUMENTS;
66 case -ENODATA: return Result::INVALID_STATE;
67 case -ENODEV: return Result::NOT_INITIALIZED;
68 case -ENOSYS: return Result::NOT_SUPPORTED;
69 default: return Result::INVALID_STATE;
70 }
71 }
72
halGetParameters(const char * keys)73 char* Stream::halGetParameters(const char* keys) {
74 return mStream->get_parameters(mStream, keys);
75 }
76
halSetParameters(const char * keysAndValues)77 int Stream::halSetParameters(const char* keysAndValues) {
78 return mStream->set_parameters(mStream, keysAndValues);
79 }
80
81 // Methods from ::android::hardware::audio::V2_0::IStream follow.
getFrameSize()82 Return<uint64_t> Stream::getFrameSize() {
83 // Needs to be implemented by interface subclasses. But can't be declared as pure virtual,
84 // since interface subclasses implementation do not inherit from this class.
85 LOG_ALWAYS_FATAL("Stream::getFrameSize is pure abstract");
86 return uint64_t {};
87 }
88
getFrameCount()89 Return<uint64_t> Stream::getFrameCount() {
90 int halFrameCount;
91 Result retval = getParam(AudioParameter::keyFrameCount, &halFrameCount);
92 return retval == Result::OK ? halFrameCount : 0;
93 }
94
getBufferSize()95 Return<uint64_t> Stream::getBufferSize() {
96 return mStream->get_buffer_size(mStream);
97 }
98
getSampleRate()99 Return<uint32_t> Stream::getSampleRate() {
100 return mStream->get_sample_rate(mStream);
101 }
102
getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)103 Return<void> Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
104 String8 halListValue;
105 Result result = getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue);
106 hidl_vec<uint32_t> sampleRates;
107 SortedVector<uint32_t> halSampleRates;
108 if (result == Result::OK) {
109 halSampleRates = samplingRatesFromString(
110 halListValue.string(), AudioParameter::valueListSeparator);
111 sampleRates.setToExternal(halSampleRates.editArray(), halSampleRates.size());
112 }
113 _hidl_cb(sampleRates);
114 return Void();
115 }
116
setSampleRate(uint32_t sampleRateHz)117 Return<Result> Stream::setSampleRate(uint32_t sampleRateHz) {
118 return setParam(AudioParameter::keySamplingRate, static_cast<int>(sampleRateHz));
119 }
120
getChannelMask()121 Return<AudioChannelMask> Stream::getChannelMask() {
122 return AudioChannelMask(mStream->get_channels(mStream));
123 }
124
getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)125 Return<void> Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
126 String8 halListValue;
127 Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue);
128 hidl_vec<AudioChannelMask> channelMasks;
129 SortedVector<audio_channel_mask_t> halChannelMasks;
130 if (result == Result::OK) {
131 halChannelMasks = channelMasksFromString(
132 halListValue.string(), AudioParameter::valueListSeparator);
133 channelMasks.resize(halChannelMasks.size());
134 for (size_t i = 0; i < halChannelMasks.size(); ++i) {
135 channelMasks[i] = AudioChannelMask(halChannelMasks[i]);
136 }
137 }
138 _hidl_cb(channelMasks);
139 return Void();
140 }
141
setChannelMask(AudioChannelMask mask)142 Return<Result> Stream::setChannelMask(AudioChannelMask mask) {
143 return setParam(AudioParameter::keyChannels, static_cast<int>(mask));
144 }
145
getFormat()146 Return<AudioFormat> Stream::getFormat() {
147 return AudioFormat(mStream->get_format(mStream));
148 }
149
getSupportedFormats(getSupportedFormats_cb _hidl_cb)150 Return<void> Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
151 String8 halListValue;
152 Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue);
153 hidl_vec<AudioFormat> formats;
154 Vector<audio_format_t> halFormats;
155 if (result == Result::OK) {
156 halFormats = formatsFromString(halListValue.string(), AudioParameter::valueListSeparator);
157 formats.resize(halFormats.size());
158 for (size_t i = 0; i < halFormats.size(); ++i) {
159 formats[i] = AudioFormat(halFormats[i]);
160 }
161 }
162 _hidl_cb(formats);
163 return Void();
164 }
165
setFormat(AudioFormat format)166 Return<Result> Stream::setFormat(AudioFormat format) {
167 return setParam(AudioParameter::keyFormat, static_cast<int>(format));
168 }
169
getAudioProperties(getAudioProperties_cb _hidl_cb)170 Return<void> Stream::getAudioProperties(getAudioProperties_cb _hidl_cb) {
171 uint32_t halSampleRate = mStream->get_sample_rate(mStream);
172 audio_channel_mask_t halMask = mStream->get_channels(mStream);
173 audio_format_t halFormat = mStream->get_format(mStream);
174 _hidl_cb(halSampleRate, AudioChannelMask(halMask), AudioFormat(halFormat));
175 return Void();
176 }
177
addEffect(uint64_t effectId)178 Return<Result> Stream::addEffect(uint64_t effectId) {
179 effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
180 if (halEffect != NULL) {
181 return analyzeStatus("add_audio_effect", mStream->add_audio_effect(mStream, halEffect));
182 } else {
183 ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
184 return Result::INVALID_ARGUMENTS;
185 }
186 }
187
removeEffect(uint64_t effectId)188 Return<Result> Stream::removeEffect(uint64_t effectId) {
189 effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
190 if (halEffect != NULL) {
191 return analyzeStatus(
192 "remove_audio_effect", mStream->remove_audio_effect(mStream, halEffect));
193 } else {
194 ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
195 return Result::INVALID_ARGUMENTS;
196 }
197 }
198
standby()199 Return<Result> Stream::standby() {
200 return analyzeStatus("standby", mStream->standby(mStream));
201 }
202
getDevice()203 Return<AudioDevice> Stream::getDevice() {
204 int device;
205 Result retval = getParam(AudioParameter::keyRouting, &device);
206 return retval == Result::OK ? static_cast<AudioDevice>(device) : AudioDevice::NONE;
207 }
208
setDevice(const DeviceAddress & address)209 Return<Result> Stream::setDevice(const DeviceAddress& address) {
210 char* halDeviceAddress =
211 audio_device_address_to_parameter(
212 static_cast<audio_devices_t>(address.device),
213 deviceAddressToHal(address).c_str());
214 AudioParameter params((String8(halDeviceAddress)));
215 free(halDeviceAddress);
216 params.addInt(
217 String8(AudioParameter::keyRouting), static_cast<audio_devices_t>(address.device));
218 return setParams(params);
219 }
220
setConnectedState(const DeviceAddress & address,bool connected)221 Return<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected) {
222 return setParam(
223 connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect,
224 deviceAddressToHal(address).c_str());
225 }
226
setHwAvSync(uint32_t hwAvSync)227 Return<Result> Stream::setHwAvSync(uint32_t hwAvSync) {
228 return setParam(AudioParameter::keyStreamHwAvSync, static_cast<int>(hwAvSync));
229 }
230
getParameters(const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)231 Return<void> Stream::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
232 getParametersImpl(keys, _hidl_cb);
233 return Void();
234 }
235
setParameters(const hidl_vec<ParameterValue> & parameters)236 Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& parameters) {
237 return setParametersImpl(parameters);
238 }
239
debugDump(const hidl_handle & fd)240 Return<void> Stream::debugDump(const hidl_handle& fd) {
241 if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
242 analyzeStatus("dump", mStream->dump(mStream, fd->data[0]));
243 }
244 return Void();
245 }
246
start()247 Return<Result> Stream::start() {
248 return Result::NOT_SUPPORTED;
249 }
250
stop()251 Return<Result> Stream::stop() {
252 return Result::NOT_SUPPORTED;
253 }
254
createMmapBuffer(int32_t minSizeFrames __unused,createMmapBuffer_cb _hidl_cb)255 Return<void> Stream::createMmapBuffer(int32_t minSizeFrames __unused,
256 createMmapBuffer_cb _hidl_cb) {
257 Result retval(Result::NOT_SUPPORTED);
258 MmapBufferInfo info;
259 _hidl_cb(retval, info);
260 return Void();
261 }
262
getMmapPosition(getMmapPosition_cb _hidl_cb)263 Return<void> Stream::getMmapPosition(getMmapPosition_cb _hidl_cb) {
264 Result retval(Result::NOT_SUPPORTED);
265 MmapPosition position;
266 _hidl_cb(retval, position);
267 return Void();
268 }
269
close()270 Return<Result> Stream::close() {
271 return Result::NOT_SUPPORTED;
272 }
273
274 } // namespace implementation
275 } // namespace V2_0
276 } // namespace audio
277 } // namespace hardware
278 } // namespace android
279