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