1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <android-base/properties.h>
18 #include <cmath>
19 #include <chrono>
20 #include <thread>
21 #include <unistd.h>
22 #include <audio_utils/channels.h>
23 #include <audio_utils/format.h>
24 #include <log/log.h>
25 #include <utils/Mutex.h>
26 #include <utils/ThreadDefs.h>
27 #include <utils/Timers.h>
28 #include PATH(APM_XSD_ENUMS_H_FILENAME)
29 #include "device_port_source.h"
30 #include "talsa.h"
31 #include "ring_buffer.h"
32 #include "audio_ops.h"
33 #include "util.h"
34 #include "debug.h"
35 
36 using ::android::base::GetBoolProperty;
37 
38 namespace xsd {
39 using namespace ::android::audio::policy::configuration::CPP_VERSION;
40 }
41 
42 namespace android {
43 namespace hardware {
44 namespace audio {
45 namespace CPP_VERSION {
46 namespace implementation {
47 
48 namespace {
49 
50 constexpr int kMaxJitterUs = 3000;  // Enforced by CTS, should be <= 6ms
51 
52 struct TinyalsaSource : public DevicePortSource {
TinyalsaSourceandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::TinyalsaSource53     TinyalsaSource(unsigned pcmCard, unsigned pcmDevice,
54                    const AudioConfig &cfg, uint64_t &frames)
55             : mStartNs(systemTime(SYSTEM_TIME_MONOTONIC))
56             , mSampleRateHz(cfg.base.sampleRateHz)
57             , mFrameSize(util::countChannels(cfg.base.channelMask) * sizeof(int16_t))
58             , mReadSizeFrames(cfg.frameCount)
59             , mFrames(frames)
60             , mRingBuffer(mFrameSize * cfg.frameCount * 3)
61             , mMixer(pcmCard)
62             , mPcm(talsa::pcmOpen(pcmCard, pcmDevice,
63                                   util::countChannels(cfg.base.channelMask),
64                                   cfg.base.sampleRateHz,
65                                   cfg.frameCount,
66                                   false /* isOut */)) {
67         if (mPcm) {
68             mProduceThread = std::thread(&TinyalsaSource::producerThread, this);
69         } else {
70             mProduceThread = std::thread([](){});
71         }
72     }
73 
~TinyalsaSourceandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::TinyalsaSource74     ~TinyalsaSource() {
75         mProduceThreadRunning = false;
76         mProduceThread.join();
77     }
78 
getCapturePositionandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::TinyalsaSource79     Result getCapturePosition(uint64_t &frames, uint64_t &time) override {
80         const AutoMutex lock(mFrameCountersMutex);
81 
82         const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
83         const uint64_t nowFrames = getCaptureFramesLocked(nowNs);
84         mFrames += (nowFrames - mPreviousFrames);
85         mPreviousFrames = nowFrames;
86 
87         frames = mFrames;
88         time = nowNs;
89         return Result::OK;
90     }
91 
getCaptureFramesLockedandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::TinyalsaSource92     uint64_t getCaptureFramesLocked(const nsecs_t nowNs) const {
93         return uint64_t(mSampleRateHz) * ns2us(nowNs - mStartNs) / 1000000;
94     }
95 
getAvailableFramesLockedandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::TinyalsaSource96     uint64_t getAvailableFramesLocked(const nsecs_t nowNs) const {
97         return getCaptureFramesLocked(nowNs) - mSentFrames;
98     }
99 
getAvailableFramesNowLockedandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::TinyalsaSource100     uint64_t getAvailableFramesNowLocked() const {
101         return getAvailableFramesLocked(systemTime(SYSTEM_TIME_MONOTONIC));
102     }
103 
getWaitFramesNowLockedandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::TinyalsaSource104     size_t getWaitFramesNowLocked(const size_t requestedFrames) const {
105         const size_t availableFrames = getAvailableFramesNowLocked();
106         return (requestedFrames > availableFrames)
107             ? (requestedFrames - availableFrames) : 0;
108     }
109 
readandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::TinyalsaSource110     size_t read(float volume, size_t bytesToRead, IWriter &writer) override {
111         const AutoMutex lock(mFrameCountersMutex);
112 
113         const size_t waitFrames = getWaitFramesNowLocked(bytesToRead / mFrameSize);
114         const auto blockUntil =
115             std::chrono::high_resolution_clock::now() +
116                 + std::chrono::microseconds(waitFrames * 1000000 / mSampleRateHz);
117 
118         while (bytesToRead > 0) {
119             if (mRingBuffer.waitForConsumeAvailable(blockUntil
120                     + std::chrono::microseconds(kMaxJitterUs))) {
121                 if (mRingBuffer.availableToConsume() >= bytesToRead) {
122                     // Since the ring buffer has all bytes we need, make sure we
123                     // are not too early here: tinyalsa is jittery, we don't
124                     // want to go faster than SYSTEM_TIME_MONOTONIC
125                     std::this_thread::sleep_until(blockUntil);
126                 }
127 
128                 auto chunk = mRingBuffer.getConsumeChunk();
129                 const size_t writeBufSzBytes = std::min(chunk.size, bytesToRead);
130 
131                 aops::multiplyByVolume(volume,
132                                        static_cast<int16_t *>(chunk.data),
133                                        writeBufSzBytes / sizeof(int16_t));
134 
135                 writer(chunk.data, writeBufSzBytes);
136                 LOG_ALWAYS_FATAL_IF(mRingBuffer.consume(chunk, writeBufSzBytes) < writeBufSzBytes);
137 
138                 bytesToRead -= writeBufSzBytes;
139                 mSentFrames += writeBufSzBytes / mFrameSize;
140             } else {
141                 ALOGD("TinyalsaSource::%s:%d pcm_readi was late delivering "
142                       "frames, inserting %zu us of silence",
143                       __func__, __LINE__,
144                       size_t(1000000 * bytesToRead / mFrameSize / mSampleRateHz));
145 
146                 static const uint8_t zeroes[256] = {0};
147 
148                 while (bytesToRead > 0) {
149                     const size_t nZeroFrames =
150                         std::min(bytesToRead, sizeof(zeroes)) / mFrameSize;
151                     const size_t nZeroBytes = nZeroFrames * mFrameSize;
152 
153                     writer(zeroes, nZeroBytes);
154                     bytesToRead -= nZeroBytes;
155                     mSentFrames += nZeroFrames;
156                 }
157                 break;
158             }
159         }
160 
161         return mFramesLost.exchange(0);
162     }
163 
producerThreadandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::TinyalsaSource164     void producerThread() {
165         util::setThreadPriority(SP_AUDIO_SYS, PRIORITY_AUDIO);
166         std::vector<uint8_t> readBuf(mReadSizeFrames * mFrameSize);
167 
168         while (mProduceThreadRunning) {
169             const size_t bytesLost = mRingBuffer.makeRoomForProduce(readBuf.size());
170             mFramesLost += bytesLost / mFrameSize;
171 
172             auto produceChunk = mRingBuffer.getProduceChunk();
173             if (produceChunk.size < readBuf.size()) {
174                 const size_t sz = doRead(readBuf.data(), readBuf.size());
175                 if (sz > 0) {
176                     LOG_ALWAYS_FATAL_IF(mRingBuffer.produce(readBuf.data(), sz) < sz);
177                 }
178             } else {
179                 const size_t sz = doRead(produceChunk.data, readBuf.size());
180                 if (sz > 0) {
181                     LOG_ALWAYS_FATAL_IF(mRingBuffer.produce(readBuf.size()) < sz);
182                 }
183             }
184         }
185     }
186 
doReadandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::TinyalsaSource187     size_t doRead(void *dst, size_t sz) {
188         const int n = talsa::pcmRead(mPcm.get(), dst, sz, mFrameSize);
189         if (n > 0) {
190             LOG_ALWAYS_FATAL_IF(static_cast<size_t>(n) > sz,
191                                 "n=%d sz=%zu mFrameSize=%u", n, sz, mFrameSize);
192             return n;
193         } else {
194             return 0;
195         }
196     }
197 
createandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::TinyalsaSource198     static std::unique_ptr<TinyalsaSource> create(unsigned pcmCard,
199                                                   unsigned pcmDevice,
200                                                   const AudioConfig &cfg,
201                                                   size_t writerBufferSizeHint,
202                                                   uint64_t &frames) {
203         (void)writerBufferSizeHint;
204 
205         auto src = std::make_unique<TinyalsaSource>(pcmCard, pcmDevice,
206                                                     cfg, frames);
207         if (src->mMixer && src->mPcm) {
208             return src;
209         } else {
210             return FAILURE(nullptr);
211         }
212     }
213 
214 private:
215     const nsecs_t mStartNs;
216     const unsigned mSampleRateHz;
217     const unsigned mFrameSize;
218     const unsigned mReadSizeFrames;
219     uint64_t &mFrames GUARDED_BY(mFrameCountersMutex);
220     uint64_t mPreviousFrames GUARDED_BY(mFrameCountersMutex) = 0;
221     uint64_t mSentFrames GUARDED_BY(mFrameCountersMutex) = 0;
222     std::atomic<uint32_t> mFramesLost = 0;
223     RingBuffer mRingBuffer;
224     talsa::Mixer mMixer;
225     talsa::PcmPtr mPcm;
226     std::thread mProduceThread;
227     std::atomic<bool> mProduceThreadRunning = true;
228     mutable Mutex mFrameCountersMutex;
229 };
230 
231 template <class G> struct GeneratedSource : public DevicePortSource {
GeneratedSourceandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::GeneratedSource232     GeneratedSource(const AudioConfig &cfg,
233                     size_t writerBufferSizeHint,
234                     uint64_t &frames,
235                     G generator)
236             : mWriteBuffer(writerBufferSizeHint / sizeof(int16_t))
237             , mFrames(frames)
238             , mStartNs(systemTime(SYSTEM_TIME_MONOTONIC))
239             , mSampleRateHz(cfg.base.sampleRateHz)
240             , mNChannels(util::countChannels(cfg.base.channelMask))
241             , mGenerator(std::move(generator)) {}
242 
getCapturePositionandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::GeneratedSource243     Result getCapturePosition(uint64_t &frames, uint64_t &time) override {
244         const AutoMutex lock(mFrameCountersMutex);
245 
246         const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
247         const uint64_t nowFrames = getCaptureFramesLocked(nowNs);
248         mFrames += (nowFrames - mPreviousFrames);
249         mPreviousFrames = nowFrames;
250         frames = mFrames;
251         time = nowNs;
252         return Result::OK;
253     }
254 
getCaptureFramesLockedandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::GeneratedSource255     uint64_t getCaptureFramesLocked(const nsecs_t nowNs) const {
256         return uint64_t(mSampleRateHz) * ns2us(nowNs - mStartNs) / 1000000;
257     }
258 
getAvailableFramesLockedandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::GeneratedSource259     uint64_t getAvailableFramesLocked(const nsecs_t nowNs) const {
260         return getCaptureFramesLocked(nowNs) - mSentFrames;
261     }
262 
readandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::GeneratedSource263     size_t read(float volume, size_t bytesToRead, IWriter &writer) override {
264         const AutoMutex lock(mFrameCountersMutex);
265         mWriteBuffer.resize(bytesToRead / sizeof(int16_t));
266 
267         int16_t *samples = mWriteBuffer.data();
268         const unsigned nChannels = mNChannels;
269         const unsigned requestedFrames = bytesToRead / nChannels / sizeof(*samples);
270 
271         unsigned availableFrames;
272         while (true) {
273             const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
274             availableFrames = getAvailableFramesLocked(nowNs);
275             if (availableFrames < requestedFrames / 2) {
276                 const unsigned neededMoreFrames = requestedFrames / 2 - availableFrames;
277 
278                 using namespace std::chrono_literals;
279                 std::this_thread::sleep_for(1s * neededMoreFrames / mSampleRateHz);
280             } else {
281                 break;
282             }
283         }
284 
285         const unsigned nFrames = std::min(requestedFrames, availableFrames);
286         mGenerator(samples, nFrames);
287         const size_t nSamples = nFrames * nChannels;
288         if (nChannels > 1) {
289             adjust_channels(samples, 1, samples, nChannels,
290                             sizeof(*samples), nFrames * sizeof(*samples));
291         }
292 
293         aops::multiplyByVolume(volume,
294                                mWriteBuffer.data(),
295                                nSamples);
296 
297         writer(mWriteBuffer.data(), nSamples * sizeof(*samples));
298         mSentFrames += nFrames;
299 
300         return 0;
301     }
302 
303 private:
304     std::vector<int16_t> mWriteBuffer;
305     uint64_t &mFrames GUARDED_BY(mFrameCountersMutex);
306     const nsecs_t mStartNs;
307     const unsigned mSampleRateHz;
308     const unsigned mNChannels;
309     uint64_t mPreviousFrames GUARDED_BY(mFrameCountersMutex) = 0;
310     uint64_t mSentFrames GUARDED_BY(mFrameCountersMutex) = 0;
311     G mGenerator;
312     mutable Mutex mFrameCountersMutex;
313 };
314 
convertFloatsToInt16(const std::vector<float> & pcmFloat)315 std::vector<int16_t> convertFloatsToInt16(const std::vector<float> &pcmFloat) {
316     std::vector<int16_t> pcmI16(pcmFloat.size());
317 
318     memcpy_by_audio_format(pcmI16.data(),   AUDIO_FORMAT_PCM_16_BIT,
319                            pcmFloat.data(), AUDIO_FORMAT_PCM_FLOAT,
320                            pcmFloat.size());
321 
322     return pcmI16;
323 }
324 
325 // https://en.wikipedia.org/wiki/Busy_signal
326 struct BusySignalGenerator {
BusySignalGeneratorandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::BusySignalGenerator327     explicit BusySignalGenerator(const uint32_t sampleRateHz) : mSampleRateHz(sampleRateHz) {
328         // 24/480 = 31/620, mValues must contain 50ms of audio samples
329         const size_t sz = sampleRateHz / 20;
330         std::vector<float> pcm(sz);
331         for (unsigned i = 0; i < sz; ++i) {
332             const double a = double(i) * M_PI * 2 / sampleRateHz;
333             pcm[i] = .5 * (sin(480 * a) + sin(620 * a));
334         }
335         mValues = convertFloatsToInt16(pcm);
336     }
337 
operator ()android::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::BusySignalGenerator338     void operator()(int16_t* s, size_t n) {
339         const unsigned rate = mSampleRateHz;
340         const unsigned rateHalf = rate / 2;
341         const int16_t *const vals = mValues.data();
342         const size_t valsSz = mValues.size();
343         size_t i = mI;
344 
345         while (n > 0) {
346             size_t len;
347             if (i < rateHalf) {
348                 const size_t valsOff = i % valsSz;
349                 len = std::min(n, std::min(rateHalf - i, valsSz - valsOff));
350                 memcpy(s, vals + valsOff, len * sizeof(*s));
351             } else {
352                 len = std::min(n, rate - i);
353                 memset(s, 0, len * sizeof(*s));
354             }
355             s += len;
356             i = (i + len) % rate;
357             n -= len;
358         }
359 
360         mI = i;
361     }
362 
363 private:
364     const unsigned mSampleRateHz;
365     std::vector<int16_t> mValues;
366     size_t mI = 0;
367 };
368 
369 struct RepeatGenerator {
RepeatGeneratorandroid::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::RepeatGenerator370     explicit RepeatGenerator(const std::vector<float> &pcm)
371             : mValues(convertFloatsToInt16(pcm)) {}
372 
operator ()android::hardware::audio::CPP_VERSION::implementation::__anond1989e5f0111::RepeatGenerator373     void operator()(int16_t* s, size_t n) {
374         const int16_t *const vals = mValues.data();
375         const size_t valsSz = mValues.size();
376         size_t i = mI;
377 
378         while (n > 0) {
379             const size_t len = std::min(n, valsSz - i);
380             memcpy(s, vals + i, len * sizeof(*s));
381             s += len;
382             i = (i + len) % valsSz;
383             n -= len;
384         }
385 
386         mI = i;
387     }
388 
389 private:
390     const std::vector<int16_t> mValues;
391     size_t mI = 0;
392 };
393 
generateSinePattern(uint32_t sampleRateHz,double freq,double amp)394 std::vector<float> generateSinePattern(uint32_t sampleRateHz,
395                                        double freq,
396                                        double amp) {
397     std::vector<float> result(3 * sampleRateHz / freq + .5);
398 
399     for (size_t i = 0; i < result.size(); ++i) {
400         const double a = double(i) * M_PI * 2 / sampleRateHz;
401         result[i] = amp * sin(a * freq);
402     }
403 
404     return result;
405 }
406 
407 template <class G> std::unique_ptr<GeneratedSource<G>>
createGeneratedSource(const AudioConfig & cfg,size_t writerBufferSizeHint,uint64_t & frames,G generator)408 createGeneratedSource(const AudioConfig &cfg,
409                       size_t writerBufferSizeHint,
410                       uint64_t &frames,
411                       G generator) {
412     return std::make_unique<GeneratedSource<G>>(cfg,
413                                                 writerBufferSizeHint,
414                                                 frames,
415                                                 std::move(generator));
416 }
417 
418 }  // namespace
419 
420 std::unique_ptr<DevicePortSource>
create(size_t writerBufferSizeHint,const DeviceAddress & address,const AudioConfig & cfg,const hidl_vec<AudioInOutFlag> & flags,uint64_t & frames)421 DevicePortSource::create(size_t writerBufferSizeHint,
422                          const DeviceAddress &address,
423                          const AudioConfig &cfg,
424                          const hidl_vec<AudioInOutFlag> &flags,
425                          uint64_t &frames) {
426     (void)flags;
427 
428     if (xsd::stringToAudioFormat(cfg.base.format) != xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT) {
429         ALOGE("%s:%d, unexpected format: '%s'", __func__, __LINE__, cfg.base.format.c_str());
430         return FAILURE(nullptr);
431     }
432 
433     switch (xsd::stringToAudioDevice(address.deviceType)) {
434     case xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT:
435     case xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC:
436         if (GetBoolProperty("ro.boot.audio.tinyalsa.simulate_input", false)) {
437             return createGeneratedSource(
438                 cfg, writerBufferSizeHint, frames,
439                 RepeatGenerator(generateSinePattern(cfg.base.sampleRateHz, 300.0, 1.0)));
440         } else {
441             auto sourceptr = TinyalsaSource::create(talsa::kPcmCard, talsa::kPcmDevice,
442                                                     cfg, writerBufferSizeHint, frames);
443             if (sourceptr != nullptr) {
444                 return sourceptr;
445             } else {
446                 ALOGW("%s:%d failed to create alsa source for '%s'; creating a tone source instead.",
447                       __func__, __LINE__, address.deviceType.c_str());
448             }
449         }
450         break;
451 
452     case xsd::AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX:
453         return createGeneratedSource(cfg, writerBufferSizeHint, frames,
454                                      BusySignalGenerator(cfg.base.sampleRateHz));
455 
456     case xsd::AudioDevice::AUDIO_DEVICE_IN_FM_TUNER:
457         return createGeneratedSource(
458             cfg, writerBufferSizeHint, frames,
459             RepeatGenerator(generateSinePattern(cfg.base.sampleRateHz, 440.0, 1.0)));
460 
461     default:
462         ALOGW("%s:%d unsupported device: '%s', creating a tone source",
463               __func__, __LINE__, address.deviceType.c_str());
464         break;
465     }
466 
467     return createGeneratedSource(
468         cfg, writerBufferSizeHint, frames,
469         RepeatGenerator(generateSinePattern(cfg.base.sampleRateHz, 220.0, 1.0)));
470 }
471 
validateDeviceAddress(const DeviceAddress & address)472 bool DevicePortSource::validateDeviceAddress(const DeviceAddress& address) {
473     switch (xsd::stringToAudioDevice(address.deviceType)) {
474     default:
475         ALOGW("%s:%d unsupported device: '%s'", __func__, __LINE__, address.deviceType.c_str());
476         return FAILURE(false);
477 
478     case xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT:
479     case xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC:
480     case xsd::AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX:
481     case xsd::AudioDevice::AUDIO_DEVICE_IN_FM_TUNER:
482     case xsd::AudioDevice::AUDIO_DEVICE_IN_BUS:
483         break;
484     }
485 
486     return true;
487 }
488 
489 }  // namespace implementation
490 }  // namespace CPP_VERSION
491 }  // namespace audio
492 }  // namespace hardware
493 }  // namespace android
494