• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::__anon52e7b78b0111::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::__anon52e7b78b0111::TinyalsaSource74     ~TinyalsaSource() {
75         mProduceThreadRunning = false;
76         mProduceThread.join();
77     }
78 
getCapturePositionandroid::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::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::__anon52e7b78b0111::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::__anon52e7b78b0111::TinyalsaSource96     uint64_t getAvailableFramesLocked(const nsecs_t nowNs) const {
97         return getCaptureFramesLocked(nowNs) - mSentFrames;
98     }
99 
getAvailableFramesNowLockedandroid::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::TinyalsaSource100     uint64_t getAvailableFramesNowLocked() const {
101         return getAvailableFramesLocked(systemTime(SYSTEM_TIME_MONOTONIC));
102     }
103 
getWaitFramesNowLockedandroid::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::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::__anon52e7b78b0111::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                 ALOGW("TinyalsaSource::%s:%d pcm_read 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::__anon52e7b78b0111::TinyalsaSource164     void producerThread() {
165         util::setThreadPriority(PRIORITY_URGENT_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::__anon52e7b78b0111::TinyalsaSource187     size_t doRead(void *dst, size_t sz) {
188         return talsa::pcmRead(mPcm.get(), dst, sz) ? sz : 0;
189     }
190 
createandroid::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::TinyalsaSource191     static std::unique_ptr<TinyalsaSource> create(unsigned pcmCard,
192                                                   unsigned pcmDevice,
193                                                   const AudioConfig &cfg,
194                                                   size_t writerBufferSizeHint,
195                                                   uint64_t &frames) {
196         (void)writerBufferSizeHint;
197 
198         auto src = std::make_unique<TinyalsaSource>(pcmCard, pcmDevice,
199                                                     cfg, frames);
200         if (src->mMixer && src->mPcm) {
201             return src;
202         } else {
203             return FAILURE(nullptr);
204         }
205     }
206 
207 private:
208     const nsecs_t mStartNs;
209     const unsigned mSampleRateHz;
210     const unsigned mFrameSize;
211     const unsigned mReadSizeFrames;
212     uint64_t &mFrames GUARDED_BY(mFrameCountersMutex);
213     uint64_t mPreviousFrames GUARDED_BY(mFrameCountersMutex) = 0;
214     uint64_t mSentFrames GUARDED_BY(mFrameCountersMutex) = 0;
215     std::atomic<uint32_t> mFramesLost = 0;
216     RingBuffer mRingBuffer;
217     talsa::Mixer mMixer;
218     talsa::PcmPtr mPcm;
219     std::thread mProduceThread;
220     std::atomic<bool> mProduceThreadRunning = true;
221     mutable Mutex mFrameCountersMutex;
222 };
223 
224 template <class G> struct GeneratedSource : public DevicePortSource {
GeneratedSourceandroid::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::GeneratedSource225     GeneratedSource(const AudioConfig &cfg,
226                     size_t writerBufferSizeHint,
227                     uint64_t &frames,
228                     G generator)
229             : mWriteBuffer(writerBufferSizeHint / sizeof(int16_t))
230             , mFrames(frames)
231             , mStartNs(systemTime(SYSTEM_TIME_MONOTONIC))
232             , mSampleRateHz(cfg.base.sampleRateHz)
233             , mNChannels(util::countChannels(cfg.base.channelMask))
234             , mGenerator(std::move(generator)) {}
235 
getCapturePositionandroid::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::GeneratedSource236     Result getCapturePosition(uint64_t &frames, uint64_t &time) override {
237         const AutoMutex lock(mFrameCountersMutex);
238 
239         const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
240         const uint64_t nowFrames = getCaptureFramesLocked(nowNs);
241         mFrames += (nowFrames - mPreviousFrames);
242         mPreviousFrames = nowFrames;
243         frames = mFrames;
244         time = nowNs;
245         return Result::OK;
246     }
247 
getCaptureFramesLockedandroid::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::GeneratedSource248     uint64_t getCaptureFramesLocked(const nsecs_t nowNs) const {
249         return uint64_t(mSampleRateHz) * ns2us(nowNs - mStartNs) / 1000000;
250     }
251 
getAvailableFramesLockedandroid::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::GeneratedSource252     uint64_t getAvailableFramesLocked(const nsecs_t nowNs) const {
253         return getCaptureFramesLocked(nowNs) - mSentFrames;
254     }
255 
readandroid::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::GeneratedSource256     size_t read(float volume, size_t bytesToRead, IWriter &writer) override {
257         const AutoMutex lock(mFrameCountersMutex);
258         mWriteBuffer.resize(bytesToRead / sizeof(int16_t));
259 
260         int16_t *samples = mWriteBuffer.data();
261         const unsigned nChannels = mNChannels;
262         const unsigned requestedFrames = bytesToRead / nChannels / sizeof(*samples);
263 
264         unsigned availableFrames;
265         while (true) {
266             const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
267             availableFrames = getAvailableFramesLocked(nowNs);
268             if (availableFrames < requestedFrames / 2) {
269                 const unsigned neededMoreFrames = requestedFrames / 2 - availableFrames;
270 
271                 using namespace std::chrono_literals;
272                 std::this_thread::sleep_for(1s * neededMoreFrames / mSampleRateHz);
273             } else {
274                 break;
275             }
276         }
277 
278         const unsigned nFrames = std::min(requestedFrames, availableFrames);
279         mGenerator(samples, nFrames);
280         const size_t nSamples = nFrames * nChannels;
281         if (nChannels > 1) {
282             adjust_channels(samples, 1, samples, nChannels,
283                             sizeof(*samples), nFrames * sizeof(*samples));
284         }
285 
286         aops::multiplyByVolume(volume,
287                                mWriteBuffer.data(),
288                                nSamples);
289 
290         writer(mWriteBuffer.data(), nSamples * sizeof(*samples));
291         mSentFrames += nFrames;
292 
293         return 0;
294     }
295 
296 private:
297     std::vector<int16_t> mWriteBuffer;
298     uint64_t &mFrames GUARDED_BY(mFrameCountersMutex);
299     const nsecs_t mStartNs;
300     const unsigned mSampleRateHz;
301     const unsigned mNChannels;
302     uint64_t mPreviousFrames GUARDED_BY(mFrameCountersMutex) = 0;
303     uint64_t mSentFrames GUARDED_BY(mFrameCountersMutex) = 0;
304     G mGenerator;
305     mutable Mutex mFrameCountersMutex;
306 };
307 
convertFloatsToInt16(const std::vector<float> & pcmFloat)308 std::vector<int16_t> convertFloatsToInt16(const std::vector<float> &pcmFloat) {
309     std::vector<int16_t> pcmI16(pcmFloat.size());
310 
311     memcpy_by_audio_format(pcmI16.data(),   AUDIO_FORMAT_PCM_16_BIT,
312                            pcmFloat.data(), AUDIO_FORMAT_PCM_FLOAT,
313                            pcmFloat.size());
314 
315     return pcmI16;
316 }
317 
318 // https://en.wikipedia.org/wiki/Busy_signal
319 struct BusySignalGenerator {
BusySignalGeneratorandroid::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::BusySignalGenerator320     explicit BusySignalGenerator(const uint32_t sampleRateHz) : mSampleRateHz(sampleRateHz) {
321         // 24/480 = 31/620, mValues must contain 50ms of audio samples
322         const size_t sz = sampleRateHz / 20;
323         std::vector<float> pcm(sz);
324         for (unsigned i = 0; i < sz; ++i) {
325             const double a = double(i) * M_PI * 2 / sampleRateHz;
326             pcm[i] = .5 * (sin(480 * a) + sin(620 * a));
327         }
328         mValues = convertFloatsToInt16(pcm);
329     }
330 
operator ()android::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::BusySignalGenerator331     void operator()(int16_t* s, size_t n) {
332         const unsigned rate = mSampleRateHz;
333         const unsigned rateHalf = rate / 2;
334         const int16_t *const vals = mValues.data();
335         const size_t valsSz = mValues.size();
336         size_t i = mI;
337 
338         while (n > 0) {
339             size_t len;
340             if (i < rateHalf) {
341                 const size_t valsOff = i % valsSz;
342                 len = std::min(n, std::min(rateHalf - i, valsSz - valsOff));
343                 memcpy(s, vals + valsOff, len * sizeof(*s));
344             } else {
345                 len = std::min(n, rate - i);
346                 memset(s, 0, len * sizeof(*s));
347             }
348             s += len;
349             i = (i + len) % rate;
350             n -= len;
351         }
352 
353         mI = i;
354     }
355 
356 private:
357     const unsigned mSampleRateHz;
358     std::vector<int16_t> mValues;
359     size_t mI = 0;
360 };
361 
362 struct RepeatGenerator {
RepeatGeneratorandroid::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::RepeatGenerator363     explicit RepeatGenerator(const std::vector<float> &pcm)
364             : mValues(convertFloatsToInt16(pcm)) {}
365 
operator ()android::hardware::audio::CPP_VERSION::implementation::__anon52e7b78b0111::RepeatGenerator366     void operator()(int16_t* s, size_t n) {
367         const int16_t *const vals = mValues.data();
368         const size_t valsSz = mValues.size();
369         size_t i = mI;
370 
371         while (n > 0) {
372             const size_t len = std::min(n, valsSz - i);
373             memcpy(s, vals + i, len * sizeof(*s));
374             s += len;
375             i = (i + len) % valsSz;
376             n -= len;
377         }
378 
379         mI = i;
380     }
381 
382 private:
383     const std::vector<int16_t> mValues;
384     size_t mI = 0;
385 };
386 
generateSinePattern(uint32_t sampleRateHz,double freq,double amp)387 std::vector<float> generateSinePattern(uint32_t sampleRateHz,
388                                        double freq,
389                                        double amp) {
390     std::vector<float> result(3 * sampleRateHz / freq + .5);
391 
392     for (size_t i = 0; i < result.size(); ++i) {
393         const double a = double(i) * M_PI * 2 / sampleRateHz;
394         result[i] = amp * sin(a * freq);
395     }
396 
397     return result;
398 }
399 
400 template <class G> std::unique_ptr<GeneratedSource<G>>
createGeneratedSource(const AudioConfig & cfg,size_t writerBufferSizeHint,uint64_t & frames,G generator)401 createGeneratedSource(const AudioConfig &cfg,
402                       size_t writerBufferSizeHint,
403                       uint64_t &frames,
404                       G generator) {
405     return std::make_unique<GeneratedSource<G>>(cfg,
406                                                 writerBufferSizeHint,
407                                                 frames,
408                                                 std::move(generator));
409 }
410 
411 }  // namespace
412 
413 std::unique_ptr<DevicePortSource>
create(size_t writerBufferSizeHint,const DeviceAddress & address,const AudioConfig & cfg,const hidl_vec<AudioInOutFlag> & flags,uint64_t & frames)414 DevicePortSource::create(size_t writerBufferSizeHint,
415                          const DeviceAddress &address,
416                          const AudioConfig &cfg,
417                          const hidl_vec<AudioInOutFlag> &flags,
418                          uint64_t &frames) {
419     (void)flags;
420 
421     if (xsd::stringToAudioFormat(cfg.base.format) != xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT) {
422         ALOGE("%s:%d, unexpected format: '%s'", __func__, __LINE__, cfg.base.format.c_str());
423         return FAILURE(nullptr);
424     }
425 
426     switch (xsd::stringToAudioDevice(address.deviceType)) {
427     case xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT:
428     case xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC:
429         if (GetBoolProperty("ro.boot.audio.tinyalsa.simulate_input", false)) {
430             return createGeneratedSource(
431                 cfg, writerBufferSizeHint, frames,
432                 RepeatGenerator(generateSinePattern(cfg.base.sampleRateHz, 300.0, 1.0)));
433         } else {
434             auto sourceptr = TinyalsaSource::create(talsa::kPcmCard, talsa::kPcmDevice,
435                                                     cfg, writerBufferSizeHint, frames);
436             if (sourceptr != nullptr) {
437                 return sourceptr;
438             } else {
439                 ALOGW("%s:%d failed to create alsa source for '%s'; creating a tone source instead.",
440                       __func__, __LINE__, address.deviceType.c_str());
441             }
442         }
443         break;
444 
445     case xsd::AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX:
446         return createGeneratedSource(cfg, writerBufferSizeHint, frames,
447                                      BusySignalGenerator(cfg.base.sampleRateHz));
448 
449     case xsd::AudioDevice::AUDIO_DEVICE_IN_FM_TUNER:
450         return createGeneratedSource(
451             cfg, writerBufferSizeHint, frames,
452             RepeatGenerator(generateSinePattern(cfg.base.sampleRateHz, 440.0, 1.0)));
453 
454     default:
455         ALOGW("%s:%d unsupported device: '%s', creating a tone source",
456               __func__, __LINE__, address.deviceType.c_str());
457         break;
458     }
459 
460     return createGeneratedSource(
461         cfg, writerBufferSizeHint, frames,
462         RepeatGenerator(generateSinePattern(cfg.base.sampleRateHz, 220.0, 1.0)));
463 }
464 
validateDeviceAddress(const DeviceAddress & address)465 bool DevicePortSource::validateDeviceAddress(const DeviceAddress& address) {
466     switch (xsd::stringToAudioDevice(address.deviceType)) {
467     default:
468         ALOGW("%s:%d unsupported device: '%s'", __func__, __LINE__, address.deviceType.c_str());
469         return FAILURE(false);
470 
471     case xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT:
472     case xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC:
473     case xsd::AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX:
474     case xsd::AudioDevice::AUDIO_DEVICE_IN_FM_TUNER:
475     case xsd::AudioDevice::AUDIO_DEVICE_IN_BUS:
476         break;
477     }
478 
479     return true;
480 }
481 
482 }  // namespace implementation
483 }  // namespace CPP_VERSION
484 }  // namespace audio
485 }  // namespace hardware
486 }  // namespace android
487