1 /*
2 * Copyright (C) 2020 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 <log/log.h>
18 #include <fmq/EventFlag.h>
19 #include <fmq/MessageQueue.h>
20 #include <hidl/MQDescriptor.h>
21 #include <hidl/Status.h>
22 #include "stream_in.h"
23 #include "device_port_source.h"
24 #include "deleters.h"
25 #include "util.h"
26 #include "debug.h"
27 #include <sys/resource.h>
28 #include <pthread.h>
29 #include <cutils/sched_policy.h>
30 #include <utils/ThreadDefs.h>
31 #include <future>
32 #include <thread>
33
34 namespace android {
35 namespace hardware {
36 namespace audio {
37 namespace V6_0 {
38 namespace implementation {
39
40 using ::android::hardware::Void;
41
42 namespace {
43
44 struct ReadThread : public IOThread {
45 typedef MessageQueue<IStreamIn::ReadParameters, kSynchronizedReadWrite> CommandMQ;
46 typedef MessageQueue<IStreamIn::ReadStatus, kSynchronizedReadWrite> StatusMQ;
47 typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
48
ReadThreadandroid::hardware::audio::V6_0::implementation::__anon5134eb280111::ReadThread49 ReadThread(StreamIn *stream, const size_t bufferSize)
50 : mStream(stream)
51 , mCommandMQ(1)
52 , mStatusMQ(1)
53 , mDataMQ(bufferSize, true /* EventFlag */) {
54 if (!mCommandMQ.isValid()) {
55 ALOGE("ReadThread::%s:%d: mCommandMQ is invalid", __func__, __LINE__);
56 return;
57 }
58 if (!mDataMQ.isValid()) {
59 ALOGE("ReadThread::%s:%d: mDataMQ is invalid", __func__, __LINE__);
60 return;
61 }
62 if (!mStatusMQ.isValid()) {
63 ALOGE("ReadThread::%s:%d: mStatusMQ is invalid", __func__, __LINE__);
64 return;
65 }
66
67 status_t status;
68
69 EventFlag* rawEfGroup = nullptr;
70 status = EventFlag::createEventFlag(mDataMQ.getEventFlagWord(), &rawEfGroup);
71 if (status != OK || !rawEfGroup) {
72 ALOGE("ReadThread::%s:%d: rawEfGroup is invalid", __func__, __LINE__);
73 return;
74 } else {
75 mEfGroup.reset(rawEfGroup);
76 }
77
78 mThread = std::thread(&ReadThread::threadLoop, this);
79 }
80
~ReadThreadandroid::hardware::audio::V6_0::implementation::__anon5134eb280111::ReadThread81 ~ReadThread() {
82 if (mThread.joinable()) {
83 requestExit();
84 mThread.join();
85 }
86 }
87
getEventFlagandroid::hardware::audio::V6_0::implementation::__anon5134eb280111::ReadThread88 EventFlag *getEventFlag() override {
89 return mEfGroup.get();
90 }
91
isRunningandroid::hardware::audio::V6_0::implementation::__anon5134eb280111::ReadThread92 bool isRunning() const {
93 return mThread.joinable();
94 }
95
getTidandroid::hardware::audio::V6_0::implementation::__anon5134eb280111::ReadThread96 std::future<pthread_t> getTid() {
97 return mTid.get_future();
98 }
99
threadLoopandroid::hardware::audio::V6_0::implementation::__anon5134eb280111::ReadThread100 void threadLoop() {
101 setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_AUDIO);
102 set_sched_policy(0, SP_FOREGROUND);
103 mTid.set_value(pthread_self());
104
105 while (true) {
106 uint32_t efState = 0;
107 mEfGroup->wait(MessageQueueFlagBits::NOT_FULL | EXIT_REQUEST | STAND_BY_REQUEST,
108 &efState);
109 if (efState & EXIT_REQUEST) {
110 return;
111 }
112
113 if (efState & STAND_BY_REQUEST) {
114 mSource.reset();
115 mBuffer.reset();
116 }
117
118 if (efState & (MessageQueueFlagBits::NOT_FULL | 0)) {
119 if (!mSource) {
120 mBuffer.reset(new uint8_t[mDataMQ.getQuantumCount()]);
121 LOG_ALWAYS_FATAL_IF(!mBuffer);
122
123 mSource = DevicePortSource::create(mStream->getDeviceAddress(),
124 mStream->getAudioConfig(),
125 mStream->getAudioOutputFlags(),
126 mStream->getFrameCounter());
127 LOG_ALWAYS_FATAL_IF(!mSource);
128 }
129
130 processCommand();
131 }
132 }
133 }
134
processCommandandroid::hardware::audio::V6_0::implementation::__anon5134eb280111::ReadThread135 void processCommand() {
136 IStreamIn::ReadParameters rParameters;
137
138 if (!mCommandMQ.read(&rParameters)) {
139 return; // Nothing to do.
140 }
141
142 IStreamIn::ReadStatus rStatus;
143 switch (rParameters.command) {
144 case IStreamIn::ReadCommand::READ:
145 rStatus = doRead(rParameters);
146 break;
147
148 case IStreamIn::ReadCommand::GET_CAPTURE_POSITION:
149 rStatus = doGetCapturePosition();
150 break;
151
152 default:
153 ALOGE("ReadThread::%s:%d: Unknown read thread command code %d",
154 __func__, __LINE__, rParameters.command);
155 rStatus.retval = FAILURE(Result::NOT_SUPPORTED);
156 break;
157 }
158
159 rStatus.replyTo = rParameters.command;
160
161 if (!mStatusMQ.write(&rStatus)) {
162 ALOGE("ReadThread::%s:%d: status message queue write failed", __func__, __LINE__);
163 }
164
165 mEfGroup->wake(MessageQueueFlagBits::NOT_EMPTY | 0);
166 }
167
doReadandroid::hardware::audio::V6_0::implementation::__anon5134eb280111::ReadThread168 IStreamIn::ReadStatus doRead(const IStreamIn::ReadParameters &rParameters) {
169 const size_t bytesToRead = std::min(mDataMQ.availableToWrite(),
170 static_cast<size_t>(rParameters.params.read));
171
172 IStreamIn::ReadStatus status;
173 size_t read = 0;
174 status.retval = doReadImpl(&mBuffer[0], bytesToRead, read);
175 if (status.retval == Result::OK) {
176 if (!mDataMQ.write(&mBuffer[0], read)) {
177 ALOGE("ReadThread::%s:%d: mDataMQ.write failed", __func__, __LINE__);
178 }
179 status.reply.read = read;
180 }
181
182 return status;
183 }
184
doReadImplandroid::hardware::audio::V6_0::implementation::__anon5134eb280111::ReadThread185 Result doReadImpl(uint8_t *const data, const size_t toRead, size_t &read) {
186 const int res = mSource->read(data, toRead);
187 if (res < 0) {
188 memset(data, 0, toRead);
189 read = toRead;
190 ALOGE("StreamInReadThread::%s:%d pcm_read failed with %s",
191 __func__, __LINE__, strerror(-res));
192 } else {
193 read = res;
194 }
195
196 return Result::OK;
197 }
198
doGetCapturePositionandroid::hardware::audio::V6_0::implementation::__anon5134eb280111::ReadThread199 IStreamIn::ReadStatus doGetCapturePosition() {
200 IStreamIn::ReadStatus status;
201
202 status.retval = mSource->getCapturePosition(
203 status.reply.capturePosition.frames,
204 status.reply.capturePosition.time);
205
206 return status;
207 }
208
209 StreamIn *const mStream;
210 CommandMQ mCommandMQ;
211 StatusMQ mStatusMQ;
212 DataMQ mDataMQ;
213 std::unique_ptr<EventFlag, deleters::forEventFlag> mEfGroup;
214 std::unique_ptr<uint8_t[]> mBuffer;
215 std::unique_ptr<DevicePortSource> mSource;
216 std::thread mThread;
217 std::promise<pthread_t> mTid;
218 };
219
220 } // namespace
221
StreamIn(sp<IDevice> dev,void (* unrefDevice)(IDevice *),int32_t ioHandle,const DeviceAddress & device,const AudioConfig & config,hidl_bitfield<AudioInputFlag> flags,const SinkMetadata & sinkMetadata)222 StreamIn::StreamIn(sp<IDevice> dev,
223 void (*unrefDevice)(IDevice*),
224 int32_t ioHandle,
225 const DeviceAddress& device,
226 const AudioConfig& config,
227 hidl_bitfield<AudioInputFlag> flags,
228 const SinkMetadata& sinkMetadata)
229 : mDev(std::move(dev))
230 , mUnrefDevice(unrefDevice)
231 , mCommon(ioHandle, device, config, flags)
232 , mSinkMetadata(sinkMetadata) {
233 }
234
~StreamIn()235 StreamIn::~StreamIn() {
236 closeImpl(true);
237 }
238
getFrameSize()239 Return<uint64_t> StreamIn::getFrameSize() {
240 return mCommon.getFrameSize();
241 }
242
getFrameCount()243 Return<uint64_t> StreamIn::getFrameCount() {
244 return mCommon.getFrameCount();
245 }
246
getBufferSize()247 Return<uint64_t> StreamIn::getBufferSize() {
248 return mCommon.getBufferSize();
249 }
250
getSampleRate()251 Return<uint32_t> StreamIn::getSampleRate() {
252 return mCommon.getSampleRate();
253 }
254
getSupportedSampleRates(AudioFormat format,getSupportedSampleRates_cb _hidl_cb)255 Return<void> StreamIn::getSupportedSampleRates(AudioFormat format,
256 getSupportedSampleRates_cb _hidl_cb) {
257 mCommon.getSupportedSampleRates(format, _hidl_cb);
258 return Void();
259 }
260
setSampleRate(uint32_t sampleRateHz)261 Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz) {
262 return mCommon.setSampleRate(sampleRateHz);
263 }
264
getChannelMask()265 Return<hidl_bitfield<AudioChannelMask>> StreamIn::getChannelMask() {
266 return mCommon.getChannelMask();
267 }
268
getSupportedChannelMasks(AudioFormat format,IStream::getSupportedChannelMasks_cb _hidl_cb)269 Return<void> StreamIn::getSupportedChannelMasks(AudioFormat format,
270 IStream::getSupportedChannelMasks_cb _hidl_cb) {
271 mCommon.getSupportedChannelMasks(format, _hidl_cb);
272 return Void();
273 }
274
setChannelMask(hidl_bitfield<AudioChannelMask> mask)275 Return<Result> StreamIn::setChannelMask(hidl_bitfield<AudioChannelMask> mask) {
276 return mCommon.setChannelMask(mask);
277 }
278
getFormat()279 Return<AudioFormat> StreamIn::getFormat() {
280 return mCommon.getFormat();
281 }
282
getSupportedFormats(getSupportedFormats_cb _hidl_cb)283 Return<void> StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
284 mCommon.getSupportedFormats(_hidl_cb);
285 return Void();
286 }
287
setFormat(AudioFormat format)288 Return<Result> StreamIn::setFormat(AudioFormat format) {
289 return mCommon.setFormat(format);
290 }
291
getAudioProperties(getAudioProperties_cb _hidl_cb)292 Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb) {
293 mCommon.getAudioProperties(_hidl_cb);
294 return Void();
295 }
296
addEffect(uint64_t effectId)297 Return<Result> StreamIn::addEffect(uint64_t effectId) {
298 (void)effectId;
299 return FAILURE(Result::INVALID_ARGUMENTS);
300 }
301
removeEffect(uint64_t effectId)302 Return<Result> StreamIn::removeEffect(uint64_t effectId) {
303 (void)effectId;
304 return FAILURE(Result::INVALID_ARGUMENTS);
305 }
306
standby()307 Return<Result> StreamIn::standby() {
308 if (mReadThread) {
309 LOG_ALWAYS_FATAL_IF(!mReadThread->standby());
310 }
311
312 return Result::OK;
313 }
314
getDevices(getDevices_cb _hidl_cb)315 Return<void> StreamIn::getDevices(getDevices_cb _hidl_cb) {
316 mCommon.getDevices(_hidl_cb);
317 return Void();
318 }
319
setDevices(const hidl_vec<DeviceAddress> & devices)320 Return<Result> StreamIn::setDevices(const hidl_vec<DeviceAddress>& devices) {
321 return mCommon.setDevices(devices);
322 }
323
getParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)324 Return<void> StreamIn::getParameters(const hidl_vec<ParameterValue>& context,
325 const hidl_vec<hidl_string>& keys,
326 getParameters_cb _hidl_cb) {
327 (void)context;
328 _hidl_cb((keys.size() > 0) ? FAILURE(Result::NOT_SUPPORTED) : Result::OK, {});
329 return Void();
330 }
331
setParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<ParameterValue> & parameters)332 Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& context,
333 const hidl_vec<ParameterValue>& parameters) {
334 (void)context;
335 (void)parameters;
336 return Result::OK;
337 }
338
setHwAvSync(uint32_t hwAvSync)339 Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) {
340 (void)hwAvSync;
341 return FAILURE(Result::NOT_SUPPORTED);
342 }
343
start()344 Return<Result> StreamIn::start() {
345 return FAILURE(Result::NOT_SUPPORTED);
346 }
347
stop()348 Return<Result> StreamIn::stop() {
349 return FAILURE(Result::NOT_SUPPORTED);
350 }
351
createMmapBuffer(int32_t minSizeFrames,createMmapBuffer_cb _hidl_cb)352 Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames,
353 createMmapBuffer_cb _hidl_cb) {
354 (void)minSizeFrames;
355 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
356 return Void();
357 }
358
getMmapPosition(getMmapPosition_cb _hidl_cb)359 Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) {
360 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
361 return Void();
362 }
363
closeImpl(const bool fromDctor)364 Result StreamIn::closeImpl(const bool fromDctor) {
365 if (mDev) {
366 mReadThread.reset();
367 mUnrefDevice(mDev.get());
368 mDev = nullptr;
369 return Result::OK;
370 } else if (fromDctor) {
371 // closeImpl is always called from the dctor, it is ok if mDev is null,
372 // we don't want to log the error in this case.
373 return Result::OK;
374 } else {
375 return FAILURE(Result::INVALID_STATE);
376 }
377 }
378
close()379 Return<Result> StreamIn::close() {
380 return closeImpl(false);
381 }
382
getAudioSource(getAudioSource_cb _hidl_cb)383 Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb) {
384 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), {});
385 return Void();
386 }
387
setGain(float gain)388 Return<Result> StreamIn::setGain(float gain) {
389 (void)gain;
390 return FAILURE(Result::NOT_SUPPORTED);
391 }
392
updateSinkMetadata(const SinkMetadata & sinkMetadata)393 Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
394 (void)sinkMetadata;
395 return Void();
396 }
397
prepareForReading(uint32_t frameSize,uint32_t framesCount,prepareForReading_cb _hidl_cb)398 Return<void> StreamIn::prepareForReading(uint32_t frameSize,
399 uint32_t framesCount,
400 prepareForReading_cb _hidl_cb) {
401 if (!frameSize || !framesCount || frameSize > 256 || framesCount > (1u << 20)) {
402 _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), {}, {}, {}, {});
403 return Void();
404 }
405
406 if (mReadThread) { // INVALID_STATE if the method was already called.
407 _hidl_cb(FAILURE(Result::INVALID_STATE), {}, {}, {}, {});
408 return Void();
409 }
410
411 auto t = std::make_unique<ReadThread>(this, frameSize * framesCount);
412
413 if (t->isRunning()) {
414 _hidl_cb(Result::OK,
415 *(t->mCommandMQ.getDesc()),
416 *(t->mDataMQ.getDesc()),
417 *(t->mStatusMQ.getDesc()),
418 {.pid = getpid(), .tid = t->getTid().get()});
419
420 mReadThread = std::move(t);
421 } else {
422 _hidl_cb(FAILURE(Result::INVALID_ARGUMENTS), {}, {}, {}, {});
423 }
424
425 return Void();
426 }
427
getInputFramesLost()428 Return<uint32_t> StreamIn::getInputFramesLost() {
429 return 0;
430 }
431
getCapturePosition(getCapturePosition_cb _hidl_cb)432 Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb) {
433 _hidl_cb(FAILURE(Result::NOT_SUPPORTED), 0, 0); // see ReadThread::doGetCapturePosition
434 return Void();
435 }
436
getActiveMicrophones(getActiveMicrophones_cb _hidl_cb)437 Return<void> StreamIn::getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) {
438 _hidl_cb(Result::OK, {util::getMicrophoneInfo()});
439 return Void();
440 }
441
setMicrophoneDirection(MicrophoneDirection direction)442 Return<Result> StreamIn::setMicrophoneDirection(MicrophoneDirection direction) {
443 (void)direction;
444 return FAILURE(Result::NOT_SUPPORTED);
445 }
446
setMicrophoneFieldDimension(float zoom)447 Return<Result> StreamIn::setMicrophoneFieldDimension(float zoom) {
448 (void)zoom;
449 return FAILURE(Result::NOT_SUPPORTED);
450 }
451
452 } // namespace implementation
453 } // namespace V6_0
454 } // namespace audio
455 } // namespace hardware
456 } // namespace android
457