Merge "virtio gpu can manage the colorbuffer. Don't need RefCountPipe" into tm-dev
diff --git a/audio/device_port_sink.cpp b/audio/device_port_sink.cpp
index 12754ff..3936805 100644
--- a/audio/device_port_sink.cpp
+++ b/audio/device_port_sink.cpp
@@ -62,8 +62,12 @@
                                   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 @@
         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 @@
                     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 @@
             , 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 b2bd59b..0276b25 100644
--- a/audio/device_port_sink.h
+++ b/audio/device_port_sink.h
@@ -31,8 +31,6 @@
 
 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 7de160d..e4c4528 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 @@
                                   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 @@
     }
 
     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 @@
         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 @@
                     const size_t nZeroBytes = nZeroFrames * mFrameSize;
 
                     writer(zeroes, nZeroBytes);
-                    mSentFrames += nZeroFrames;
                     bytesToRead -= nZeroBytes;
+                    mSentFrames += nZeroFrames;
                 }
                 break;
             }
@@ -176,14 +186,7 @@
     }
 
     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 @@
     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 @@
             , 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 @@
         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 @@
         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 @@
             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 09fe013..0c8e518 100644
--- a/audio/stream_out.cpp
+++ b/audio/stream_out.cpp
@@ -80,13 +80,6 @@
             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 @@
         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 @@
             }
 
             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::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 985ca2a..4bc0c4f 100644
--- a/audio/talsa.cpp
+++ b/audio/talsa.cpp
@@ -132,6 +132,81 @@
     }
 }
 
+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 02c09d4..c77b08f 100644
--- a/audio/talsa.h
+++ b/audio/talsa.h
@@ -32,6 +32,11 @@
 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 237e9fa..522d197 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>