StreamOut.impl.h revision a1db22a3e5b45b3bd3c2edf84c605ce211c89220
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 // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422 105b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov uint32_t efState = 0; 106b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mEfGroup->wait( 107b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState, NS_PER_SEC); 108b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) { 109b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov continue; // Nothing to do. 110b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 111a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (!mCommandMQ->read(&mStatus.replyTo)) { 112a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov continue; // Nothing to do. 113a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov } 114a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov switch (mStatus.replyTo) { 115a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov case IStreamOut::WriteCommand::WRITE: 116a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov doWrite(); 117a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov break; 118a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov case IStreamOut::WriteCommand::GET_PRESENTATION_POSITION: 119a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov doGetPresentationPosition(); 120a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov break; 121a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov case IStreamOut::WriteCommand::GET_LATENCY: 122a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov doGetLatency(); 123a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov break; 124a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov default: 125a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov ALOGE("Unknown write thread command code %d", mStatus.replyTo); 126a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mStatus.retval = Result::NOT_SUPPORTED; 127a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov break; 128b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 129a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (!mStatusMQ->write(&mStatus)) { 130a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov ALOGE("status message queue write failed"); 131b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 132b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)); 133b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 134b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 135b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return false; 136b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov} 137b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 138b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov} // namespace 139b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 14010548295023bee99108e418499aff09fe578211eMikhail NaganovStreamOut::StreamOut(audio_hw_device_t* device, audio_stream_out_t* stream) 141b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov : mIsClosed(false), mDevice(device), mStream(stream), 1427deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent mStreamCommon(new Stream(&stream->common)), 143b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStreamMmap(new StreamMmap<audio_stream_out_t>(stream)), 144b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mEfGroup(nullptr), mStopWriteThread(false) { 14510548295023bee99108e418499aff09fe578211eMikhail Naganov} 14610548295023bee99108e418499aff09fe578211eMikhail Naganov 14710548295023bee99108e418499aff09fe578211eMikhail NaganovStreamOut::~StreamOut() { 148b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov ATRACE_CALL(); 149b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov close(); 150b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov if (mWriteThread.get()) { 151b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov ATRACE_NAME("mWriteThread->join"); 152b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov status_t status = mWriteThread->join(); 153b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov ALOGE_IF(status, "write thread exit error: %s", strerror(-status)); 154b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov } 155b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov if (mEfGroup) { 156b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov status_t status = EventFlag::deleteEventFlag(&mEfGroup); 157b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status)); 158b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov } 159b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov mCallback.clear(); 160b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov mDevice->close_output_stream(mDevice, mStream); 16110548295023bee99108e418499aff09fe578211eMikhail Naganov mStream = nullptr; 16210548295023bee99108e418499aff09fe578211eMikhail Naganov mDevice = nullptr; 16310548295023bee99108e418499aff09fe578211eMikhail Naganov} 16410548295023bee99108e418499aff09fe578211eMikhail Naganov 16510548295023bee99108e418499aff09fe578211eMikhail Naganov// Methods from ::android::hardware::audio::V2_0::IStream follow. 16610548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint64_t> StreamOut::getFrameSize() { 16710548295023bee99108e418499aff09fe578211eMikhail Naganov return audio_stream_out_frame_size(mStream); 16810548295023bee99108e418499aff09fe578211eMikhail Naganov} 16910548295023bee99108e418499aff09fe578211eMikhail Naganov 17010548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint64_t> StreamOut::getFrameCount() { 17110548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getFrameCount(); 17210548295023bee99108e418499aff09fe578211eMikhail Naganov} 17310548295023bee99108e418499aff09fe578211eMikhail Naganov 17410548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint64_t> StreamOut::getBufferSize() { 17510548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getBufferSize(); 17610548295023bee99108e418499aff09fe578211eMikhail Naganov} 17710548295023bee99108e418499aff09fe578211eMikhail Naganov 17810548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint32_t> StreamOut::getSampleRate() { 17910548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getSampleRate(); 18010548295023bee99108e418499aff09fe578211eMikhail Naganov} 18110548295023bee99108e418499aff09fe578211eMikhail Naganov 18210548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) { 18310548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getSupportedSampleRates(_hidl_cb); 18410548295023bee99108e418499aff09fe578211eMikhail Naganov} 18510548295023bee99108e418499aff09fe578211eMikhail Naganov 18610548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setSampleRate(uint32_t sampleRateHz) { 18710548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setSampleRate(sampleRateHz); 18810548295023bee99108e418499aff09fe578211eMikhail Naganov} 18910548295023bee99108e418499aff09fe578211eMikhail Naganov 19010548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<AudioChannelMask> StreamOut::getChannelMask() { 19110548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getChannelMask(); 19210548295023bee99108e418499aff09fe578211eMikhail Naganov} 19310548295023bee99108e418499aff09fe578211eMikhail Naganov 19410548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) { 19510548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getSupportedChannelMasks(_hidl_cb); 19610548295023bee99108e418499aff09fe578211eMikhail Naganov} 19710548295023bee99108e418499aff09fe578211eMikhail Naganov 19810548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setChannelMask(AudioChannelMask mask) { 19910548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setChannelMask(mask); 20010548295023bee99108e418499aff09fe578211eMikhail Naganov} 20110548295023bee99108e418499aff09fe578211eMikhail Naganov 20210548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<AudioFormat> StreamOut::getFormat() { 20310548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getFormat(); 20410548295023bee99108e418499aff09fe578211eMikhail Naganov} 20510548295023bee99108e418499aff09fe578211eMikhail Naganov 20610548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getSupportedFormats(getSupportedFormats_cb _hidl_cb) { 20710548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getSupportedFormats(_hidl_cb); 20810548295023bee99108e418499aff09fe578211eMikhail Naganov} 20910548295023bee99108e418499aff09fe578211eMikhail Naganov 21010548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setFormat(AudioFormat format) { 21110548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setFormat(format); 21210548295023bee99108e418499aff09fe578211eMikhail Naganov} 21310548295023bee99108e418499aff09fe578211eMikhail Naganov 21410548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getAudioProperties(getAudioProperties_cb _hidl_cb) { 21510548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getAudioProperties(_hidl_cb); 21610548295023bee99108e418499aff09fe578211eMikhail Naganov} 21710548295023bee99108e418499aff09fe578211eMikhail Naganov 21810548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::addEffect(uint64_t effectId) { 21910548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->addEffect(effectId); 22010548295023bee99108e418499aff09fe578211eMikhail Naganov} 22110548295023bee99108e418499aff09fe578211eMikhail Naganov 22210548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::removeEffect(uint64_t effectId) { 22310548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->removeEffect(effectId); 22410548295023bee99108e418499aff09fe578211eMikhail Naganov} 22510548295023bee99108e418499aff09fe578211eMikhail Naganov 22610548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::standby() { 22710548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->standby(); 22810548295023bee99108e418499aff09fe578211eMikhail Naganov} 22910548295023bee99108e418499aff09fe578211eMikhail Naganov 23010548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<AudioDevice> StreamOut::getDevice() { 23110548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getDevice(); 23210548295023bee99108e418499aff09fe578211eMikhail Naganov} 23310548295023bee99108e418499aff09fe578211eMikhail Naganov 23410548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setDevice(const DeviceAddress& address) { 23510548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setDevice(address); 23610548295023bee99108e418499aff09fe578211eMikhail Naganov} 23710548295023bee99108e418499aff09fe578211eMikhail Naganov 23810548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setConnectedState(const DeviceAddress& address, bool connected) { 23910548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setConnectedState(address, connected); 24010548295023bee99108e418499aff09fe578211eMikhail Naganov} 24110548295023bee99108e418499aff09fe578211eMikhail Naganov 24210548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setHwAvSync(uint32_t hwAvSync) { 24310548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setHwAvSync(hwAvSync); 24410548295023bee99108e418499aff09fe578211eMikhail Naganov} 24510548295023bee99108e418499aff09fe578211eMikhail Naganov 24610548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getParameters( 24710548295023bee99108e418499aff09fe578211eMikhail Naganov const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) { 24810548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->getParameters(keys, _hidl_cb); 24910548295023bee99108e418499aff09fe578211eMikhail Naganov} 25010548295023bee99108e418499aff09fe578211eMikhail Naganov 25110548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setParameters(const hidl_vec<ParameterValue>& parameters) { 25210548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->setParameters(parameters); 25310548295023bee99108e418499aff09fe578211eMikhail Naganov} 25410548295023bee99108e418499aff09fe578211eMikhail Naganov 25570b9a15df00a42b319279d903bf5923564920e3bMartijn CoenenReturn<void> StreamOut::debugDump(const hidl_handle& fd) { 25610548295023bee99108e418499aff09fe578211eMikhail Naganov return mStreamCommon->debugDump(fd); 25710548295023bee99108e418499aff09fe578211eMikhail Naganov} 25810548295023bee99108e418499aff09fe578211eMikhail Naganov 259b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail NaganovReturn<Result> StreamOut::close() { 260b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (mIsClosed) return Result::INVALID_STATE; 261b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mIsClosed = true; 262b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (mWriteThread.get()) { 263b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStopWriteThread.store(true, std::memory_order_release); 264b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 265b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (mEfGroup) { 266b0abafbf0a6174e8c8933cc5fb19501a2d22c53bMikhail Naganov mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)); 267b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 268b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Result::OK; 269b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov} 270b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 27110548295023bee99108e418499aff09fe578211eMikhail Naganov// Methods from ::android::hardware::audio::V2_0::IStreamOut follow. 27210548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<uint32_t> StreamOut::getLatency() { 27310548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->get_latency(mStream); 27410548295023bee99108e418499aff09fe578211eMikhail Naganov} 27510548295023bee99108e418499aff09fe578211eMikhail Naganov 27610548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setVolume(float left, float right) { 27710548295023bee99108e418499aff09fe578211eMikhail Naganov Result retval(Result::NOT_SUPPORTED); 27810548295023bee99108e418499aff09fe578211eMikhail Naganov if (mStream->set_volume != NULL) { 2797deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent retval = Stream::analyzeStatus( 28010548295023bee99108e418499aff09fe578211eMikhail Naganov "set_volume", mStream->set_volume(mStream, left, right)); 28110548295023bee99108e418499aff09fe578211eMikhail Naganov } 28210548295023bee99108e418499aff09fe578211eMikhail Naganov return retval; 28310548295023bee99108e418499aff09fe578211eMikhail Naganov} 28410548295023bee99108e418499aff09fe578211eMikhail Naganov 285b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail NaganovReturn<void> StreamOut::prepareForWriting( 286a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov uint32_t frameSize, uint32_t framesCount, prepareForWriting_cb _hidl_cb) { 287b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov status_t status; 288a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov ThreadInfo threadInfo = { 0, 0 }; 289b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // Create message queues. 290b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (mDataMQ) { 291b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGE("the client attempts to call prepareForWriting twice"); 292b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov _hidl_cb(Result::INVALID_STATE, 293a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 294b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Void(); 295b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 296a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1)); 297b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov std::unique_ptr<DataMQ> tempDataMQ( 298b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov new DataMQ(frameSize * framesCount, true /* EventFlag */)); 299b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1)); 300a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) { 301a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid"); 302b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid"); 303b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid"); 304b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov _hidl_cb(Result::INVALID_ARGUMENTS, 305a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 306b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Void(); 307b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 308b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // TODO: Remove event flag management once blocking MQ is implemented. b/33815422 309b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup); 310b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (status != OK || !mEfGroup) { 311b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGE("failed creating event flag for data MQ: %s", strerror(-status)); 312b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov _hidl_cb(Result::INVALID_ARGUMENTS, 313a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 314b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Void(); 315b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov } 316b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 317b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov // Create and launch the thread. 318b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mWriteThread = new WriteThread( 319b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov &mStopWriteThread, 320b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStream, 321a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov tempCommandMQ.get(), 322b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov tempDataMQ.get(), 323b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov tempStatusMQ.get(), 324a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov mEfGroup); 325b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov status = mWriteThread->run("writer", PRIORITY_URGENT_AUDIO); 326b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov if (status != OK) { 327b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov ALOGW("failed to start writer thread: %s", strerror(-status)); 328b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov _hidl_cb(Result::INVALID_ARGUMENTS, 329a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo); 330b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov return Void(); 33110548295023bee99108e418499aff09fe578211eMikhail Naganov } 332b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov 333a468fa84d13b085b1808f20f70d22ed9dbe3f3ebMikhail Naganov mCommandMQ = std::move(tempCommandMQ); 334b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mDataMQ = std::move(tempDataMQ); 335b29438ef70549a331d11c0384c53cf1dc6e7f0beMikhail Naganov mStatusMQ = std::move(tempStatusMQ); 336a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov threadInfo.pid = getpid(); 337a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov threadInfo.tid = mWriteThread->getTid(); 338a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov _hidl_cb(Result::OK, 339a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(), 340a1db22a3e5b45b3bd3c2edf84c605ce211c89220Mikhail Naganov threadInfo); 34110548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 34210548295023bee99108e418499aff09fe578211eMikhail Naganov} 34310548295023bee99108e418499aff09fe578211eMikhail Naganov 34410548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb) { 34510548295023bee99108e418499aff09fe578211eMikhail Naganov uint32_t halDspFrames; 3467deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Result retval = Stream::analyzeStatus( 34710548295023bee99108e418499aff09fe578211eMikhail Naganov "get_render_position", mStream->get_render_position(mStream, &halDspFrames)); 34810548295023bee99108e418499aff09fe578211eMikhail Naganov _hidl_cb(retval, halDspFrames); 34910548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 35010548295023bee99108e418499aff09fe578211eMikhail Naganov} 35110548295023bee99108e418499aff09fe578211eMikhail Naganov 35210548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb) { 35310548295023bee99108e418499aff09fe578211eMikhail Naganov Result retval(Result::NOT_SUPPORTED); 35410548295023bee99108e418499aff09fe578211eMikhail Naganov int64_t timestampUs = 0; 35510548295023bee99108e418499aff09fe578211eMikhail Naganov if (mStream->get_next_write_timestamp != NULL) { 3567deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent retval = Stream::analyzeStatus( 35710548295023bee99108e418499aff09fe578211eMikhail Naganov "get_next_write_timestamp", 35810548295023bee99108e418499aff09fe578211eMikhail Naganov mStream->get_next_write_timestamp(mStream, ×tampUs)); 35910548295023bee99108e418499aff09fe578211eMikhail Naganov } 36010548295023bee99108e418499aff09fe578211eMikhail Naganov _hidl_cb(retval, timestampUs); 36110548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 36210548295023bee99108e418499aff09fe578211eMikhail Naganov} 36310548295023bee99108e418499aff09fe578211eMikhail Naganov 36410548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::setCallback(const sp<IStreamOutCallback>& callback) { 36510548295023bee99108e418499aff09fe578211eMikhail Naganov if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED; 36610548295023bee99108e418499aff09fe578211eMikhail Naganov int result = mStream->set_callback(mStream, StreamOut::asyncCallback, this); 36710548295023bee99108e418499aff09fe578211eMikhail Naganov if (result == 0) { 36810548295023bee99108e418499aff09fe578211eMikhail Naganov mCallback = callback; 36910548295023bee99108e418499aff09fe578211eMikhail Naganov } 3707deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return Stream::analyzeStatus("set_callback", result); 37110548295023bee99108e418499aff09fe578211eMikhail Naganov} 37210548295023bee99108e418499aff09fe578211eMikhail Naganov 3736e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail NaganovReturn<Result> StreamOut::clearCallback() { 3746e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED; 3756e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov mCallback.clear(); 3766e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov return Result::OK; 3776e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov} 3786e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov 37910548295023bee99108e418499aff09fe578211eMikhail Naganov// static 38010548295023bee99108e418499aff09fe578211eMikhail Naganovint StreamOut::asyncCallback(stream_callback_event_t event, void*, void *cookie) { 38110548295023bee99108e418499aff09fe578211eMikhail Naganov wp<StreamOut> weakSelf(reinterpret_cast<StreamOut*>(cookie)); 38210548295023bee99108e418499aff09fe578211eMikhail Naganov sp<StreamOut> self = weakSelf.promote(); 3836e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov if (self == nullptr || self->mCallback == nullptr) return 0; 38410548295023bee99108e418499aff09fe578211eMikhail Naganov ALOGV("asyncCallback() event %d", event); 38510548295023bee99108e418499aff09fe578211eMikhail Naganov switch (event) { 38610548295023bee99108e418499aff09fe578211eMikhail Naganov case STREAM_CBK_EVENT_WRITE_READY: 3876e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov self->mCallback->onWriteReady(); 38810548295023bee99108e418499aff09fe578211eMikhail Naganov break; 38910548295023bee99108e418499aff09fe578211eMikhail Naganov case STREAM_CBK_EVENT_DRAIN_READY: 3906e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov self->mCallback->onDrainReady(); 39110548295023bee99108e418499aff09fe578211eMikhail Naganov break; 39210548295023bee99108e418499aff09fe578211eMikhail Naganov case STREAM_CBK_EVENT_ERROR: 3936e81e9bb3c13d8c51fde503cf8be2bfb56e1ca1dMikhail Naganov self->mCallback->onError(); 39410548295023bee99108e418499aff09fe578211eMikhail Naganov break; 39510548295023bee99108e418499aff09fe578211eMikhail Naganov default: 39610548295023bee99108e418499aff09fe578211eMikhail Naganov ALOGW("asyncCallback() unknown event %d", event); 39710548295023bee99108e418499aff09fe578211eMikhail Naganov break; 39810548295023bee99108e418499aff09fe578211eMikhail Naganov } 39910548295023bee99108e418499aff09fe578211eMikhail Naganov return 0; 40010548295023bee99108e418499aff09fe578211eMikhail Naganov} 40110548295023bee99108e418499aff09fe578211eMikhail Naganov 40210548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<void> StreamOut::supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb) { 40310548295023bee99108e418499aff09fe578211eMikhail Naganov _hidl_cb(mStream->pause != NULL, mStream->resume != NULL); 40410548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 40510548295023bee99108e418499aff09fe578211eMikhail Naganov} 40610548295023bee99108e418499aff09fe578211eMikhail Naganov 40710548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::pause() { 40810548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->pause != NULL ? 4097deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Stream::analyzeStatus("pause", mStream->pause(mStream)) : 41010548295023bee99108e418499aff09fe578211eMikhail Naganov Result::NOT_SUPPORTED; 41110548295023bee99108e418499aff09fe578211eMikhail Naganov} 41210548295023bee99108e418499aff09fe578211eMikhail Naganov 41310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::resume() { 41410548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->resume != NULL ? 4157deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Stream::analyzeStatus("resume", mStream->resume(mStream)) : 41610548295023bee99108e418499aff09fe578211eMikhail Naganov Result::NOT_SUPPORTED; 41710548295023bee99108e418499aff09fe578211eMikhail Naganov} 41810548295023bee99108e418499aff09fe578211eMikhail Naganov 41910548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<bool> StreamOut::supportsDrain() { 42010548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->drain != NULL; 42110548295023bee99108e418499aff09fe578211eMikhail Naganov} 42210548295023bee99108e418499aff09fe578211eMikhail Naganov 42310548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::drain(AudioDrain type) { 42410548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->drain != NULL ? 4257deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Stream::analyzeStatus( 42610548295023bee99108e418499aff09fe578211eMikhail Naganov "drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type))) : 42710548295023bee99108e418499aff09fe578211eMikhail Naganov Result::NOT_SUPPORTED; 42810548295023bee99108e418499aff09fe578211eMikhail Naganov} 42910548295023bee99108e418499aff09fe578211eMikhail Naganov 43010548295023bee99108e418499aff09fe578211eMikhail NaganovReturn<Result> StreamOut::flush() { 43110548295023bee99108e418499aff09fe578211eMikhail Naganov return mStream->flush != NULL ? 4327deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent Stream::analyzeStatus("flush", mStream->flush(mStream)) : 43310548295023bee99108e418499aff09fe578211eMikhail Naganov Result::NOT_SUPPORTED; 43410548295023bee99108e418499aff09fe578211eMikhail Naganov} 43510548295023bee99108e418499aff09fe578211eMikhail Naganov 436ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov// static 437ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail NaganovResult StreamOut::getPresentationPositionImpl( 438ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov audio_stream_out_t *stream, uint64_t *frames, TimeSpec *timeStamp) { 43910548295023bee99108e418499aff09fe578211eMikhail Naganov Result retval(Result::NOT_SUPPORTED); 440ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov if (stream->get_presentation_position == NULL) return retval; 441ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov struct timespec halTimeStamp; 442ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov retval = Stream::analyzeStatus( 443ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov "get_presentation_position", 444ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov stream->get_presentation_position(stream, frames, &halTimeStamp), 445ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov // Don't logspam on EINVAL--it's normal for get_presentation_position 446d63e79022a1c244617d6aab7806788570373016aMikhail Naganov // to return it sometimes. EAGAIN may be returned by A2DP audio HAL 447d63e79022a1c244617d6aab7806788570373016aMikhail Naganov // implementation. 448d63e79022a1c244617d6aab7806788570373016aMikhail Naganov EINVAL, EAGAIN); 449ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov if (retval == Result::OK) { 450ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov timeStamp->tvSec = halTimeStamp.tv_sec; 451ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov timeStamp->tvNSec = halTimeStamp.tv_nsec; 452ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov } 453ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov return retval; 454ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov} 455ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov 456ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail NaganovReturn<void> StreamOut::getPresentationPosition(getPresentationPosition_cb _hidl_cb) { 45710548295023bee99108e418499aff09fe578211eMikhail Naganov uint64_t frames = 0; 45810548295023bee99108e418499aff09fe578211eMikhail Naganov TimeSpec timeStamp = { 0, 0 }; 459ee901e3fd885709abc9b9e2b8e521022e27522d3Mikhail Naganov Result retval = getPresentationPositionImpl(mStream, &frames, &timeStamp); 46010548295023bee99108e418499aff09fe578211eMikhail Naganov _hidl_cb(retval, frames, timeStamp); 46110548295023bee99108e418499aff09fe578211eMikhail Naganov return Void(); 46210548295023bee99108e418499aff09fe578211eMikhail Naganov} 46310548295023bee99108e418499aff09fe578211eMikhail Naganov 4647deb7dad39e58b6e5de812075950adc27cd51d95Eric LaurentReturn<Result> StreamOut::start() { 4657deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return mStreamMmap->start(); 4667deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent} 4677deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent 4687deb7dad39e58b6e5de812075950adc27cd51d95Eric LaurentReturn<Result> StreamOut::stop() { 4697deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return mStreamMmap->stop(); 4707deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent} 4717deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent 4727deb7dad39e58b6e5de812075950adc27cd51d95Eric LaurentReturn<void> StreamOut::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) { 4737deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return mStreamMmap->createMmapBuffer( 4747deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent minSizeFrames, audio_stream_out_frame_size(mStream), _hidl_cb); 4757deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent} 4767deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent 4777deb7dad39e58b6e5de812075950adc27cd51d95Eric LaurentReturn<void> StreamOut::getMmapPosition(getMmapPosition_cb _hidl_cb) { 4787deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent return mStreamMmap->getMmapPosition(_hidl_cb); 4797deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent} 4807deb7dad39e58b6e5de812075950adc27cd51d95Eric Laurent 48110548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace implementation 48210548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace V2_0 48310548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace audio 48410548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace hardware 48510548295023bee99108e418499aff09fe578211eMikhail Naganov} // namespace android 486