diff options
-rw-r--r-- | audio/device_port_sink.cpp | 25 | ||||
-rw-r--r-- | audio/device_port_sink.h | 2 | ||||
-rw-r--r-- | audio/device_port_source.cpp | 71 | ||||
-rw-r--r-- | audio/stream_out.cpp | 34 | ||||
-rw-r--r-- | audio/talsa.cpp | 75 | ||||
-rw-r--r-- | audio/talsa.h | 5 | ||||
-rw-r--r-- | overlay/frameworks/base/core/res/res/values/config.xml | 3 |
7 files changed, 142 insertions, 73 deletions
diff --git a/audio/device_port_sink.cpp b/audio/device_port_sink.cpp index 12754ff4..3936805d 100644 --- a/audio/device_port_sink.cpp +++ b/audio/device_port_sink.cpp @@ -62,8 +62,12 @@ struct TinyalsaSink : public DevicePortSink { cfg.base.sampleRateHz, cfg.frameCount, true /* isOut */)) { - LOG_ALWAYS_FATAL_IF(::pcm_prepare(mPcm.get())); - mConsumeThread = std::thread(&TinyalsaSink::consumeThread, this); + if (mPcm) { + LOG_ALWAYS_FATAL_IF(!talsa::pcmPrepare(mPcm.get())); + mConsumeThread = std::thread(&TinyalsaSink::consumeThread, this); + } else { + mConsumeThread = std::thread([](){}); + } } ~TinyalsaSink() { @@ -71,14 +75,6 @@ struct TinyalsaSink : public DevicePortSink { mConsumeThread.join(); } - Result start() override { - return ::pcm_start(mPcm.get()) ? FAILURE(Result::INVALID_STATE) : Result::OK; - } - - Result stop() override { - return ::pcm_stop(mPcm.get()) ? FAILURE(Result::INVALID_STATE) : Result::OK; - } - Result getPresentationPosition(uint64_t &frames, TimeSpec &ts) override { const AutoMutex lock(mFrameCountersMutex); @@ -203,11 +199,7 @@ struct TinyalsaSink : public DevicePortSink { LOG_ALWAYS_FATAL_IF(mRingBuffer.consume(chunk, szBytes) < szBytes); } - int res = ::pcm_write(mPcm.get(), writeBuffer.data(), szBytes); - if (res < 0) { - ALOGW("TinyalsaSink::%s:%d pcm_write failed with res=%d", - __func__, __LINE__, res); - } + talsa::pcmWrite(mPcm.get(), writeBuffer.data(), szBytes); } } } @@ -252,9 +244,6 @@ struct NullSink : public DevicePortSink { , mInitialFrames(frames) , mFrames(frames) {} - Result start() override { return Result::OK; } - Result stop() override { return Result::OK; } - Result getPresentationPosition(uint64_t &frames, TimeSpec &ts) override { const AutoMutex lock(mFrameCountersMutex); diff --git a/audio/device_port_sink.h b/audio/device_port_sink.h index b2bd59b1..0276b25a 100644 --- a/audio/device_port_sink.h +++ b/audio/device_port_sink.h @@ -31,8 +31,6 @@ using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION; struct DevicePortSink { virtual ~DevicePortSink() {} - virtual Result start() = 0; - virtual Result stop() = 0; virtual Result getPresentationPosition(uint64_t &frames, TimeSpec &ts) = 0; virtual size_t write(float volume, size_t bytesToWrite, IReader &) = 0; diff --git a/audio/device_port_source.cpp b/audio/device_port_source.cpp index 7de160d8..e4c4528b 100644 --- a/audio/device_port_source.cpp +++ b/audio/device_port_source.cpp @@ -22,6 +22,7 @@ #include <audio_utils/channels.h> #include <audio_utils/format.h> #include <log/log.h> +#include <utils/Mutex.h> #include <utils/ThreadDefs.h> #include <utils/Timers.h> #include PATH(APM_XSD_ENUMS_H_FILENAME) @@ -63,7 +64,12 @@ struct TinyalsaSource : public DevicePortSource { cfg.base.sampleRateHz, cfg.frameCount, false /* isOut */)) { - mProduceThread = std::thread(&TinyalsaSource::producerThread, this); + if (mPcm) { + LOG_ALWAYS_FATAL_IF(!talsa::pcmPrepare(mPcm.get())); + mProduceThread = std::thread(&TinyalsaSource::producerThread, this); + } else { + mProduceThread = std::thread([](){}); + } } ~TinyalsaSource() { @@ -72,8 +78,10 @@ struct TinyalsaSource : public DevicePortSource { } Result getCapturePosition(uint64_t &frames, uint64_t &time) override { + const AutoMutex lock(mFrameCountersMutex); + const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC); - const uint64_t nowFrames = getCaptureFrames(nowNs); + const uint64_t nowFrames = getCaptureFramesLocked(nowNs); mFrames += (nowFrames - mPreviousFrames); mPreviousFrames = nowFrames; @@ -82,26 +90,28 @@ struct TinyalsaSource : public DevicePortSource { return Result::OK; } - uint64_t getCaptureFrames(const nsecs_t nowNs) const { + uint64_t getCaptureFramesLocked(const nsecs_t nowNs) const { return uint64_t(mSampleRateHz) * ns2us(nowNs - mStartNs) / 1000000; } - uint64_t getAvailableFrames(const nsecs_t nowNs) const { - return getCaptureFrames(nowNs) - mSentFrames; + uint64_t getAvailableFramesLocked(const nsecs_t nowNs) const { + return getCaptureFramesLocked(nowNs) - mSentFrames; } - uint64_t getAvailableFramesNow() const { - return getAvailableFrames(systemTime(SYSTEM_TIME_MONOTONIC)); + uint64_t getAvailableFramesNowLocked() const { + return getAvailableFramesLocked(systemTime(SYSTEM_TIME_MONOTONIC)); } - size_t getWaitFramesNow(const size_t requestedFrames) const { - const size_t availableFrames = getAvailableFramesNow(); + size_t getWaitFramesNowLocked(const size_t requestedFrames) const { + const size_t availableFrames = getAvailableFramesNowLocked(); return (requestedFrames > availableFrames) ? (requestedFrames - availableFrames) : 0; } size_t read(float volume, size_t bytesToRead, IWriter &writer) override { - const size_t waitFrames = getWaitFramesNow(bytesToRead / mFrameSize); + const AutoMutex lock(mFrameCountersMutex); + + const size_t waitFrames = getWaitFramesNowLocked(bytesToRead / mFrameSize); const auto blockUntil = std::chrono::high_resolution_clock::now() + + std::chrono::microseconds(waitFrames * 1000000 / mSampleRateHz); @@ -142,8 +152,8 @@ struct TinyalsaSource : public DevicePortSource { const size_t nZeroBytes = nZeroFrames * mFrameSize; writer(zeroes, nZeroBytes); - mSentFrames += nZeroFrames; bytesToRead -= nZeroBytes; + mSentFrames += nZeroFrames; } break; } @@ -176,14 +186,7 @@ struct TinyalsaSource : public DevicePortSource { } size_t doRead(void *dst, size_t sz) { - const int res = ::pcm_read(mPcm.get(), dst, sz); - if (res < 0) { - ALOGW("TinyalsaSource::%s:%d pcm_read failed with res=%d", - __func__, __LINE__, res); - return 0; - } - - return sz; + return talsa::pcmRead(mPcm.get(), dst, sz) ? sz : 0; } static std::unique_ptr<TinyalsaSource> create(unsigned pcmCard, @@ -207,15 +210,16 @@ private: const unsigned mSampleRateHz; const unsigned mFrameSize; const unsigned mReadSizeFrames; - uint64_t &mFrames; - uint64_t mPreviousFrames = 0; - uint64_t mSentFrames = 0; + uint64_t &mFrames GUARDED_BY(mFrameCountersMutex); + uint64_t mPreviousFrames GUARDED_BY(mFrameCountersMutex) = 0; + uint64_t mSentFrames GUARDED_BY(mFrameCountersMutex) = 0; std::atomic<uint32_t> mFramesLost = 0; RingBuffer mRingBuffer; talsa::Mixer mMixer; talsa::PcmPtr mPcm; std::thread mProduceThread; std::atomic<bool> mProduceThreadRunning = true; + mutable Mutex mFrameCountersMutex; }; template <class G> struct GeneratedSource : public DevicePortSource { @@ -231,8 +235,10 @@ template <class G> struct GeneratedSource : public DevicePortSource { , mGenerator(std::move(generator)) {} Result getCapturePosition(uint64_t &frames, uint64_t &time) override { + const AutoMutex lock(mFrameCountersMutex); + const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC); - const uint64_t nowFrames = getCaptureFrames(nowNs); + const uint64_t nowFrames = getCaptureFramesLocked(nowNs); mFrames += (nowFrames - mPreviousFrames); mPreviousFrames = nowFrames; frames = mFrames; @@ -240,15 +246,16 @@ template <class G> struct GeneratedSource : public DevicePortSource { return Result::OK; } - uint64_t getCaptureFrames(const nsecs_t nowNs) const { + uint64_t getCaptureFramesLocked(const nsecs_t nowNs) const { return uint64_t(mSampleRateHz) * ns2us(nowNs - mStartNs) / 1000000; } - uint64_t getAvailableFrames(const nsecs_t nowNs) const { - return getCaptureFrames(nowNs) - mSentFrames; + uint64_t getAvailableFramesLocked(const nsecs_t nowNs) const { + return getCaptureFramesLocked(nowNs) - mSentFrames; } size_t read(float volume, size_t bytesToRead, IWriter &writer) override { + const AutoMutex lock(mFrameCountersMutex); mWriteBuffer.resize(bytesToRead / sizeof(int16_t)); int16_t *samples = mWriteBuffer.data(); @@ -258,7 +265,7 @@ template <class G> struct GeneratedSource : public DevicePortSource { unsigned availableFrames; while (true) { const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC); - availableFrames = getAvailableFrames(nowNs); + availableFrames = getAvailableFramesLocked(nowNs); if (availableFrames < requestedFrames / 2) { const unsigned neededMoreFrames = requestedFrames / 2 - availableFrames; @@ -276,25 +283,27 @@ template <class G> struct GeneratedSource : public DevicePortSource { adjust_channels(samples, 1, samples, nChannels, sizeof(*samples), nFrames * sizeof(*samples)); } - mSentFrames += nFrames; aops::multiplyByVolume(volume, mWriteBuffer.data(), nSamples); writer(mWriteBuffer.data(), nSamples * sizeof(*samples)); + mSentFrames += nFrames; + return 0; } private: std::vector<int16_t> mWriteBuffer; - uint64_t &mFrames; + uint64_t &mFrames GUARDED_BY(mFrameCountersMutex); const nsecs_t mStartNs; const unsigned mSampleRateHz; const unsigned mNChannels; - uint64_t mPreviousFrames = 0; - uint64_t mSentFrames = 0; + uint64_t mPreviousFrames GUARDED_BY(mFrameCountersMutex) = 0; + uint64_t mSentFrames GUARDED_BY(mFrameCountersMutex) = 0; G mGenerator; + mutable Mutex mFrameCountersMutex; }; std::vector<int16_t> convertFloatsToInt16(const std::vector<float> &pcmFloat) { diff --git a/audio/stream_out.cpp b/audio/stream_out.cpp index 09fe0139..0c8e518f 100644 --- a/audio/stream_out.cpp +++ b/audio/stream_out.cpp @@ -80,13 +80,6 @@ struct WriteThread : public IOThread { mEfGroup.reset(rawEfGroup); } - mSink = DevicePortSink::create(mDataMQ.getQuantumCount(), - stream->getDeviceAddress(), - stream->getAudioConfig(), - stream->getAudioOutputFlags(), - stream->getFrameCounter()); - LOG_ALWAYS_FATAL_IF(!mSink); - mThread = std::thread(&WriteThread::threadLoop, this); } @@ -109,13 +102,6 @@ struct WriteThread : public IOThread { return mTid.get_future(); } - Result start() { - return mSink->start(); - } - - Result stop() { - return mSink->stop(); - } void threadLoop() { util::setThreadPriority(PRIORITY_URGENT_AUDIO); @@ -130,11 +116,19 @@ struct WriteThread : public IOThread { } if (efState & STAND_BY_REQUEST) { - mSink->stop(); + mSink.reset(); } if (efState & (MessageQueueFlagBits::NOT_EMPTY | 0)) { - mSink->start(); + if (!mSink) { + mSink = DevicePortSink::create(mDataMQ.getQuantumCount(), + mStream->getDeviceAddress(), + mStream->getAudioConfig(), + mStream->getAudioOutputFlags(), + mStream->getFrameCounter()); + LOG_ALWAYS_FATAL_IF(!mSink); + } + processCommand(); } } @@ -344,15 +338,11 @@ Return<Result> StreamOut::close() { } Return<Result> StreamOut::start() { - return mWriteThread - ? static_cast<WriteThread*>(mWriteThread.get())->start() - : FAILURE(Result::INVALID_STATE); + return FAILURE(Result::NOT_SUPPORTED); } Return<Result> StreamOut::stop() { - return mWriteThread - ? static_cast<WriteThread*>(mWriteThread.get())->stop() - : FAILURE(Result::INVALID_STATE); + return FAILURE(Result::NOT_SUPPORTED); } Return<void> StreamOut::createMmapBuffer(int32_t minSizeFrames, diff --git a/audio/talsa.cpp b/audio/talsa.cpp index 985ca2a4..4bc0c4f6 100644 --- a/audio/talsa.cpp +++ b/audio/talsa.cpp @@ -132,6 +132,81 @@ std::unique_ptr<pcm_t, PcmDeleter> pcmOpen(const unsigned int dev, } } +bool pcmPrepare(pcm_t *pcm) { + if (!pcm) { + return FAILURE(false); + } + + const int r = ::pcm_prepare(pcm); + if (r) { + ALOGE("%s:%d pcm_prepare failed with %s", + __func__, __LINE__, ::pcm_get_error(pcm)); + return FAILURE(false); + } else { + return true; + } +} + +bool pcmStart(pcm_t *pcm) { + if (!pcm) { + return FAILURE(false); + } + + const int r = ::pcm_start(pcm); + if (r) { + ALOGE("%s:%d pcm_start failed with %s", + __func__, __LINE__, ::pcm_get_error(pcm)); + return FAILURE(false); + } else { + return true; + } +} + +bool pcmStop(pcm_t *pcm) { + if (!pcm) { + return FAILURE(false); + } + + const int r = ::pcm_stop(pcm); + if (r) { + ALOGE("%s:%d pcm_stop failed with %s", + __func__, __LINE__, ::pcm_get_error(pcm)); + return FAILURE(false); + } else { + return true; + } +} + +bool pcmRead(pcm_t *pcm, void *data, unsigned int count) { + if (!pcm) { + return FAILURE(false); + } + + const int r = ::pcm_read(pcm, data, count); + if (r) { + ALOGE("%s:%d pcm_read failed with %s (%d)", + __func__, __LINE__, ::pcm_get_error(pcm), r); + return FAILURE(false); + } else { + return true; + } +} + +bool pcmWrite(pcm_t *pcm, const void *data, unsigned int count) { + if (!pcm) { + return FAILURE(false); + } + + const int r = ::pcm_write(pcm, data, count); + if (r) { + ALOGE("%s:%d pcm_write failed with %s (%d)", + __func__, __LINE__, ::pcm_get_error(pcm), r); + return FAILURE(false); + } else { + return true; + } +} + Mixer::Mixer(unsigned card): mMixer(mixerGetOrOpen(card)) {} Mixer::~Mixer() { diff --git a/audio/talsa.h b/audio/talsa.h index 02c09d4d..c77b08f3 100644 --- a/audio/talsa.h +++ b/audio/talsa.h @@ -32,6 +32,11 @@ typedef struct pcm pcm_t; struct PcmDeleter { void operator()(pcm_t *x) const; }; typedef std::unique_ptr<pcm_t, PcmDeleter> PcmPtr; PcmPtr pcmOpen(unsigned int dev, unsigned int card, unsigned int nChannels, size_t sampleRateHz, size_t frameCount, bool isOut); +bool pcmPrepare(pcm_t *pcm); +bool pcmStart(pcm_t *pcm); +bool pcmStop(pcm_t *pcm); +bool pcmRead(pcm_t *pcm, void *data, unsigned int count); +bool pcmWrite(pcm_t *pcm, const void *data, unsigned int count); class Mixer { public: diff --git a/overlay/frameworks/base/core/res/res/values/config.xml b/overlay/frameworks/base/core/res/res/values/config.xml index 237e9fab..522d1978 100644 --- a/overlay/frameworks/base/core/res/res/values/config.xml +++ b/overlay/frameworks/base/core/res/res/values/config.xml @@ -79,4 +79,7 @@ <item>telephony</item> <item>network</item> </string-array> + + <bool name="config_supportMicNearUltrasound">false</bool> + <bool name="config_supportSpeakerNearUltrasound">false</bool> </resources> |