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 <common/all-versions/IncludeGuard.h>
18
19 //#define LOG_NDEBUG 0
20 #define ATRACE_TAG ATRACE_TAG_AUDIO
21
22 #include <android/log.h>
23 #include <hardware/audio.h>
24 #include <utils/Trace.h>
25 #include <memory>
26
27 using ::android::hardware::audio::AUDIO_HAL_VERSION::MessageQueueFlagBits;
28 #include "Conversions.h"
29
30 namespace android {
31 namespace hardware {
32 namespace audio {
33 namespace AUDIO_HAL_VERSION {
34 namespace implementation {
35
36 using ::android::hardware::audio::common::AUDIO_HAL_VERSION::ThreadInfo;
37
38 namespace {
39
40 class ReadThread : public Thread {
41 public:
42 // ReadThread's lifespan never exceeds StreamIn's lifespan.
ReadThread(std::atomic<bool> * stop,audio_stream_in_t * stream,StreamIn::CommandMQ * commandMQ,StreamIn::DataMQ * dataMQ,StreamIn::StatusMQ * statusMQ,EventFlag * efGroup)43 ReadThread(std::atomic<bool>* stop, audio_stream_in_t* stream, StreamIn::CommandMQ* commandMQ,
44 StreamIn::DataMQ* dataMQ, StreamIn::StatusMQ* statusMQ, EventFlag* efGroup)
45 : Thread(false /*canCallJava*/),
46 mStop(stop),
47 mStream(stream),
48 mCommandMQ(commandMQ),
49 mDataMQ(dataMQ),
50 mStatusMQ(statusMQ),
51 mEfGroup(efGroup),
52 mBuffer(nullptr) {}
init()53 bool init() {
54 mBuffer.reset(new (std::nothrow) uint8_t[mDataMQ->getQuantumCount()]);
55 return mBuffer != nullptr;
56 }
~ReadThread()57 virtual ~ReadThread() {}
58
59 private:
60 std::atomic<bool>* mStop;
61 audio_stream_in_t* mStream;
62 StreamIn::CommandMQ* mCommandMQ;
63 StreamIn::DataMQ* mDataMQ;
64 StreamIn::StatusMQ* mStatusMQ;
65 EventFlag* mEfGroup;
66 std::unique_ptr<uint8_t[]> mBuffer;
67 IStreamIn::ReadParameters mParameters;
68 IStreamIn::ReadStatus mStatus;
69
70 bool threadLoop() override;
71
72 void doGetCapturePosition();
73 void doRead();
74 };
75
doRead()76 void ReadThread::doRead() {
77 size_t availableToWrite = mDataMQ->availableToWrite();
78 size_t requestedToRead = mParameters.params.read;
79 if (requestedToRead > availableToWrite) {
80 ALOGW(
81 "truncating read data from %d to %d due to insufficient data queue "
82 "space",
83 (int32_t)requestedToRead, (int32_t)availableToWrite);
84 requestedToRead = availableToWrite;
85 }
86 ssize_t readResult = mStream->read(mStream, &mBuffer[0], requestedToRead);
87 mStatus.retval = Result::OK;
88 if (readResult >= 0) {
89 mStatus.reply.read = readResult;
90 if (!mDataMQ->write(&mBuffer[0], readResult)) {
91 ALOGW("data message queue write failed");
92 }
93 } else {
94 mStatus.retval = Stream::analyzeStatus("read", readResult);
95 }
96 }
97
doGetCapturePosition()98 void ReadThread::doGetCapturePosition() {
99 mStatus.retval = StreamIn::getCapturePositionImpl(
100 mStream, &mStatus.reply.capturePosition.frames, &mStatus.reply.capturePosition.time);
101 }
102
threadLoop()103 bool ReadThread::threadLoop() {
104 // This implementation doesn't return control back to the Thread until it
105 // decides to stop,
106 // as the Thread uses mutexes, and this can lead to priority inversion.
107 while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
108 uint32_t efState = 0;
109 mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
110 if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) {
111 continue; // Nothing to do.
112 }
113 if (!mCommandMQ->read(&mParameters)) {
114 continue; // Nothing to do.
115 }
116 mStatus.replyTo = mParameters.command;
117 switch (mParameters.command) {
118 case IStreamIn::ReadCommand::READ:
119 doRead();
120 break;
121 case IStreamIn::ReadCommand::GET_CAPTURE_POSITION:
122 doGetCapturePosition();
123 break;
124 default:
125 ALOGE("Unknown read thread command code %d", mParameters.command);
126 mStatus.retval = Result::NOT_SUPPORTED;
127 break;
128 }
129 if (!mStatusMQ->write(&mStatus)) {
130 ALOGW("status message queue write failed");
131 }
132 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
133 }
134
135 return false;
136 }
137
138 } // namespace
139
StreamIn(const sp<Device> & device,audio_stream_in_t * stream)140 StreamIn::StreamIn(const sp<Device>& device, audio_stream_in_t* stream)
141 : mIsClosed(false),
142 mDevice(device),
143 mStream(stream),
144 mStreamCommon(new Stream(&stream->common)),
145 mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)),
146 mEfGroup(nullptr),
147 mStopReadThread(false) {}
148
~StreamIn()149 StreamIn::~StreamIn() {
150 ATRACE_CALL();
151 close();
152 if (mReadThread.get()) {
153 ATRACE_NAME("mReadThread->join");
154 status_t status = mReadThread->join();
155 ALOGE_IF(status, "read thread exit error: %s", strerror(-status));
156 }
157 if (mEfGroup) {
158 status_t status = EventFlag::deleteEventFlag(&mEfGroup);
159 ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status));
160 }
161 mDevice->closeInputStream(mStream);
162 mStream = nullptr;
163 }
164
165 // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStream follow.
getFrameSize()166 Return<uint64_t> StreamIn::getFrameSize() {
167 return audio_stream_in_frame_size(mStream);
168 }
169
getFrameCount()170 Return<uint64_t> StreamIn::getFrameCount() {
171 return mStreamCommon->getFrameCount();
172 }
173
getBufferSize()174 Return<uint64_t> StreamIn::getBufferSize() {
175 return mStreamCommon->getBufferSize();
176 }
177
getSampleRate()178 Return<uint32_t> StreamIn::getSampleRate() {
179 return mStreamCommon->getSampleRate();
180 }
181
182 #ifdef AUDIO_HAL_VERSION_2_0
getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)183 Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
184 return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
185 }
getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)186 Return<void> StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
187 return mStreamCommon->getSupportedSampleRates(_hidl_cb);
188 }
189 #endif
190
getSupportedChannelMasks(AudioFormat format,getSupportedChannelMasks_cb _hidl_cb)191 Return<void> StreamIn::getSupportedChannelMasks(AudioFormat format,
192 getSupportedChannelMasks_cb _hidl_cb) {
193 return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb);
194 }
getSupportedSampleRates(AudioFormat format,getSupportedSampleRates_cb _hidl_cb)195 Return<void> StreamIn::getSupportedSampleRates(AudioFormat format,
196 getSupportedSampleRates_cb _hidl_cb) {
197 return mStreamCommon->getSupportedSampleRates(format, _hidl_cb);
198 }
199
setSampleRate(uint32_t sampleRateHz)200 Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz) {
201 return mStreamCommon->setSampleRate(sampleRateHz);
202 }
203
getChannelMask()204 Return<AudioChannelBitfield> StreamIn::getChannelMask() {
205 return mStreamCommon->getChannelMask();
206 }
207
setChannelMask(AudioChannelBitfield mask)208 Return<Result> StreamIn::setChannelMask(AudioChannelBitfield mask) {
209 return mStreamCommon->setChannelMask(mask);
210 }
211
getFormat()212 Return<AudioFormat> StreamIn::getFormat() {
213 return mStreamCommon->getFormat();
214 }
215
getSupportedFormats(getSupportedFormats_cb _hidl_cb)216 Return<void> StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
217 return mStreamCommon->getSupportedFormats(_hidl_cb);
218 }
219
setFormat(AudioFormat format)220 Return<Result> StreamIn::setFormat(AudioFormat format) {
221 return mStreamCommon->setFormat(format);
222 }
223
getAudioProperties(getAudioProperties_cb _hidl_cb)224 Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb) {
225 return mStreamCommon->getAudioProperties(_hidl_cb);
226 }
227
addEffect(uint64_t effectId)228 Return<Result> StreamIn::addEffect(uint64_t effectId) {
229 return mStreamCommon->addEffect(effectId);
230 }
231
removeEffect(uint64_t effectId)232 Return<Result> StreamIn::removeEffect(uint64_t effectId) {
233 return mStreamCommon->removeEffect(effectId);
234 }
235
standby()236 Return<Result> StreamIn::standby() {
237 return mStreamCommon->standby();
238 }
239
setHwAvSync(uint32_t hwAvSync)240 Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) {
241 return mStreamCommon->setHwAvSync(hwAvSync);
242 }
243
244 #ifdef AUDIO_HAL_VERSION_2_0
setConnectedState(const DeviceAddress & address,bool connected)245 Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected) {
246 return mStreamCommon->setConnectedState(address, connected);
247 }
248
getDevice()249 Return<AudioDevice> StreamIn::getDevice() {
250 return mStreamCommon->getDevice();
251 }
252
setDevice(const DeviceAddress & address)253 Return<Result> StreamIn::setDevice(const DeviceAddress& address) {
254 return mStreamCommon->setDevice(address);
255 }
256
getParameters(const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)257 Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
258 return mStreamCommon->getParameters(keys, _hidl_cb);
259 }
260
setParameters(const hidl_vec<ParameterValue> & parameters)261 Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& parameters) {
262 return mStreamCommon->setParameters(parameters);
263 }
264
debugDump(const hidl_handle & fd)265 Return<void> StreamIn::debugDump(const hidl_handle& fd) {
266 return mStreamCommon->debugDump(fd);
267 }
268 #elif defined(AUDIO_HAL_VERSION_4_0)
getDevices(getDevices_cb _hidl_cb)269 Return<void> StreamIn::getDevices(getDevices_cb _hidl_cb) {
270 return mStreamCommon->getDevices(_hidl_cb);
271 }
272
setDevices(const hidl_vec<DeviceAddress> & devices)273 Return<Result> StreamIn::setDevices(const hidl_vec<DeviceAddress>& devices) {
274 return mStreamCommon->setDevices(devices);
275 }
getParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)276 Return<void> StreamIn::getParameters(const hidl_vec<ParameterValue>& context,
277 const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
278 return mStreamCommon->getParameters(context, keys, _hidl_cb);
279 }
280
setParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<ParameterValue> & parameters)281 Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& context,
282 const hidl_vec<ParameterValue>& parameters) {
283 return mStreamCommon->setParameters(context, parameters);
284 }
285 #endif
286
start()287 Return<Result> StreamIn::start() {
288 return mStreamMmap->start();
289 }
290
stop()291 Return<Result> StreamIn::stop() {
292 return mStreamMmap->stop();
293 }
294
createMmapBuffer(int32_t minSizeFrames,createMmapBuffer_cb _hidl_cb)295 Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
296 return mStreamMmap->createMmapBuffer(minSizeFrames, audio_stream_in_frame_size(mStream),
297 _hidl_cb);
298 }
299
getMmapPosition(getMmapPosition_cb _hidl_cb)300 Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) {
301 return mStreamMmap->getMmapPosition(_hidl_cb);
302 }
303
close()304 Return<Result> StreamIn::close() {
305 if (mIsClosed) return Result::INVALID_STATE;
306 mIsClosed = true;
307 if (mReadThread.get()) {
308 mStopReadThread.store(true, std::memory_order_release);
309 }
310 if (mEfGroup) {
311 mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
312 }
313 return Result::OK;
314 }
315
316 // Methods from ::android::hardware::audio::AUDIO_HAL_VERSION::IStreamIn follow.
getAudioSource(getAudioSource_cb _hidl_cb)317 Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb) {
318 int halSource;
319 Result retval = mStreamCommon->getParam(AudioParameter::keyInputSource, &halSource);
320 AudioSource source(AudioSource::DEFAULT);
321 if (retval == Result::OK) {
322 source = AudioSource(halSource);
323 }
324 _hidl_cb(retval, source);
325 return Void();
326 }
327
setGain(float gain)328 Return<Result> StreamIn::setGain(float gain) {
329 if (!isGainNormalized(gain)) {
330 ALOGW("Can not set a stream input gain (%f) outside [0,1]", gain);
331 return Result::INVALID_ARGUMENTS;
332 }
333 return Stream::analyzeStatus("set_gain", mStream->set_gain(mStream, gain));
334 }
335
prepareForReading(uint32_t frameSize,uint32_t framesCount,prepareForReading_cb _hidl_cb)336 Return<void> StreamIn::prepareForReading(uint32_t frameSize, uint32_t framesCount,
337 prepareForReading_cb _hidl_cb) {
338 status_t status;
339 ThreadInfo threadInfo = {0, 0};
340
341 // Wrap the _hidl_cb to return an error
342 auto sendError = [&threadInfo, &_hidl_cb](Result result) {
343 _hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(),
344 threadInfo);
345
346 };
347
348 // Create message queues.
349 if (mDataMQ) {
350 ALOGE("the client attempts to call prepareForReading twice");
351 sendError(Result::INVALID_STATE);
352 return Void();
353 }
354 std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1));
355
356 // Check frameSize and framesCount
357 if (frameSize == 0 || framesCount == 0) {
358 ALOGE("Null frameSize (%u) or framesCount (%u)", frameSize, framesCount);
359 sendError(Result::INVALID_ARGUMENTS);
360 return Void();
361 }
362
363 if (frameSize > Stream::MAX_BUFFER_SIZE / framesCount) {
364 ALOGE("Buffer too big: %u*%u bytes > MAX_BUFFER_SIZE (%u)", frameSize, framesCount,
365 Stream::MAX_BUFFER_SIZE);
366 sendError(Result::INVALID_ARGUMENTS);
367 return Void();
368 }
369 std::unique_ptr<DataMQ> tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */));
370
371 std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
372 if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
373 ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid");
374 ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
375 ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
376 sendError(Result::INVALID_ARGUMENTS);
377 return Void();
378 }
379 EventFlag* tempRawEfGroup{};
380 status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &tempRawEfGroup);
381 std::unique_ptr<EventFlag, void (*)(EventFlag*)> tempElfGroup(
382 tempRawEfGroup, [](auto* ef) { EventFlag::deleteEventFlag(&ef); });
383 if (status != OK || !tempElfGroup) {
384 ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
385 sendError(Result::INVALID_ARGUMENTS);
386 return Void();
387 }
388
389 // Create and launch the thread.
390 auto tempReadThread =
391 std::make_unique<ReadThread>(&mStopReadThread, mStream, tempCommandMQ.get(),
392 tempDataMQ.get(), tempStatusMQ.get(), tempElfGroup.get());
393 if (!tempReadThread->init()) {
394 ALOGW("failed to start reader thread: %s", strerror(-status));
395 sendError(Result::INVALID_ARGUMENTS);
396 return Void();
397 }
398 status = tempReadThread->run("reader", PRIORITY_URGENT_AUDIO);
399 if (status != OK) {
400 ALOGW("failed to start reader thread: %s", strerror(-status));
401 sendError(Result::INVALID_ARGUMENTS);
402 return Void();
403 }
404
405 mCommandMQ = std::move(tempCommandMQ);
406 mDataMQ = std::move(tempDataMQ);
407 mStatusMQ = std::move(tempStatusMQ);
408 mReadThread = tempReadThread.release();
409 mEfGroup = tempElfGroup.release();
410 threadInfo.pid = getpid();
411 threadInfo.tid = mReadThread->getTid();
412 _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(),
413 threadInfo);
414 return Void();
415 }
416
getInputFramesLost()417 Return<uint32_t> StreamIn::getInputFramesLost() {
418 return mStream->get_input_frames_lost(mStream);
419 }
420
421 // static
getCapturePositionImpl(audio_stream_in_t * stream,uint64_t * frames,uint64_t * time)422 Result StreamIn::getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames,
423 uint64_t* time) {
424 // HAL may have a stub function, always returning ENOSYS, don't
425 // spam the log in this case.
426 static const std::vector<int> ignoredErrors{ENOSYS};
427 Result retval(Result::NOT_SUPPORTED);
428 if (stream->get_capture_position == NULL) return retval;
429 int64_t halFrames, halTime;
430 retval = Stream::analyzeStatus("get_capture_position",
431 stream->get_capture_position(stream, &halFrames, &halTime),
432 ignoredErrors);
433 if (retval == Result::OK) {
434 *frames = halFrames;
435 *time = halTime;
436 }
437 return retval;
438 };
439
getCapturePosition(getCapturePosition_cb _hidl_cb)440 Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb) {
441 uint64_t frames = 0, time = 0;
442 Result retval = getCapturePositionImpl(mStream, &frames, &time);
443 _hidl_cb(retval, frames, time);
444 return Void();
445 }
446
debug(const hidl_handle & fd,const hidl_vec<hidl_string> & options)447 Return<void> StreamIn::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
448 return mStreamCommon->debug(fd, options);
449 }
450
451 #ifdef AUDIO_HAL_VERSION_4_0
updateSinkMetadata(const SinkMetadata & sinkMetadata)452 Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
453 if (mStream->update_sink_metadata == nullptr) {
454 return Void(); // not supported by the HAL
455 }
456 std::vector<record_track_metadata> halTracks;
457 halTracks.reserve(sinkMetadata.tracks.size());
458 for (auto& metadata : sinkMetadata.tracks) {
459 halTracks.push_back(
460 {.source = static_cast<audio_source_t>(metadata.source), .gain = metadata.gain});
461 }
462 const sink_metadata_t halMetadata = {
463 .track_count = halTracks.size(), .tracks = halTracks.data(),
464 };
465 mStream->update_sink_metadata(mStream, &halMetadata);
466 return Void();
467 }
468
getActiveMicrophones(getActiveMicrophones_cb _hidl_cb)469 Return<void> StreamIn::getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) {
470 Result retval = Result::NOT_SUPPORTED;
471 size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT;
472 audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
473
474 hidl_vec<MicrophoneInfo> microphones;
475 if (mStream->get_active_microphones != NULL &&
476 mStream->get_active_microphones(mStream, &mic_array[0], &actual_mics) == 0) {
477 microphones.resize(actual_mics);
478 for (size_t i = 0; i < actual_mics; ++i) {
479 halToMicrophoneCharacteristics(µphones[i], mic_array[i]);
480 }
481 retval = Result::OK;
482 }
483
484 _hidl_cb(retval, microphones);
485 return Void();
486 }
487 #endif
488
489 } // namespace implementation
490 } // namespace AUDIO_HAL_VERSION
491 } // namespace audio
492 } // namespace hardware
493 } // namespace android
494