StreamOut.impl.h revision 936279e1ffe6bf7e842c46f9a94d98a48dce6754
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 21f9d303435d80161fabb16cdff3b8f2f75f362480Yifan Hong#include <android/log.h> 22b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov#include <hardware/audio.h> 23b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov#include <utils/Trace.h> 2410548295023bee99108e418499aff09fe578211eMikhail Naganov 2510548295023bee99108e418499aff09fe578211eMikhail Naganov#include "StreamOut.h" 2610548295023bee99108e418499aff09fe578211eMikhail Naganov 2710548295023bee99108e418499aff09fe578211eMikhail Naganovnamespace android { 2810548295023bee99108e418499aff09fe578211eMikhail Naganovnamespace hardware { 2910548295023bee99108e418499aff09fe578211eMikhail Naganovnamespace audio { 3010548295023bee99108e418499aff09fe578211eMikhail Naganovnamespace V2_0 { 3110548295023bee99108e418499aff09fe578211eMikhail Naganovnamespace implementation { 3210548295023bee99108e418499aff09fe578211eMikhail Naganov 33a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganovusing ::android::hardware::audio::common::V2_0::ThreadInfo; 34a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov 35b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganovnamespace { 36b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 37b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganovclass WriteThread : public Thread { 38b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov public: 39b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // WriteThread's lifespan never exceeds StreamOut's lifespan. 40b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov WriteThread(std::atomic<bool>* stop, 41b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov audio_stream_out_t* stream, 42a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov StreamOut::CommandMQ* commandMQ, 43b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov StreamOut::DataMQ* dataMQ, 44b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov StreamOut::StatusMQ* statusMQ, 45a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov EventFlag* efGroup) 46b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov : Thread(false /*canCallJava*/), 47b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStop(stop), 48b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStream(stream), 49a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mCommandMQ(commandMQ), 50b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mDataMQ(dataMQ), 51b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStatusMQ(statusMQ), 52b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mEfGroup(efGroup), 53b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mBuffer(new uint8_t[dataMQ->getQuantumCount()]) { 54b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 55b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov virtual ~WriteThread() {} 56b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 57b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov private: 58b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov std::atomic<bool>* mStop; 59b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov audio_stream_out_t* mStream; 60a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov StreamOut::CommandMQ* mCommandMQ; 61b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov StreamOut::DataMQ* mDataMQ; 62b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov StreamOut::StatusMQ* mStatusMQ; 63b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov EventFlag* mEfGroup; 64b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov std::unique_ptr<uint8_t[]> mBuffer; 65a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov IStreamOut::WriteStatus mStatus; 66b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 67b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov bool threadLoop() override; 68a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov 69a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov void doGetLatency(); 70a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov void doGetPresentationPosition(); 71a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov void doWrite(); 72b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov}; 73b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 74a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganovvoid WriteThread::doWrite() { 75a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov const size_t availToRead = mDataMQ->availableToRead(); 76a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.retval = Result::OK; 77a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.reply.written = 0; 78a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (mDataMQ->read(&mBuffer[0], availToRead)) { 79a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov ssize_t writeResult = mStream->write(mStream, &mBuffer[0], availToRead); 80a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (writeResult >= 0) { 81a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.reply.written = writeResult; 82a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov } else { 83a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.retval = Stream::analyzeStatus("write", writeResult); 84a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov } 85a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov } 86a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov} 87a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov 88a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganovvoid WriteThread::doGetPresentationPosition() { 89a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.retval = StreamOut::getPresentationPositionImpl( 90a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStream, 91a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov &mStatus.reply.presentationPosition.frames, 92a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov &mStatus.reply.presentationPosition.timeStamp); 93a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov} 94a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov 95a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganovvoid WriteThread::doGetLatency() { 96a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.retval = Result::OK; 97a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.reply.latencyMs = mStream->get_latency(mStream); 98a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov} 99a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov 100b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganovbool WriteThread::threadLoop() { 101b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // This implementation doesn't return control back to the Thread until it decides to stop, 102b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // as the Thread uses mutexes, and this can lead to priority inversion. 103b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) { 104b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov uint32_t efState = 0; 105e867456982c1ee68e884294f5655abb6212ab533Mikhail Naganov mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState); 106b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) { 107b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov continue; // Nothing to do. 108b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 109a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (!mCommandMQ->read(&mStatus.replyTo)) { 110a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov continue; // Nothing to do. 111a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov } 112a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov switch (mStatus.replyTo) { 113a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov case IStreamOut::WriteCommand::WRITE: 114a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov doWrite(); 115a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov break; 116a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov case IStreamOut::WriteCommand::GET_PRESENTATION_POSITION: 117a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov doGetPresentationPosition(); 118a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov break; 119a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov case IStreamOut::WriteCommand::GET_LATENCY: 120a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov doGetLatency(); 121a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov break; 122a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov default: 123a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov ALOGE("Unknown write thread command code %d", mStatus.replyTo); 124a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.retval = Result::NOT_SUPPORTED; 125a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov break; 126b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 127a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (!mStatusMQ->write(&mStatus)) { 128a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov ALOGE("status message queue write failed"); 129b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 130b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)); 131b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 132b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 133b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return false; 134b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov} 135b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 136b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov} // namespace 137b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 138936279e1ffe6bf7e842c46f9a94d98a48dce6754Mikhail NaganovStreamOut::StreamOut(const sp<Device>& device, audio_stream_out_t* stream) 139b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov : mIsClosed(false), mDevice(device), mStream(stream), 1407deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent mStreamCommon(new Stream(&stream->common)), 141b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStreamMmap(new StreamMmap<audio_stream_out_t>(stream)), 142b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mEfGroup(nullptr), mStopWriteThread(false) { 14310548295023bee99108e418499aff09fe578211eMikhail Naganov} 14410548295023bee99108e418499aff09fe578211eMikhail Naganov 14510548295023bee99108e418499aff09fe578211eMikhail NaganovStreamOut::~StreamOut() { 146b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov ATRACE_CALL(); 147b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov close(); 148b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov if (mWriteThread.get()) { 149b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov ATRACE_NAME("mWriteThread->join"); 150b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov status_t status = mWriteThread->join(); 151b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov ALOGE_IF(status, "write thread exit error: %s", strerror(-status)); 152b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov } 153b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov if (mEfGroup) { 154b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov status_t status = EventFlag::deleteEventFlag(&mEfGroup); 155b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status)); 156b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov } 157b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov mCallback.clear(); 158936279e1ffe6bf7e842c46f9a94d98a48dce6754Mikhail Naganov mDevice->closeOutputStream(mStream); 15910548295023bee99108e418499aff09fe578211eMikhail Naganov mStream = nullptr; 16010548295023bee99108e418499aff09fe578211eMikhail Naganov} 16110548295023bee99108e418499aff09fe578211eMikhail Naganov 16210548295023bee99108e418499aff09fe578211eMikhail Naganov// Methods from ::android::hardware::audio::V2_0::IStream follow. 16310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint64_t> StreamOut::getFrameSize() { 16410548295023bee99108e418499aff09fe578211eMikhail Naganov return audio_stream_out_frame_size(mStream); 16510548295023bee99108e418499aff09fe578211eMikhail Naganov} 16610548295023bee99108e418499aff09fe578211eMikhail Naganov 16710548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint64_t> StreamOut::getFrameCount() { 16810548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getFrameCount(); 16910548295023bee99108e418499aff09fe578211eMikhail Naganov} 17010548295023bee99108e418499aff09fe578211eMikhail Naganov 17110548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint64_t> StreamOut::getBufferSize() { 17210548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getBufferSize(); 17310548295023bee99108e418499aff09fe578211eMikhail Naganov} 17410548295023bee99108e418499aff09fe578211eMikhail Naganov 17510548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint32_t> StreamOut::getSampleRate() { 17610548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getSampleRate(); 17710548295023bee99108e418499aff09fe578211eMikhail Naganov} 17810548295023bee99108e418499aff09fe578211eMikhail Naganov 17910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) { 18010548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getSupportedSampleRates(_hidl_cb); 18110548295023bee99108e418499aff09fe578211eMikhail Naganov} 18210548295023bee99108e418499aff09fe578211eMikhail Naganov 18310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setSampleRate(uint32_t sampleRateHz) { 18410548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setSampleRate(sampleRateHz); 18510548295023bee99108e418499aff09fe578211eMikhail Naganov} 18610548295023bee99108e418499aff09fe578211eMikhail Naganov 18710548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<AudioChannelMask> StreamOut::getChannelMask() { 18810548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getChannelMask(); 18910548295023bee99108e418499aff09fe578211eMikhail Naganov} 19010548295023bee99108e418499aff09fe578211eMikhail Naganov 19110548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { 19210548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getSupportedChannelMasks(_hidl_cb); 19310548295023bee99108e418499aff09fe578211eMikhail Naganov} 19410548295023bee99108e418499aff09fe578211eMikhail Naganov 19510548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setChannelMask(AudioChannelMask mask) { 19610548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setChannelMask(mask); 19710548295023bee99108e418499aff09fe578211eMikhail Naganov} 19810548295023bee99108e418499aff09fe578211eMikhail Naganov 19910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<AudioFormat> StreamOut::getFormat() { 20010548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getFormat(); 20110548295023bee99108e418499aff09fe578211eMikhail Naganov} 20210548295023bee99108e418499aff09fe578211eMikhail Naganov 20310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getSupportedFormats(getSupportedFormats_cb _hidl_cb) { 20410548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getSupportedFormats(_hidl_cb); 20510548295023bee99108e418499aff09fe578211eMikhail Naganov} 20610548295023bee99108e418499aff09fe578211eMikhail Naganov 20710548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setFormat(AudioFormat format) { 20810548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setFormat(format); 20910548295023bee99108e418499aff09fe578211eMikhail Naganov} 21010548295023bee99108e418499aff09fe578211eMikhail Naganov 21110548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getAudioProperties(getAudioProperties_cb _hidl_cb) { 21210548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getAudioProperties(_hidl_cb); 21310548295023bee99108e418499aff09fe578211eMikhail Naganov} 21410548295023bee99108e418499aff09fe578211eMikhail Naganov 21510548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::addEffect(uint64_t effectId) { 21610548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->addEffect(effectId); 21710548295023bee99108e418499aff09fe578211eMikhail Naganov} 21810548295023bee99108e418499aff09fe578211eMikhail Naganov 21910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::removeEffect(uint64_t effectId) { 22010548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->removeEffect(effectId); 22110548295023bee99108e418499aff09fe578211eMikhail Naganov} 22210548295023bee99108e418499aff09fe578211eMikhail Naganov 22310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::standby() { 22410548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->standby(); 22510548295023bee99108e418499aff09fe578211eMikhail Naganov} 22610548295023bee99108e418499aff09fe578211eMikhail Naganov 22710548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<AudioDevice> StreamOut::getDevice() { 22810548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getDevice(); 22910548295023bee99108e418499aff09fe578211eMikhail Naganov} 23010548295023bee99108e418499aff09fe578211eMikhail Naganov 23110548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setDevice(const DeviceAddress& address) { 23210548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setDevice(address); 23310548295023bee99108e418499aff09fe578211eMikhail Naganov} 23410548295023bee99108e418499aff09fe578211eMikhail Naganov 23510548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setConnectedState(const DeviceAddress& address, bool connected) { 23610548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setConnectedState(address, connected); 23710548295023bee99108e418499aff09fe578211eMikhail Naganov} 23810548295023bee99108e418499aff09fe578211eMikhail Naganov 23910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setHwAvSync(uint32_t hwAvSync) { 24010548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setHwAvSync(hwAvSync); 24110548295023bee99108e418499aff09fe578211eMikhail Naganov} 24210548295023bee99108e418499aff09fe578211eMikhail Naganov 24310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getParameters( 24410548295023bee99108e418499aff09fe578211eMikhail Naganov const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) { 24510548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getParameters(keys, _hidl_cb); 24610548295023bee99108e418499aff09fe578211eMikhail Naganov} 24710548295023bee99108e418499aff09fe578211eMikhail Naganov 24810548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setParameters(const hidl_vec<ParameterValue>& parameters) { 24910548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setParameters(parameters); 25010548295023bee99108e418499aff09fe578211eMikhail Naganov} 25110548295023bee99108e418499aff09fe578211eMikhail Naganov 25270b9a15df00a42b319279d903bf5923564920e3bMartijn CoenenReturn<void> StreamOut::debugDump(const hidl_handle& fd) { 25310548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->debugDump(fd); 25410548295023bee99108e418499aff09fe578211eMikhail Naganov} 25510548295023bee99108e418499aff09fe578211eMikhail Naganov 256b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail NaganovReturn<Result> StreamOut::close() { 257b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (mIsClosed) return Result::INVALID_STATE; 258b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mIsClosed = true; 259b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (mWriteThread.get()) { 260b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStopWriteThread.store(true, std::memory_order_release); 261b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 262b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (mEfGroup) { 263b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)); 264b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 265b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Result::OK; 266b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov} 267b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 26810548295023bee99108e418499aff09fe578211eMikhail Naganov// Methods from ::android::hardware::audio::V2_0::IStreamOut follow. 26910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint32_t> StreamOut::getLatency() { 27010548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->get_latency(mStream); 27110548295023bee99108e418499aff09fe578211eMikhail Naganov} 27210548295023bee99108e418499aff09fe578211eMikhail Naganov 27310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setVolume(float left, float right) { 27410548295023bee99108e418499aff09fe578211eMikhail Naganov Result retval(Result::NOT_SUPPORTED); 27510548295023bee99108e418499aff09fe578211eMikhail Naganov if (mStream->set_volume != NULL) { 2767deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent retval = Stream::analyzeStatus( 27710548295023bee99108e418499aff09fe578211eMikhail Naganov "set_volume", mStream->set_volume(mStream, left, right)); 27810548295023bee99108e418499aff09fe578211eMikhail Naganov } 27910548295023bee99108e418499aff09fe578211eMikhail Naganov return retval; 28010548295023bee99108e418499aff09fe578211eMikhail Naganov} 28110548295023bee99108e418499aff09fe578211eMikhail Naganov 282b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail NaganovReturn<void> StreamOut::prepareForWriting( 283a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov uint32_t frameSize, uint32_t framesCount, prepareForWriting_cb _hidl_cb) { 284b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov status_t status; 285a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov ThreadInfo threadInfo = { 0, 0 }; 286b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // Create message queues. 287b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (mDataMQ) { 288b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGE("the client attempts to call prepareForWriting twice"); 289b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov _hidl_cb(Result::INVALID_STATE, 290a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 291b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Void(); 292b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 293a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1)); 294b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov std::unique_ptr<DataMQ> tempDataMQ( 295b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov new DataMQ(frameSize * framesCount, true /* EventFlag */)); 296b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1)); 297a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) { 298a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid"); 299b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid"); 300b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid"); 301b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov _hidl_cb(Result::INVALID_ARGUMENTS, 302a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 303b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Void(); 304b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 305b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup); 306b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (status != OK || !mEfGroup) { 307b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGE("failed creating event flag for data MQ: %s", strerror(-status)); 308b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov _hidl_cb(Result::INVALID_ARGUMENTS, 309a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 310b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Void(); 311b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 312b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 313b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // Create and launch the thread. 314b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mWriteThread = new WriteThread( 315b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov &mStopWriteThread, 316b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStream, 317a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov tempCommandMQ.get(), 318b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov tempDataMQ.get(), 319b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov tempStatusMQ.get(), 320a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov mEfGroup); 321b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov status = mWriteThread->run("writer", PRIORITY_URGENT_AUDIO); 322b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (status != OK) { 323b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGW("failed to start writer thread: %s", strerror(-status)); 324b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov _hidl_cb(Result::INVALID_ARGUMENTS, 325a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 326b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Void(); 32710548295023bee99108e418499aff09fe578211eMikhail Naganov } 328b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 329a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mCommandMQ = std::move(tempCommandMQ); 330b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mDataMQ = std::move(tempDataMQ); 331b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStatusMQ = std::move(tempStatusMQ); 332a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov threadInfo.pid = getpid(); 333a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov threadInfo.tid = mWriteThread->getTid(); 334a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov _hidl_cb(Result::OK, 335a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(), 336a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov threadInfo); 33710548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 33810548295023bee99108e418499aff09fe578211eMikhail Naganov} 33910548295023bee99108e418499aff09fe578211eMikhail Naganov 34010548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb) { 34110548295023bee99108e418499aff09fe578211eMikhail Naganov uint32_t halDspFrames; 3427deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Result retval = Stream::analyzeStatus( 34310548295023bee99108e418499aff09fe578211eMikhail Naganov "get_render_position", mStream->get_render_position(mStream, &halDspFrames)); 34410548295023bee99108e418499aff09fe578211eMikhail Naganov _hidl_cb(retval, halDspFrames); 34510548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 34610548295023bee99108e418499aff09fe578211eMikhail Naganov} 34710548295023bee99108e418499aff09fe578211eMikhail Naganov 34810548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb) { 34910548295023bee99108e418499aff09fe578211eMikhail Naganov Result retval(Result::NOT_SUPPORTED); 35010548295023bee99108e418499aff09fe578211eMikhail Naganov int64_t timestampUs = 0; 35110548295023bee99108e418499aff09fe578211eMikhail Naganov if (mStream->get_next_write_timestamp != NULL) { 3527deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent retval = Stream::analyzeStatus( 35310548295023bee99108e418499aff09fe578211eMikhail Naganov "get_next_write_timestamp", 35410548295023bee99108e418499aff09fe578211eMikhail Naganov mStream->get_next_write_timestamp(mStream, ×tampUs)); 35510548295023bee99108e418499aff09fe578211eMikhail Naganov } 35610548295023bee99108e418499aff09fe578211eMikhail Naganov _hidl_cb(retval, timestampUs); 35710548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 35810548295023bee99108e418499aff09fe578211eMikhail Naganov} 35910548295023bee99108e418499aff09fe578211eMikhail Naganov 36010548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setCallback(const sp<IStreamOutCallback>& callback) { 36110548295023bee99108e418499aff09fe578211eMikhail Naganov if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED; 36210548295023bee99108e418499aff09fe578211eMikhail Naganov int result = mStream->set_callback(mStream, StreamOut::asyncCallback, this); 36310548295023bee99108e418499aff09fe578211eMikhail Naganov if (result == 0) { 36410548295023bee99108e418499aff09fe578211eMikhail Naganov mCallback = callback; 36510548295023bee99108e418499aff09fe578211eMikhail Naganov } 3667deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return Stream::analyzeStatus("set_callback", result); 36710548295023bee99108e418499aff09fe578211eMikhail Naganov} 36810548295023bee99108e418499aff09fe578211eMikhail Naganov 3696e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail NaganovReturn<Result> StreamOut::clearCallback() { 3706e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED; 3716e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov mCallback.clear(); 3726e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov return Result::OK; 3736e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov} 3746e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov 37510548295023bee99108e418499aff09fe578211eMikhail Naganov// static 37610548295023bee99108e418499aff09fe578211eMikhail Naganovint StreamOut::asyncCallback(stream_callback_event_t event, void*, void *cookie) { 37710548295023bee99108e418499aff09fe578211eMikhail Naganov wp<StreamOut> weakSelf(reinterpret_cast<StreamOut*>(cookie)); 37810548295023bee99108e418499aff09fe578211eMikhail Naganov sp<StreamOut> self = weakSelf.promote(); 3796e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov if (self == nullptr || self->mCallback == nullptr) return 0; 38010548295023bee99108e418499aff09fe578211eMikhail Naganov ALOGV("asyncCallback() event %d", event); 38110548295023bee99108e418499aff09fe578211eMikhail Naganov switch (event) { 38210548295023bee99108e418499aff09fe578211eMikhail Naganov case STREAM_CBK_EVENT_WRITE_READY: 3836e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov self->mCallback->onWriteReady(); 38410548295023bee99108e418499aff09fe578211eMikhail Naganov break; 38510548295023bee99108e418499aff09fe578211eMikhail Naganov case STREAM_CBK_EVENT_DRAIN_READY: 3866e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov self->mCallback->onDrainReady(); 38710548295023bee99108e418499aff09fe578211eMikhail Naganov break; 38810548295023bee99108e418499aff09fe578211eMikhail Naganov case STREAM_CBK_EVENT_ERROR: 3896e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov self->mCallback->onError(); 39010548295023bee99108e418499aff09fe578211eMikhail Naganov break; 39110548295023bee99108e418499aff09fe578211eMikhail Naganov default: 39210548295023bee99108e418499aff09fe578211eMikhail Naganov ALOGW("asyncCallback() unknown event %d", event); 39310548295023bee99108e418499aff09fe578211eMikhail Naganov break; 39410548295023bee99108e418499aff09fe578211eMikhail Naganov } 39510548295023bee99108e418499aff09fe578211eMikhail Naganov return 0; 39610548295023bee99108e418499aff09fe578211eMikhail Naganov} 39710548295023bee99108e418499aff09fe578211eMikhail Naganov 39810548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb) { 39910548295023bee99108e418499aff09fe578211eMikhail Naganov _hidl_cb(mStream->pause != NULL, mStream->resume != NULL); 40010548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 40110548295023bee99108e418499aff09fe578211eMikhail Naganov} 40210548295023bee99108e418499aff09fe578211eMikhail Naganov 40310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::pause() { 40410548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->pause != NULL ? 4057deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Stream::analyzeStatus("pause", mStream->pause(mStream)) : 40610548295023bee99108e418499aff09fe578211eMikhail Naganov Result::NOT_SUPPORTED; 40710548295023bee99108e418499aff09fe578211eMikhail Naganov} 40810548295023bee99108e418499aff09fe578211eMikhail Naganov 40910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::resume() { 41010548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->resume != NULL ? 4117deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Stream::analyzeStatus("resume", mStream->resume(mStream)) : 41210548295023bee99108e418499aff09fe578211eMikhail Naganov Result::NOT_SUPPORTED; 41310548295023bee99108e418499aff09fe578211eMikhail Naganov} 41410548295023bee99108e418499aff09fe578211eMikhail Naganov 41510548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<bool> StreamOut::supportsDrain() { 41610548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->drain != NULL; 41710548295023bee99108e418499aff09fe578211eMikhail Naganov} 41810548295023bee99108e418499aff09fe578211eMikhail Naganov 41910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::drain(AudioDrain type) { 42010548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->drain != NULL ? 4217deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Stream::analyzeStatus( 42210548295023bee99108e418499aff09fe578211eMikhail Naganov "drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type))) : 42310548295023bee99108e418499aff09fe578211eMikhail Naganov Result::NOT_SUPPORTED; 42410548295023bee99108e418499aff09fe578211eMikhail Naganov} 42510548295023bee99108e418499aff09fe578211eMikhail Naganov 42610548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::flush() { 42710548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->flush != NULL ? 4287deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Stream::analyzeStatus("flush", mStream->flush(mStream)) : 42910548295023bee99108e418499aff09fe578211eMikhail Naganov Result::NOT_SUPPORTED; 43010548295023bee99108e418499aff09fe578211eMikhail Naganov} 43110548295023bee99108e418499aff09fe578211eMikhail Naganov 432ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov// static 433ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail NaganovResult StreamOut::getPresentationPositionImpl( 434ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov audio_stream_out_t *stream, uint64_t *frames, TimeSpec *timeStamp) { 43510548295023bee99108e418499aff09fe578211eMikhail Naganov Result retval(Result::NOT_SUPPORTED); 436ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov if (stream->get_presentation_position == NULL) return retval; 437ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov struct timespec halTimeStamp; 438ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov retval = Stream::analyzeStatus( 439ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov "get_presentation_position", 440ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov stream->get_presentation_position(stream, frames, &halTimeStamp), 441ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov // Don't logspam on EINVAL--it's normal for get_presentation_position 442d63e79022a1c244617d6aab7806788570373016aMikhail Naganov // to return it sometimes. EAGAIN may be returned by A2DP audio HAL 443d63e79022a1c244617d6aab7806788570373016aMikhail Naganov // implementation. 444d63e79022a1c244617d6aab7806788570373016aMikhail Naganov EINVAL, EAGAIN); 445ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov if (retval == Result::OK) { 446ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov timeStamp->tvSec = halTimeStamp.tv_sec; 447ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov timeStamp->tvNSec = halTimeStamp.tv_nsec; 448ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov } 449ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov return retval; 450ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov} 451ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov 452ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail NaganovReturn<void> StreamOut::getPresentationPosition(getPresentationPosition_cb _hidl_cb) { 45310548295023bee99108e418499aff09fe578211eMikhail Naganov uint64_t frames = 0; 45410548295023bee99108e418499aff09fe578211eMikhail Naganov TimeSpec timeStamp = { 0, 0 }; 455ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov Result retval = getPresentationPositionImpl(mStream, &frames, &timeStamp); 45610548295023bee99108e418499aff09fe578211eMikhail Naganov _hidl_cb(retval, frames, timeStamp); 45710548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 45810548295023bee99108e418499aff09fe578211eMikhail Naganov} 45910548295023bee99108e418499aff09fe578211eMikhail Naganov 4607deb7dad39e58b6e5de812075950adc27cd51d95Eric LaurentReturn<Result> StreamOut::start() { 4617deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return mStreamMmap->start(); 4627deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent} 4637deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent 4647deb7dad39e58b6e5de812075950adc27cd51d95Eric LaurentReturn<Result> StreamOut::stop() { 4657deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return mStreamMmap->stop(); 4667deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent} 4677deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent 4687deb7dad39e58b6e5de812075950adc27cd51d95Eric LaurentReturn<void> StreamOut::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) { 4697deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return mStreamMmap->createMmapBuffer( 4707deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent minSizeFrames, audio_stream_out_frame_size(mStream), _hidl_cb); 4717deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent} 4727deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent 4737deb7dad39e58b6e5de812075950adc27cd51d95Eric LaurentReturn<void> StreamOut::getMmapPosition(getMmapPosition_cb _hidl_cb) { 4747deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return mStreamMmap->getMmapPosition(_hidl_cb); 4757deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent} 4767deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent 47710548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace implementation 47810548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace V2_0 47910548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace audio 48010548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace hardware 48110548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace android 482