• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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