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/default/EffectMap.h"
21 #include "core/default/Conversions.h"
22 #include "core/default/Util.h"
23
24 #include <inttypes.h>
25
26 #include <android/log.h>
27 #include <hardware/audio.h>
28 #include <hardware/audio_effect.h>
29 #include <media/TypeConverter.h>
30 #include <utils/SortedVector.h>
31 #include <utils/Vector.h>
32
33 namespace android {
34 namespace hardware {
35 namespace audio {
36 namespace CPP_VERSION {
37 namespace implementation {
38
Stream(audio_stream_t * stream)39 Stream::Stream(audio_stream_t* stream) : mStream(stream) {}
40
~Stream()41 Stream::~Stream() {
42 mStream = nullptr;
43 }
44
45 // static
analyzeStatus(const char * funcName,int status)46 Result Stream::analyzeStatus(const char* funcName, int status) {
47 return util::analyzeStatus("stream", funcName, status);
48 }
49
50 // static
analyzeStatus(const char * funcName,int status,const std::vector<int> & ignoreErrors)51 Result Stream::analyzeStatus(const char* funcName, int status,
52 const std::vector<int>& ignoreErrors) {
53 return util::analyzeStatus("stream", funcName, status, ignoreErrors);
54 }
55
halGetParameters(const char * keys)56 char* Stream::halGetParameters(const char* keys) {
57 return mStream->get_parameters(mStream, keys);
58 }
59
halSetParameters(const char * keysAndValues)60 int Stream::halSetParameters(const char* keysAndValues) {
61 return mStream->set_parameters(mStream, keysAndValues);
62 }
63
64 // Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
getFrameSize()65 Return<uint64_t> Stream::getFrameSize() {
66 // Needs to be implemented by interface subclasses. But can't be declared as pure virtual,
67 // since interface subclasses implementation do not inherit from this class.
68 LOG_ALWAYS_FATAL("Stream::getFrameSize is pure abstract");
69 return uint64_t{};
70 }
71
getFrameCount()72 Return<uint64_t> Stream::getFrameCount() {
73 int halFrameCount;
74 Result retval = getParam(AudioParameter::keyFrameCount, &halFrameCount);
75 return retval == Result::OK ? halFrameCount : 0;
76 }
77
getBufferSize()78 Return<uint64_t> Stream::getBufferSize() {
79 return mStream->get_buffer_size(mStream);
80 }
81
getSampleRate()82 Return<uint32_t> Stream::getSampleRate() {
83 return mStream->get_sample_rate(mStream);
84 }
85
86 #if MAJOR_VERSION == 2
getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)87 Return<void> Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
88 return getSupportedSampleRates(getFormat(), _hidl_cb);
89 }
getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)90 Return<void> Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
91 return getSupportedChannelMasks(getFormat(), _hidl_cb);
92 }
93 #endif
94
getSupportedSampleRates(AudioFormat format,getSupportedSampleRates_cb _hidl_cb)95 Return<void> Stream::getSupportedSampleRates(AudioFormat format,
96 getSupportedSampleRates_cb _hidl_cb) {
97 AudioParameter context;
98 context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
99 String8 halListValue;
100 Result result =
101 getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue, context);
102 hidl_vec<uint32_t> sampleRates;
103 SortedVector<uint32_t> halSampleRates;
104 if (result == Result::OK) {
105 halSampleRates =
106 samplingRatesFromString(halListValue.string(), AudioParameter::valueListSeparator);
107 sampleRates.setToExternal(halSampleRates.editArray(), halSampleRates.size());
108 // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
109 // Note that this method must succeed (non empty list) if the format is supported.
110 if (sampleRates.size() == 0) {
111 result = Result::NOT_SUPPORTED;
112 }
113 }
114 #if MAJOR_VERSION == 2
115 _hidl_cb(sampleRates);
116 #elif MAJOR_VERSION >= 4
117 _hidl_cb(result, sampleRates);
118 #endif
119 return Void();
120 }
121
getSupportedChannelMasks(AudioFormat format,getSupportedChannelMasks_cb _hidl_cb)122 Return<void> Stream::getSupportedChannelMasks(AudioFormat format,
123 getSupportedChannelMasks_cb _hidl_cb) {
124 AudioParameter context;
125 context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
126 String8 halListValue;
127 Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue, context);
128 hidl_vec<AudioChannelBitfield> channelMasks;
129 SortedVector<audio_channel_mask_t> halChannelMasks;
130 if (result == Result::OK) {
131 halChannelMasks =
132 channelMasksFromString(halListValue.string(), AudioParameter::valueListSeparator);
133 channelMasks.resize(halChannelMasks.size());
134 for (size_t i = 0; i < halChannelMasks.size(); ++i) {
135 channelMasks[i] = AudioChannelBitfield(halChannelMasks[i]);
136 }
137 // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
138 // Note that this method must succeed (non empty list) if the format is supported.
139 if (channelMasks.size() == 0) {
140 result = Result::NOT_SUPPORTED;
141 }
142 }
143 #if MAJOR_VERSION == 2
144 _hidl_cb(channelMasks);
145 #elif MAJOR_VERSION >= 4
146 _hidl_cb(result, channelMasks);
147 #endif
148 return Void();
149 }
150
setSampleRate(uint32_t sampleRateHz)151 Return<Result> Stream::setSampleRate(uint32_t sampleRateHz) {
152 return setParam(AudioParameter::keySamplingRate, static_cast<int>(sampleRateHz));
153 }
154
getChannelMask()155 Return<AudioChannelBitfield> Stream::getChannelMask() {
156 return AudioChannelBitfield(mStream->get_channels(mStream));
157 }
158
setChannelMask(AudioChannelBitfield mask)159 Return<Result> Stream::setChannelMask(AudioChannelBitfield mask) {
160 return setParam(AudioParameter::keyChannels, static_cast<int>(mask));
161 }
162
getFormat()163 Return<AudioFormat> Stream::getFormat() {
164 return AudioFormat(mStream->get_format(mStream));
165 }
166
getSupportedFormats(getSupportedFormats_cb _hidl_cb)167 Return<void> Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
168 String8 halListValue;
169 Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue);
170 hidl_vec<AudioFormat> formats;
171 Vector<audio_format_t> halFormats;
172 if (result == Result::OK) {
173 halFormats = formatsFromString(halListValue.string(), AudioParameter::valueListSeparator);
174 formats.resize(halFormats.size());
175 for (size_t i = 0; i < halFormats.size(); ++i) {
176 formats[i] = AudioFormat(halFormats[i]);
177 }
178 }
179 _hidl_cb(formats);
180 return Void();
181 }
182
setFormat(AudioFormat format)183 Return<Result> Stream::setFormat(AudioFormat format) {
184 return setParam(AudioParameter::keyFormat, static_cast<int>(format));
185 }
186
getAudioProperties(getAudioProperties_cb _hidl_cb)187 Return<void> Stream::getAudioProperties(getAudioProperties_cb _hidl_cb) {
188 uint32_t halSampleRate = mStream->get_sample_rate(mStream);
189 audio_channel_mask_t halMask = mStream->get_channels(mStream);
190 audio_format_t halFormat = mStream->get_format(mStream);
191 _hidl_cb(halSampleRate, AudioChannelBitfield(halMask), AudioFormat(halFormat));
192 return Void();
193 }
194
addEffect(uint64_t effectId)195 Return<Result> Stream::addEffect(uint64_t effectId) {
196 effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
197 if (halEffect != NULL) {
198 return analyzeStatus("add_audio_effect", mStream->add_audio_effect(mStream, halEffect));
199 } else {
200 ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
201 return Result::INVALID_ARGUMENTS;
202 }
203 }
204
removeEffect(uint64_t effectId)205 Return<Result> Stream::removeEffect(uint64_t effectId) {
206 effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
207 if (halEffect != NULL) {
208 return analyzeStatus("remove_audio_effect",
209 mStream->remove_audio_effect(mStream, halEffect));
210 } else {
211 ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
212 return Result::INVALID_ARGUMENTS;
213 }
214 }
215
standby()216 Return<Result> Stream::standby() {
217 return analyzeStatus("standby", mStream->standby(mStream));
218 }
219
setHwAvSync(uint32_t hwAvSync)220 Return<Result> Stream::setHwAvSync(uint32_t hwAvSync) {
221 return setParam(AudioParameter::keyStreamHwAvSync, static_cast<int>(hwAvSync));
222 }
223
224 #if MAJOR_VERSION == 2
getDevice()225 Return<AudioDevice> Stream::getDevice() {
226 int device = 0;
227 Result retval = getParam(AudioParameter::keyRouting, &device);
228 return retval == Result::OK ? static_cast<AudioDevice>(device) : AudioDevice::NONE;
229 }
230
setDevice(const DeviceAddress & address)231 Return<Result> Stream::setDevice(const DeviceAddress& address) {
232 return setParam(AudioParameter::keyRouting, address);
233 }
234
getParameters(const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)235 Return<void> Stream::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
236 getParametersImpl({} /* context */, keys, _hidl_cb);
237 return Void();
238 }
239
setParameters(const hidl_vec<ParameterValue> & parameters)240 Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& parameters) {
241 return setParametersImpl({} /* context */, parameters);
242 }
243
setConnectedState(const DeviceAddress & address,bool connected)244 Return<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected) {
245 return setParam(
246 connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect,
247 address);
248 }
249 #elif MAJOR_VERSION >= 4
getDevices(getDevices_cb _hidl_cb)250 Return<void> Stream::getDevices(getDevices_cb _hidl_cb) {
251 int device = 0;
252 Result retval = getParam(AudioParameter::keyRouting, &device);
253 hidl_vec<DeviceAddress> devices;
254 if (retval == Result::OK) {
255 devices.resize(1);
256 devices[0].device = static_cast<AudioDevice>(device);
257 }
258 _hidl_cb(retval, devices);
259 return Void();
260 }
261
setDevices(const hidl_vec<DeviceAddress> & devices)262 Return<Result> Stream::setDevices(const hidl_vec<DeviceAddress>& devices) {
263 // FIXME: can the legacy API set multiple device with address ?
264 if (devices.size() > 1) {
265 return Result::NOT_SUPPORTED;
266 }
267 DeviceAddress address;
268 if (devices.size() == 1) {
269 address = devices[0];
270 } else {
271 address.device = AudioDevice::NONE;
272 }
273 return setParam(AudioParameter::keyRouting, address);
274 }
getParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)275 Return<void> Stream::getParameters(const hidl_vec<ParameterValue>& context,
276 const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
277 getParametersImpl(context, keys, _hidl_cb);
278 return Void();
279 }
280
setParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<ParameterValue> & parameters)281 Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& context,
282 const hidl_vec<ParameterValue>& parameters) {
283 return setParametersImpl(context, parameters);
284 }
285 #endif
286
start()287 Return<Result> Stream::start() {
288 return Result::NOT_SUPPORTED;
289 }
290
stop()291 Return<Result> Stream::stop() {
292 return Result::NOT_SUPPORTED;
293 }
294
createMmapBuffer(int32_t minSizeFrames __unused,createMmapBuffer_cb _hidl_cb)295 Return<void> Stream::createMmapBuffer(int32_t minSizeFrames __unused,
296 createMmapBuffer_cb _hidl_cb) {
297 Result retval(Result::NOT_SUPPORTED);
298 MmapBufferInfo info;
299 _hidl_cb(retval, info);
300 return Void();
301 }
302
getMmapPosition(getMmapPosition_cb _hidl_cb)303 Return<void> Stream::getMmapPosition(getMmapPosition_cb _hidl_cb) {
304 Result retval(Result::NOT_SUPPORTED);
305 MmapPosition position;
306 _hidl_cb(retval, position);
307 return Void();
308 }
309
close()310 Return<Result> Stream::close() {
311 return Result::NOT_SUPPORTED;
312 }
313
debug(const hidl_handle & fd,const hidl_vec<hidl_string> &)314 Return<void> Stream::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
315 if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
316 analyzeStatus("dump", mStream->dump(mStream, fd->data[0]));
317 }
318 return Void();
319 }
320
321 #if MAJOR_VERSION == 2
debugDump(const hidl_handle & fd)322 Return<void> Stream::debugDump(const hidl_handle& fd) {
323 return debug(fd, {} /* options */);
324 }
325 #endif
326
327 } // namespace implementation
328 } // namespace CPP_VERSION
329 } // namespace audio
330 } // namespace hardware
331 } // namespace android
332