StreamOut.impl.h revision 67d550888a021633cc33cb284bb0658b008887c6
110548295023bee99108e418499aff09fe578211eMikhail Naganov/* 210548295023bee99108e418499aff09fe578211eMikhail Naganov * Copyright (C) 2016 The Android Open Source Project 310548295023bee99108e418499aff09fe578211eMikhail Naganov * 410548295023bee99108e418499aff09fe578211eMikhail Naganov * Licensed under the Apache License, Version 2.0 (the "License"); 510548295023bee99108e418499aff09fe578211eMikhail Naganov * you may not use this file except in compliance with the License. 610548295023bee99108e418499aff09fe578211eMikhail Naganov * You may obtain a copy of the License at 710548295023bee99108e418499aff09fe578211eMikhail Naganov * 810548295023bee99108e418499aff09fe578211eMikhail Naganov * http://www.apache.org/licenses/LICENSE-2.0 910548295023bee99108e418499aff09fe578211eMikhail Naganov * 1010548295023bee99108e418499aff09fe578211eMikhail Naganov * Unless required by applicable law or agreed to in writing, software 1110548295023bee99108e418499aff09fe578211eMikhail Naganov * distributed under the License is distributed on an "AS IS" BASIS, 1210548295023bee99108e418499aff09fe578211eMikhail Naganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1310548295023bee99108e418499aff09fe578211eMikhail Naganov * See the License for the specific language governing permissions and 1410548295023bee99108e418499aff09fe578211eMikhail Naganov * limitations under the License. 1510548295023bee99108e418499aff09fe578211eMikhail Naganov */ 1610548295023bee99108e418499aff09fe578211eMikhail Naganov 1710548295023bee99108e418499aff09fe578211eMikhail Naganov#define LOG_TAG "StreamOutHAL" 18685f0e36a1185b24f473f0382ba2175685dbcdf9Mikhail Naganov//#define LOG_NDEBUG 0 19b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov#define ATRACE_TAG ATRACE_TAG_AUDIO 2010548295023bee99108e418499aff09fe578211eMikhail Naganov 2167d550888a021633cc33cb284bb0658b008887c6Kevin Rocard#include <memory> 2267d550888a021633cc33cb284bb0658b008887c6Kevin Rocard 23f9d303435d80161fabb16cdff3b8f2f75f362480Yifan Hong#include <android/log.h> 24b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov#include <hardware/audio.h> 25b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov#include <utils/Trace.h> 2610548295023bee99108e418499aff09fe578211eMikhail Naganov 2710548295023bee99108e418499aff09fe578211eMikhail Naganov#include "StreamOut.h" 2810548295023bee99108e418499aff09fe578211eMikhail Naganov 2910548295023bee99108e418499aff09fe578211eMikhail Naganovnamespace android { 3010548295023bee99108e418499aff09fe578211eMikhail Naganovnamespace hardware { 3110548295023bee99108e418499aff09fe578211eMikhail Naganovnamespace audio { 3210548295023bee99108e418499aff09fe578211eMikhail Naganovnamespace V2_0 { 3310548295023bee99108e418499aff09fe578211eMikhail Naganovnamespace implementation { 3410548295023bee99108e418499aff09fe578211eMikhail Naganov 35a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganovusing ::android::hardware::audio::common::V2_0::ThreadInfo; 36a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov 37b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganovnamespace { 38b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 39b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganovclass WriteThread : public Thread { 40b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov public: 41b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // WriteThread's lifespan never exceeds StreamOut's lifespan. 42b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov WriteThread(std::atomic<bool>* stop, 43b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov audio_stream_out_t* stream, 44a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov StreamOut::CommandMQ* commandMQ, 45b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov StreamOut::DataMQ* dataMQ, 46b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov StreamOut::StatusMQ* statusMQ, 47a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov EventFlag* efGroup) 48b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov : Thread(false /*canCallJava*/), 49b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStop(stop), 50b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStream(stream), 51a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mCommandMQ(commandMQ), 52b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mDataMQ(dataMQ), 53b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStatusMQ(statusMQ), 54b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mEfGroup(efGroup), 5567d550888a021633cc33cb284bb0658b008887c6Kevin Rocard mBuffer(nullptr) { 5667d550888a021633cc33cb284bb0658b008887c6Kevin Rocard } 5767d550888a021633cc33cb284bb0658b008887c6Kevin Rocard bool init() { 5867d550888a021633cc33cb284bb0658b008887c6Kevin Rocard mBuffer.reset(new(std::nothrow) uint8_t[mDataMQ->getQuantumCount()]); 5967d550888a021633cc33cb284bb0658b008887c6Kevin Rocard return mBuffer != nullptr; 60b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 61b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov virtual ~WriteThread() {} 62b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 63b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov private: 64b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov std::atomic<bool>* mStop; 65b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov audio_stream_out_t* mStream; 66a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov StreamOut::CommandMQ* mCommandMQ; 67b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov StreamOut::DataMQ* mDataMQ; 68b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov StreamOut::StatusMQ* mStatusMQ; 69b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov EventFlag* mEfGroup; 70b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov std::unique_ptr<uint8_t[]> mBuffer; 71a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov IStreamOut::WriteStatus mStatus; 72b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 73b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov bool threadLoop() override; 74a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov 75a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov void doGetLatency(); 76a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov void doGetPresentationPosition(); 77a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov void doWrite(); 78b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov}; 79b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 80a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganovvoid WriteThread::doWrite() { 81a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov const size_t availToRead = mDataMQ->availableToRead(); 82a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.retval = Result::OK; 83a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.reply.written = 0; 84a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (mDataMQ->read(&mBuffer[0], availToRead)) { 85a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov ssize_t writeResult = mStream->write(mStream, &mBuffer[0], availToRead); 86a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (writeResult >= 0) { 87a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.reply.written = writeResult; 88a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov } else { 89a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.retval = Stream::analyzeStatus("write", writeResult); 90a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov } 91a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov } 92a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov} 93a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov 94a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganovvoid WriteThread::doGetPresentationPosition() { 95a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.retval = StreamOut::getPresentationPositionImpl( 96a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStream, 97a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov &mStatus.reply.presentationPosition.frames, 98a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov &mStatus.reply.presentationPosition.timeStamp); 99a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov} 100a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov 101a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganovvoid WriteThread::doGetLatency() { 102a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.retval = Result::OK; 103a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.reply.latencyMs = mStream->get_latency(mStream); 104a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov} 105a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov 106b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganovbool WriteThread::threadLoop() { 107b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // This implementation doesn't return control back to the Thread until it decides to stop, 108b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // as the Thread uses mutexes, and this can lead to priority inversion. 109b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) { 110b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov uint32_t efState = 0; 111e867456982c1ee68e884294f5655abb6212ab533Mikhail Naganov mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState); 112b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) { 113b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov continue; // Nothing to do. 114b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 115a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (!mCommandMQ->read(&mStatus.replyTo)) { 116a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov continue; // Nothing to do. 117a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov } 118a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov switch (mStatus.replyTo) { 119a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov case IStreamOut::WriteCommand::WRITE: 120a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov doWrite(); 121a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov break; 122a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov case IStreamOut::WriteCommand::GET_PRESENTATION_POSITION: 123a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov doGetPresentationPosition(); 124a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov break; 125a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov case IStreamOut::WriteCommand::GET_LATENCY: 126a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov doGetLatency(); 127a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov break; 128a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov default: 129a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov ALOGE("Unknown write thread command code %d", mStatus.replyTo); 130a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.retval = Result::NOT_SUPPORTED; 131a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov break; 132b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 133a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (!mStatusMQ->write(&mStatus)) { 134a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov ALOGE("status message queue write failed"); 135b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 136b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)); 137b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 138b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 139b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return false; 140b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov} 141b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 142b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov} // namespace 143b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 144936279e1ffe6bf7e842c46f9a94d98a48dce6754Mikhail NaganovStreamOut::StreamOut(const sp<Device>& device, audio_stream_out_t* stream) 145b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov : mIsClosed(false), mDevice(device), mStream(stream), 1467deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent mStreamCommon(new Stream(&stream->common)), 147b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStreamMmap(new StreamMmap<audio_stream_out_t>(stream)), 148b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mEfGroup(nullptr), mStopWriteThread(false) { 14910548295023bee99108e418499aff09fe578211eMikhail Naganov} 15010548295023bee99108e418499aff09fe578211eMikhail Naganov 15110548295023bee99108e418499aff09fe578211eMikhail NaganovStreamOut::~StreamOut() { 152b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov ATRACE_CALL(); 153b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov close(); 154b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov if (mWriteThread.get()) { 155b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov ATRACE_NAME("mWriteThread->join"); 156b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov status_t status = mWriteThread->join(); 157b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov ALOGE_IF(status, "write thread exit error: %s", strerror(-status)); 158b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov } 159b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov if (mEfGroup) { 160b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov status_t status = EventFlag::deleteEventFlag(&mEfGroup); 161b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status)); 162b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov } 163b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov mCallback.clear(); 164936279e1ffe6bf7e842c46f9a94d98a48dce6754Mikhail Naganov mDevice->closeOutputStream(mStream); 16510548295023bee99108e418499aff09fe578211eMikhail Naganov mStream = nullptr; 16610548295023bee99108e418499aff09fe578211eMikhail Naganov} 16710548295023bee99108e418499aff09fe578211eMikhail Naganov 16810548295023bee99108e418499aff09fe578211eMikhail Naganov// Methods from ::android::hardware::audio::V2_0::IStream follow. 16910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint64_t> StreamOut::getFrameSize() { 17010548295023bee99108e418499aff09fe578211eMikhail Naganov return audio_stream_out_frame_size(mStream); 17110548295023bee99108e418499aff09fe578211eMikhail Naganov} 17210548295023bee99108e418499aff09fe578211eMikhail Naganov 17310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint64_t> StreamOut::getFrameCount() { 17410548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getFrameCount(); 17510548295023bee99108e418499aff09fe578211eMikhail Naganov} 17610548295023bee99108e418499aff09fe578211eMikhail Naganov 17710548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint64_t> StreamOut::getBufferSize() { 17810548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getBufferSize(); 17910548295023bee99108e418499aff09fe578211eMikhail Naganov} 18010548295023bee99108e418499aff09fe578211eMikhail Naganov 18110548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint32_t> StreamOut::getSampleRate() { 18210548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getSampleRate(); 18310548295023bee99108e418499aff09fe578211eMikhail Naganov} 18410548295023bee99108e418499aff09fe578211eMikhail Naganov 18510548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) { 18610548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getSupportedSampleRates(_hidl_cb); 18710548295023bee99108e418499aff09fe578211eMikhail Naganov} 18810548295023bee99108e418499aff09fe578211eMikhail Naganov 18910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setSampleRate(uint32_t sampleRateHz) { 19010548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setSampleRate(sampleRateHz); 19110548295023bee99108e418499aff09fe578211eMikhail Naganov} 19210548295023bee99108e418499aff09fe578211eMikhail Naganov 19310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<AudioChannelMask> StreamOut::getChannelMask() { 19410548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getChannelMask(); 19510548295023bee99108e418499aff09fe578211eMikhail Naganov} 19610548295023bee99108e418499aff09fe578211eMikhail Naganov 19710548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { 19810548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getSupportedChannelMasks(_hidl_cb); 19910548295023bee99108e418499aff09fe578211eMikhail Naganov} 20010548295023bee99108e418499aff09fe578211eMikhail Naganov 20110548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setChannelMask(AudioChannelMask mask) { 20210548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setChannelMask(mask); 20310548295023bee99108e418499aff09fe578211eMikhail Naganov} 20410548295023bee99108e418499aff09fe578211eMikhail Naganov 20510548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<AudioFormat> StreamOut::getFormat() { 20610548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getFormat(); 20710548295023bee99108e418499aff09fe578211eMikhail Naganov} 20810548295023bee99108e418499aff09fe578211eMikhail Naganov 20910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getSupportedFormats(getSupportedFormats_cb _hidl_cb) { 21010548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getSupportedFormats(_hidl_cb); 21110548295023bee99108e418499aff09fe578211eMikhail Naganov} 21210548295023bee99108e418499aff09fe578211eMikhail Naganov 21310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setFormat(AudioFormat format) { 21410548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setFormat(format); 21510548295023bee99108e418499aff09fe578211eMikhail Naganov} 21610548295023bee99108e418499aff09fe578211eMikhail Naganov 21710548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getAudioProperties(getAudioProperties_cb _hidl_cb) { 21810548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getAudioProperties(_hidl_cb); 21910548295023bee99108e418499aff09fe578211eMikhail Naganov} 22010548295023bee99108e418499aff09fe578211eMikhail Naganov 22110548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::addEffect(uint64_t effectId) { 22210548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->addEffect(effectId); 22310548295023bee99108e418499aff09fe578211eMikhail Naganov} 22410548295023bee99108e418499aff09fe578211eMikhail Naganov 22510548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::removeEffect(uint64_t effectId) { 22610548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->removeEffect(effectId); 22710548295023bee99108e418499aff09fe578211eMikhail Naganov} 22810548295023bee99108e418499aff09fe578211eMikhail Naganov 22910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::standby() { 23010548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->standby(); 23110548295023bee99108e418499aff09fe578211eMikhail Naganov} 23210548295023bee99108e418499aff09fe578211eMikhail Naganov 23310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<AudioDevice> StreamOut::getDevice() { 23410548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getDevice(); 23510548295023bee99108e418499aff09fe578211eMikhail Naganov} 23610548295023bee99108e418499aff09fe578211eMikhail Naganov 23710548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setDevice(const DeviceAddress& address) { 23810548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setDevice(address); 23910548295023bee99108e418499aff09fe578211eMikhail Naganov} 24010548295023bee99108e418499aff09fe578211eMikhail Naganov 24110548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setConnectedState(const DeviceAddress& address, bool connected) { 24210548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setConnectedState(address, connected); 24310548295023bee99108e418499aff09fe578211eMikhail Naganov} 24410548295023bee99108e418499aff09fe578211eMikhail Naganov 24510548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setHwAvSync(uint32_t hwAvSync) { 24610548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setHwAvSync(hwAvSync); 24710548295023bee99108e418499aff09fe578211eMikhail Naganov} 24810548295023bee99108e418499aff09fe578211eMikhail Naganov 24910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getParameters( 25010548295023bee99108e418499aff09fe578211eMikhail Naganov const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) { 25110548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getParameters(keys, _hidl_cb); 25210548295023bee99108e418499aff09fe578211eMikhail Naganov} 25310548295023bee99108e418499aff09fe578211eMikhail Naganov 25410548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setParameters(const hidl_vec<ParameterValue>& parameters) { 25510548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setParameters(parameters); 25610548295023bee99108e418499aff09fe578211eMikhail Naganov} 25710548295023bee99108e418499aff09fe578211eMikhail Naganov 25870b9a15df00a42b319279d903bf5923564920e3bMartijn CoenenReturn<void> StreamOut::debugDump(const hidl_handle& fd) { 25910548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->debugDump(fd); 26010548295023bee99108e418499aff09fe578211eMikhail Naganov} 26110548295023bee99108e418499aff09fe578211eMikhail Naganov 262b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail NaganovReturn<Result> StreamOut::close() { 263b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (mIsClosed) return Result::INVALID_STATE; 264b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mIsClosed = true; 265b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (mWriteThread.get()) { 266b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStopWriteThread.store(true, std::memory_order_release); 267b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 268b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (mEfGroup) { 269b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)); 270b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 271b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Result::OK; 272b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov} 273b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 27410548295023bee99108e418499aff09fe578211eMikhail Naganov// Methods from ::android::hardware::audio::V2_0::IStreamOut follow. 27510548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint32_t> StreamOut::getLatency() { 27610548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->get_latency(mStream); 27710548295023bee99108e418499aff09fe578211eMikhail Naganov} 27810548295023bee99108e418499aff09fe578211eMikhail Naganov 27910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setVolume(float left, float right) { 28010548295023bee99108e418499aff09fe578211eMikhail Naganov Result retval(Result::NOT_SUPPORTED); 28110548295023bee99108e418499aff09fe578211eMikhail Naganov if (mStream->set_volume != NULL) { 2827deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent retval = Stream::analyzeStatus( 28310548295023bee99108e418499aff09fe578211eMikhail Naganov "set_volume", mStream->set_volume(mStream, left, right)); 28410548295023bee99108e418499aff09fe578211eMikhail Naganov } 28510548295023bee99108e418499aff09fe578211eMikhail Naganov return retval; 28610548295023bee99108e418499aff09fe578211eMikhail Naganov} 28710548295023bee99108e418499aff09fe578211eMikhail Naganov 288b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail NaganovReturn<void> StreamOut::prepareForWriting( 289a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov uint32_t frameSize, uint32_t framesCount, prepareForWriting_cb _hidl_cb) { 290b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov status_t status; 291a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov ThreadInfo threadInfo = { 0, 0 }; 292b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // Create message queues. 293b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (mDataMQ) { 294b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGE("the client attempts to call prepareForWriting twice"); 295b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov _hidl_cb(Result::INVALID_STATE, 296a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 297b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Void(); 298b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 299a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1)); 300b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov std::unique_ptr<DataMQ> tempDataMQ( 301b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov new DataMQ(frameSize * framesCount, true /* EventFlag */)); 302b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1)); 303a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) { 304a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid"); 305b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid"); 306b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid"); 307b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov _hidl_cb(Result::INVALID_ARGUMENTS, 308a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 309b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Void(); 310b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 311b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup); 312b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (status != OK || !mEfGroup) { 313b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGE("failed creating event flag for data MQ: %s", strerror(-status)); 314b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov _hidl_cb(Result::INVALID_ARGUMENTS, 315a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 316b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Void(); 317b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 318b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 319b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // Create and launch the thread. 32067d550888a021633cc33cb284bb0658b008887c6Kevin Rocard auto tempWriteThread = std::make_unique<WriteThread>( 321b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov &mStopWriteThread, 322b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStream, 323a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov tempCommandMQ.get(), 324b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov tempDataMQ.get(), 325b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov tempStatusMQ.get(), 326a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov mEfGroup); 32767d550888a021633cc33cb284bb0658b008887c6Kevin Rocard if (!tempWriteThread->init()) { 32867d550888a021633cc33cb284bb0658b008887c6Kevin Rocard _hidl_cb(Result::INVALID_ARGUMENTS, 32967d550888a021633cc33cb284bb0658b008887c6Kevin Rocard CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 33067d550888a021633cc33cb284bb0658b008887c6Kevin Rocard return Void(); 33167d550888a021633cc33cb284bb0658b008887c6Kevin Rocard } 33267d550888a021633cc33cb284bb0658b008887c6Kevin Rocard status = tempWriteThread->run("writer", PRIORITY_URGENT_AUDIO); 333b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (status != OK) { 334b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGW("failed to start writer thread: %s", strerror(-status)); 335b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov _hidl_cb(Result::INVALID_ARGUMENTS, 336a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 337b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Void(); 33810548295023bee99108e418499aff09fe578211eMikhail Naganov } 339b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 340a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mCommandMQ = std::move(tempCommandMQ); 341b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mDataMQ = std::move(tempDataMQ); 342b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStatusMQ = std::move(tempStatusMQ); 34367d550888a021633cc33cb284bb0658b008887c6Kevin Rocard mWriteThread = tempWriteThread.release(); 344a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov threadInfo.pid = getpid(); 345a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov threadInfo.tid = mWriteThread->getTid(); 346a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov _hidl_cb(Result::OK, 347a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(), 348a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov threadInfo); 34910548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 35010548295023bee99108e418499aff09fe578211eMikhail Naganov} 35110548295023bee99108e418499aff09fe578211eMikhail Naganov 35210548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb) { 35310548295023bee99108e418499aff09fe578211eMikhail Naganov uint32_t halDspFrames; 3547deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Result retval = Stream::analyzeStatus( 35510548295023bee99108e418499aff09fe578211eMikhail Naganov "get_render_position", mStream->get_render_position(mStream, &halDspFrames)); 35610548295023bee99108e418499aff09fe578211eMikhail Naganov _hidl_cb(retval, halDspFrames); 35710548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 35810548295023bee99108e418499aff09fe578211eMikhail Naganov} 35910548295023bee99108e418499aff09fe578211eMikhail Naganov 36010548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb) { 36110548295023bee99108e418499aff09fe578211eMikhail Naganov Result retval(Result::NOT_SUPPORTED); 36210548295023bee99108e418499aff09fe578211eMikhail Naganov int64_t timestampUs = 0; 36310548295023bee99108e418499aff09fe578211eMikhail Naganov if (mStream->get_next_write_timestamp != NULL) { 3647deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent retval = Stream::analyzeStatus( 36510548295023bee99108e418499aff09fe578211eMikhail Naganov "get_next_write_timestamp", 36610548295023bee99108e418499aff09fe578211eMikhail Naganov mStream->get_next_write_timestamp(mStream, ×tampUs)); 36710548295023bee99108e418499aff09fe578211eMikhail Naganov } 36810548295023bee99108e418499aff09fe578211eMikhail Naganov _hidl_cb(retval, timestampUs); 36910548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 37010548295023bee99108e418499aff09fe578211eMikhail Naganov} 37110548295023bee99108e418499aff09fe578211eMikhail Naganov 37210548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setCallback(const sp<IStreamOutCallback>& callback) { 37310548295023bee99108e418499aff09fe578211eMikhail Naganov if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED; 37410548295023bee99108e418499aff09fe578211eMikhail Naganov int result = mStream->set_callback(mStream, StreamOut::asyncCallback, this); 37510548295023bee99108e418499aff09fe578211eMikhail Naganov if (result == 0) { 37610548295023bee99108e418499aff09fe578211eMikhail Naganov mCallback = callback; 37710548295023bee99108e418499aff09fe578211eMikhail Naganov } 3787deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return Stream::analyzeStatus("set_callback", result); 37910548295023bee99108e418499aff09fe578211eMikhail Naganov} 38010548295023bee99108e418499aff09fe578211eMikhail Naganov 3816e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail NaganovReturn<Result> StreamOut::clearCallback() { 3826e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED; 3836e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov mCallback.clear(); 3846e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov return Result::OK; 3856e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov} 3866e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov 38710548295023bee99108e418499aff09fe578211eMikhail Naganov// static 38810548295023bee99108e418499aff09fe578211eMikhail Naganovint StreamOut::asyncCallback(stream_callback_event_t event, void*, void *cookie) { 38910548295023bee99108e418499aff09fe578211eMikhail Naganov wp<StreamOut> weakSelf(reinterpret_cast<StreamOut*>(cookie)); 39010548295023bee99108e418499aff09fe578211eMikhail Naganov sp<StreamOut> self = weakSelf.promote(); 3916e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov if (self == nullptr || self->mCallback == nullptr) return 0; 39210548295023bee99108e418499aff09fe578211eMikhail Naganov ALOGV("asyncCallback() event %d", event); 39310548295023bee99108e418499aff09fe578211eMikhail Naganov switch (event) { 39410548295023bee99108e418499aff09fe578211eMikhail Naganov case STREAM_CBK_EVENT_WRITE_READY: 3956e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov self->mCallback->onWriteReady(); 39610548295023bee99108e418499aff09fe578211eMikhail Naganov break; 39710548295023bee99108e418499aff09fe578211eMikhail Naganov case STREAM_CBK_EVENT_DRAIN_READY: 3986e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov self->mCallback->onDrainReady(); 39910548295023bee99108e418499aff09fe578211eMikhail Naganov break; 40010548295023bee99108e418499aff09fe578211eMikhail Naganov case STREAM_CBK_EVENT_ERROR: 4016e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov self->mCallback->onError(); 40210548295023bee99108e418499aff09fe578211eMikhail Naganov break; 40310548295023bee99108e418499aff09fe578211eMikhail Naganov default: 40410548295023bee99108e418499aff09fe578211eMikhail Naganov ALOGW("asyncCallback() unknown event %d", event); 40510548295023bee99108e418499aff09fe578211eMikhail Naganov break; 40610548295023bee99108e418499aff09fe578211eMikhail Naganov } 40710548295023bee99108e418499aff09fe578211eMikhail Naganov return 0; 40810548295023bee99108e418499aff09fe578211eMikhail Naganov} 40910548295023bee99108e418499aff09fe578211eMikhail Naganov 41010548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb) { 41110548295023bee99108e418499aff09fe578211eMikhail Naganov _hidl_cb(mStream->pause != NULL, mStream->resume != NULL); 41210548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 41310548295023bee99108e418499aff09fe578211eMikhail Naganov} 41410548295023bee99108e418499aff09fe578211eMikhail Naganov 41510548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::pause() { 41610548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->pause != NULL ? 4177deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Stream::analyzeStatus("pause", mStream->pause(mStream)) : 41810548295023bee99108e418499aff09fe578211eMikhail Naganov Result::NOT_SUPPORTED; 41910548295023bee99108e418499aff09fe578211eMikhail Naganov} 42010548295023bee99108e418499aff09fe578211eMikhail Naganov 42110548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::resume() { 42210548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->resume != NULL ? 4237deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Stream::analyzeStatus("resume", mStream->resume(mStream)) : 42410548295023bee99108e418499aff09fe578211eMikhail Naganov Result::NOT_SUPPORTED; 42510548295023bee99108e418499aff09fe578211eMikhail Naganov} 42610548295023bee99108e418499aff09fe578211eMikhail Naganov 42710548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<bool> StreamOut::supportsDrain() { 42810548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->drain != NULL; 42910548295023bee99108e418499aff09fe578211eMikhail Naganov} 43010548295023bee99108e418499aff09fe578211eMikhail Naganov 43110548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::drain(AudioDrain type) { 43210548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->drain != NULL ? 4337deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Stream::analyzeStatus( 43410548295023bee99108e418499aff09fe578211eMikhail Naganov "drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type))) : 43510548295023bee99108e418499aff09fe578211eMikhail Naganov Result::NOT_SUPPORTED; 43610548295023bee99108e418499aff09fe578211eMikhail Naganov} 43710548295023bee99108e418499aff09fe578211eMikhail Naganov 43810548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::flush() { 43910548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->flush != NULL ? 4407deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Stream::analyzeStatus("flush", mStream->flush(mStream)) : 44110548295023bee99108e418499aff09fe578211eMikhail Naganov Result::NOT_SUPPORTED; 44210548295023bee99108e418499aff09fe578211eMikhail Naganov} 44310548295023bee99108e418499aff09fe578211eMikhail Naganov 444ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov// static 445ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail NaganovResult StreamOut::getPresentationPositionImpl( 446ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov audio_stream_out_t *stream, uint64_t *frames, TimeSpec *timeStamp) { 44710548295023bee99108e418499aff09fe578211eMikhail Naganov Result retval(Result::NOT_SUPPORTED); 448ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov if (stream->get_presentation_position == NULL) return retval; 449ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov struct timespec halTimeStamp; 450ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov retval = Stream::analyzeStatus( 451ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov "get_presentation_position", 452ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov stream->get_presentation_position(stream, frames, &halTimeStamp), 453ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov // Don't logspam on EINVAL--it's normal for get_presentation_position 454d63e79022a1c244617d6aab7806788570373016aMikhail Naganov // to return it sometimes. EAGAIN may be returned by A2DP audio HAL 455d63e79022a1c244617d6aab7806788570373016aMikhail Naganov // implementation. 456d63e79022a1c244617d6aab7806788570373016aMikhail Naganov EINVAL, EAGAIN); 457ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov if (retval == Result::OK) { 458ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov timeStamp->tvSec = halTimeStamp.tv_sec; 459ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov timeStamp->tvNSec = halTimeStamp.tv_nsec; 460ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov } 461ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov return retval; 462ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov} 463ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov 464ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail NaganovReturn<void> StreamOut::getPresentationPosition(getPresentationPosition_cb _hidl_cb) { 46510548295023bee99108e418499aff09fe578211eMikhail Naganov uint64_t frames = 0; 46610548295023bee99108e418499aff09fe578211eMikhail Naganov TimeSpec timeStamp = { 0, 0 }; 467ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov Result retval = getPresentationPositionImpl(mStream, &frames, &timeStamp); 46810548295023bee99108e418499aff09fe578211eMikhail Naganov _hidl_cb(retval, frames, timeStamp); 46910548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 47010548295023bee99108e418499aff09fe578211eMikhail Naganov} 47110548295023bee99108e418499aff09fe578211eMikhail Naganov 4727deb7dad39e58b6e5de812075950adc27cd51d95Eric LaurentReturn<Result> StreamOut::start() { 4737deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return mStreamMmap->start(); 4747deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent} 4757deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent 4767deb7dad39e58b6e5de812075950adc27cd51d95Eric LaurentReturn<Result> StreamOut::stop() { 4777deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return mStreamMmap->stop(); 4787deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent} 4797deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent 4807deb7dad39e58b6e5de812075950adc27cd51d95Eric LaurentReturn<void> StreamOut::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) { 4817deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return mStreamMmap->createMmapBuffer( 4827deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent minSizeFrames, audio_stream_out_frame_size(mStream), _hidl_cb); 4837deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent} 4847deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent 4857deb7dad39e58b6e5de812075950adc27cd51d95Eric LaurentReturn<void> StreamOut::getMmapPosition(getMmapPosition_cb _hidl_cb) { 4867deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return mStreamMmap->getMmapPosition(_hidl_cb); 4877deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent} 4887deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent 48910548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace implementation 49010548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace V2_0 49110548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace audio 49210548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace hardware 49310548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace android 494