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
27using ::android::hardware::audio::AUDIO_HAL_VERSION::MessageQueueFlagBits;
28#include "Conversions.h"
29
30namespace android {
31namespace hardware {
32namespace audio {
33namespace AUDIO_HAL_VERSION {
34namespace implementation {
35
36using ::android::hardware::audio::common::AUDIO_HAL_VERSION::ThreadInfo;
37
38namespace {
39
40class ReadThread : public Thread {
41   public:
42    // ReadThread's lifespan never exceeds StreamIn's lifespan.
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) {}
53    bool init() {
54        mBuffer.reset(new (std::nothrow) uint8_t[mDataMQ->getQuantumCount()]);
55        return mBuffer != nullptr;
56    }
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
76void 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
98void ReadThread::doGetCapturePosition() {
99    mStatus.retval = StreamIn::getCapturePositionImpl(
100        mStream, &mStatus.reply.capturePosition.frames, &mStatus.reply.capturePosition.time);
101}
102
103bool 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
140StreamIn::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
149StreamIn::~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.
166Return<uint64_t> StreamIn::getFrameSize() {
167    return audio_stream_in_frame_size(mStream);
168}
169
170Return<uint64_t> StreamIn::getFrameCount() {
171    return mStreamCommon->getFrameCount();
172}
173
174Return<uint64_t> StreamIn::getBufferSize() {
175    return mStreamCommon->getBufferSize();
176}
177
178Return<uint32_t> StreamIn::getSampleRate() {
179    return mStreamCommon->getSampleRate();
180}
181
182#ifdef AUDIO_HAL_VERSION_2_0
183Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
184    return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
185}
186Return<void> StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
187    return mStreamCommon->getSupportedSampleRates(_hidl_cb);
188}
189#endif
190
191Return<void> StreamIn::getSupportedChannelMasks(AudioFormat format,
192                                                getSupportedChannelMasks_cb _hidl_cb) {
193    return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb);
194}
195Return<void> StreamIn::getSupportedSampleRates(AudioFormat format,
196                                               getSupportedSampleRates_cb _hidl_cb) {
197    return mStreamCommon->getSupportedSampleRates(format, _hidl_cb);
198}
199
200Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz) {
201    return mStreamCommon->setSampleRate(sampleRateHz);
202}
203
204Return<AudioChannelBitfield> StreamIn::getChannelMask() {
205    return mStreamCommon->getChannelMask();
206}
207
208Return<Result> StreamIn::setChannelMask(AudioChannelBitfield mask) {
209    return mStreamCommon->setChannelMask(mask);
210}
211
212Return<AudioFormat> StreamIn::getFormat() {
213    return mStreamCommon->getFormat();
214}
215
216Return<void> StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
217    return mStreamCommon->getSupportedFormats(_hidl_cb);
218}
219
220Return<Result> StreamIn::setFormat(AudioFormat format) {
221    return mStreamCommon->setFormat(format);
222}
223
224Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb) {
225    return mStreamCommon->getAudioProperties(_hidl_cb);
226}
227
228Return<Result> StreamIn::addEffect(uint64_t effectId) {
229    return mStreamCommon->addEffect(effectId);
230}
231
232Return<Result> StreamIn::removeEffect(uint64_t effectId) {
233    return mStreamCommon->removeEffect(effectId);
234}
235
236Return<Result> StreamIn::standby() {
237    return mStreamCommon->standby();
238}
239
240Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) {
241    return mStreamCommon->setHwAvSync(hwAvSync);
242}
243
244#ifdef AUDIO_HAL_VERSION_2_0
245Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected) {
246    return mStreamCommon->setConnectedState(address, connected);
247}
248
249Return<AudioDevice> StreamIn::getDevice() {
250    return mStreamCommon->getDevice();
251}
252
253Return<Result> StreamIn::setDevice(const DeviceAddress& address) {
254    return mStreamCommon->setDevice(address);
255}
256
257Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
258    return mStreamCommon->getParameters(keys, _hidl_cb);
259}
260
261Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& parameters) {
262    return mStreamCommon->setParameters(parameters);
263}
264
265Return<void> StreamIn::debugDump(const hidl_handle& fd) {
266    return mStreamCommon->debugDump(fd);
267}
268#elif defined(AUDIO_HAL_VERSION_4_0)
269Return<void> StreamIn::getDevices(getDevices_cb _hidl_cb) {
270    return mStreamCommon->getDevices(_hidl_cb);
271}
272
273Return<Result> StreamIn::setDevices(const hidl_vec<DeviceAddress>& devices) {
274    return mStreamCommon->setDevices(devices);
275}
276Return<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
281Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& context,
282                                       const hidl_vec<ParameterValue>& parameters) {
283    return mStreamCommon->setParameters(context, parameters);
284}
285#endif
286
287Return<Result> StreamIn::start() {
288    return mStreamMmap->start();
289}
290
291Return<Result> StreamIn::stop() {
292    return mStreamMmap->stop();
293}
294
295Return<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
300Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) {
301    return mStreamMmap->getMmapPosition(_hidl_cb);
302}
303
304Return<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.
317Return<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
328Return<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
336Return<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
417Return<uint32_t> StreamIn::getInputFramesLost() {
418    return mStream->get_input_frames_lost(mStream);
419}
420
421// static
422Result 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
440Return<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
447Return<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
452Return<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
469Return<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(&microphones[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