• 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::__anond756d68c0111::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::__anond756d68c0111::TinyalsaSource74     ~TinyalsaSource() {
75         mProduceThreadRunning = false;
76         ALOGD("%s: joining producerThread", __func__);
77         mProduceThread.join();
78         if (mPcm) {
79             ALOGD("%s: stopping PCM stream", __func__);
80             LOG_ALWAYS_FATAL_IF(pcm_stop(mPcm.get()) != 0);
81         }
82     }
83 
getCapturePositionandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::TinyalsaSource84     Result getCapturePosition(uint64_t &frames, uint64_t &time) override {
85         const AutoMutex lock(mFrameCountersMutex);
86 
87         const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
88         const uint64_t nowFrames = getCaptureFramesLocked(nowNs);
89         mFrames += (nowFrames - mPreviousFrames);
90         mPreviousFrames = nowFrames;
91 
92         frames = mFrames;
93         time = nowNs;
94         return Result::OK;
95     }
96 
getCaptureFramesLockedandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::TinyalsaSource97     uint64_t getCaptureFramesLocked(const nsecs_t nowNs) const {
98         return uint64_t(mSampleRateHz) * ns2us(nowNs - mStartNs) / 1000000;
99     }
100 
getAvailableFramesLockedandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::TinyalsaSource101     uint64_t getAvailableFramesLocked(const nsecs_t nowNs) const {
102         return getCaptureFramesLocked(nowNs) - mSentFrames;
103     }
104 
getAvailableFramesNowLockedandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::TinyalsaSource105     uint64_t getAvailableFramesNowLocked() const {
106         return getAvailableFramesLocked(systemTime(SYSTEM_TIME_MONOTONIC));
107     }
108 
getWaitFramesNowLockedandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::TinyalsaSource109     size_t getWaitFramesNowLocked(const size_t requestedFrames) const {
110         const size_t availableFrames = getAvailableFramesNowLocked();
111         return (requestedFrames > availableFrames)
112             ? (requestedFrames - availableFrames) : 0;
113     }
114 
readandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::TinyalsaSource115     size_t read(float volume, size_t bytesToRead, IWriter &writer) override {
116         const AutoMutex lock(mFrameCountersMutex);
117 
118         const size_t waitFrames = getWaitFramesNowLocked(bytesToRead / mFrameSize);
119         const auto blockUntil =
120             std::chrono::high_resolution_clock::now() +
121                 + std::chrono::microseconds(waitFrames * 1000000 / mSampleRateHz);
122 
123         while (bytesToRead > 0) {
124             if (mRingBuffer.waitForConsumeAvailable(blockUntil
125                     + std::chrono::microseconds(kMaxJitterUs))) {
126                 if (mRingBuffer.availableToConsume() >= bytesToRead) {
127                     // Since the ring buffer has all bytes we need, make sure we
128                     // are not too early here: tinyalsa is jittery, we don't
129                     // want to go faster than SYSTEM_TIME_MONOTONIC
130                     std::this_thread::sleep_until(blockUntil);
131                 }
132 
133                 auto chunk = mRingBuffer.getConsumeChunk();
134                 const size_t writeBufSzBytes = std::min(chunk.size, bytesToRead);
135 
136                 aops::multiplyByVolume(volume,
137                                        static_cast<int16_t *>(chunk.data),
138                                        writeBufSzBytes / sizeof(int16_t));
139 
140                 writer(chunk.data, writeBufSzBytes);
141                 LOG_ALWAYS_FATAL_IF(mRingBuffer.consume(chunk, writeBufSzBytes) < writeBufSzBytes);
142 
143                 bytesToRead -= writeBufSzBytes;
144                 mSentFrames += writeBufSzBytes / mFrameSize;
145             } else {
146                 ALOGD("TinyalsaSource::%s:%d pcm_readi was late delivering "
147                       "frames, inserting %zu us of silence",
148                       __func__, __LINE__,
149                       size_t(1000000 * bytesToRead / mFrameSize / mSampleRateHz));
150 
151                 static const uint8_t zeroes[256] = {0};
152 
153                 while (bytesToRead > 0) {
154                     const size_t nZeroFrames =
155                         std::min(bytesToRead, sizeof(zeroes)) / mFrameSize;
156                     const size_t nZeroBytes = nZeroFrames * mFrameSize;
157 
158                     writer(zeroes, nZeroBytes);
159                     bytesToRead -= nZeroBytes;
160                     mSentFrames += nZeroFrames;
161                 }
162                 break;
163             }
164         }
165 
166         return mFramesLost.exchange(0);
167     }
168 
producerThreadandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::TinyalsaSource169     void producerThread() {
170         util::setThreadPriority(SP_AUDIO_SYS, PRIORITY_AUDIO);
171         std::vector<uint8_t> readBuf(mReadSizeFrames * mFrameSize);
172 
173         while (mProduceThreadRunning) {
174             const size_t bytesLost = mRingBuffer.makeRoomForProduce(readBuf.size());
175             mFramesLost += bytesLost / mFrameSize;
176 
177             auto produceChunk = mRingBuffer.getProduceChunk();
178             if (produceChunk.size < readBuf.size()) {
179                 const size_t sz = doRead(readBuf.data(), readBuf.size());
180                 if (sz > 0) {
181                     LOG_ALWAYS_FATAL_IF(mRingBuffer.produce(readBuf.data(), sz) < sz);
182                 }
183             } else {
184                 const size_t sz = doRead(produceChunk.data, readBuf.size());
185                 if (sz > 0) {
186                     LOG_ALWAYS_FATAL_IF(mRingBuffer.produce(readBuf.size()) < sz);
187                 }
188             }
189         }
190         ALOGD("%s: exiting", __func__);
191     }
192 
doReadandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::TinyalsaSource193     size_t doRead(void *dst, size_t sz) {
194         const int n = talsa::pcmRead(mPcm.get(), dst, sz, mFrameSize);
195         if (n > 0) {
196             LOG_ALWAYS_FATAL_IF(static_cast<size_t>(n) > sz,
197                                 "n=%d sz=%zu mFrameSize=%u", n, sz, mFrameSize);
198             return n;
199         } else {
200             return 0;
201         }
202     }
203 
createandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::TinyalsaSource204     static std::unique_ptr<TinyalsaSource> create(unsigned pcmCard,
205                                                   unsigned pcmDevice,
206                                                   const AudioConfig &cfg,
207                                                   size_t writerBufferSizeHint,
208                                                   uint64_t &frames) {
209         (void)writerBufferSizeHint;
210 
211         auto src = std::make_unique<TinyalsaSource>(pcmCard, pcmDevice,
212                                                     cfg, frames);
213         if (src->mMixer && src->mPcm) {
214             return src;
215         } else {
216             return FAILURE(nullptr);
217         }
218     }
219 
220 private:
221     const nsecs_t mStartNs;
222     const unsigned mSampleRateHz;
223     const unsigned mFrameSize;
224     const unsigned mReadSizeFrames;
225     uint64_t &mFrames GUARDED_BY(mFrameCountersMutex);
226     uint64_t mPreviousFrames GUARDED_BY(mFrameCountersMutex) = 0;
227     uint64_t mSentFrames GUARDED_BY(mFrameCountersMutex) = 0;
228     std::atomic<uint32_t> mFramesLost = 0;
229     RingBuffer mRingBuffer;
230     talsa::Mixer mMixer;
231     talsa::PcmPtr mPcm;
232     std::thread mProduceThread;
233     std::atomic<bool> mProduceThreadRunning = true;
234     mutable Mutex mFrameCountersMutex;
235 };
236 
237 template <class G> struct GeneratedSource : public DevicePortSource {
GeneratedSourceandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::GeneratedSource238     GeneratedSource(const AudioConfig &cfg,
239                     size_t writerBufferSizeHint,
240                     uint64_t &frames,
241                     G generator)
242             : mWriteBuffer(writerBufferSizeHint / sizeof(int16_t))
243             , mFrames(frames)
244             , mStartNs(systemTime(SYSTEM_TIME_MONOTONIC))
245             , mSampleRateHz(cfg.base.sampleRateHz)
246             , mNChannels(util::countChannels(cfg.base.channelMask))
247             , mGenerator(std::move(generator)) {}
248 
getCapturePositionandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::GeneratedSource249     Result getCapturePosition(uint64_t &frames, uint64_t &time) override {
250         const AutoMutex lock(mFrameCountersMutex);
251 
252         const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
253         const uint64_t nowFrames = getCaptureFramesLocked(nowNs);
254         mFrames += (nowFrames - mPreviousFrames);
255         mPreviousFrames = nowFrames;
256         frames = mFrames;
257         time = nowNs;
258         return Result::OK;
259     }
260 
getCaptureFramesLockedandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::GeneratedSource261     uint64_t getCaptureFramesLocked(const nsecs_t nowNs) const {
262         return uint64_t(mSampleRateHz) * ns2us(nowNs - mStartNs) / 1000000;
263     }
264 
getAvailableFramesLockedandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::GeneratedSource265     uint64_t getAvailableFramesLocked(const nsecs_t nowNs) const {
266         return getCaptureFramesLocked(nowNs) - mSentFrames;
267     }
268 
readandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::GeneratedSource269     size_t read(float volume, size_t bytesToRead, IWriter &writer) override {
270         const AutoMutex lock(mFrameCountersMutex);
271         mWriteBuffer.resize(bytesToRead / sizeof(int16_t));
272 
273         int16_t *samples = mWriteBuffer.data();
274         const unsigned nChannels = mNChannels;
275         const unsigned requestedFrames = bytesToRead / nChannels / sizeof(*samples);
276 
277         unsigned availableFrames;
278         while (true) {
279             const nsecs_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
280             availableFrames = getAvailableFramesLocked(nowNs);
281             if (availableFrames < requestedFrames / 2) {
282                 const unsigned neededMoreFrames = requestedFrames / 2 - availableFrames;
283 
284                 using namespace std::chrono_literals;
285                 std::this_thread::sleep_for(1s * neededMoreFrames / mSampleRateHz);
286             } else {
287                 break;
288             }
289         }
290 
291         const unsigned nFrames = std::min(requestedFrames, availableFrames);
292         mGenerator(samples, nFrames);
293         const size_t nSamples = nFrames * nChannels;
294         if (nChannels > 1) {
295             adjust_channels(samples, 1, samples, nChannels,
296                             sizeof(*samples), nFrames * sizeof(*samples));
297         }
298 
299         aops::multiplyByVolume(volume,
300                                mWriteBuffer.data(),
301                                nSamples);
302 
303         writer(mWriteBuffer.data(), nSamples * sizeof(*samples));
304         mSentFrames += nFrames;
305 
306         return 0;
307     }
308 
309 private:
310     std::vector<int16_t> mWriteBuffer;
311     uint64_t &mFrames GUARDED_BY(mFrameCountersMutex);
312     const nsecs_t mStartNs;
313     const unsigned mSampleRateHz;
314     const unsigned mNChannels;
315     uint64_t mPreviousFrames GUARDED_BY(mFrameCountersMutex) = 0;
316     uint64_t mSentFrames GUARDED_BY(mFrameCountersMutex) = 0;
317     G mGenerator;
318     mutable Mutex mFrameCountersMutex;
319 };
320 
convertFloatsToInt16(const std::vector<float> & pcmFloat)321 std::vector<int16_t> convertFloatsToInt16(const std::vector<float> &pcmFloat) {
322     std::vector<int16_t> pcmI16(pcmFloat.size());
323 
324     memcpy_by_audio_format(pcmI16.data(),   AUDIO_FORMAT_PCM_16_BIT,
325                            pcmFloat.data(), AUDIO_FORMAT_PCM_FLOAT,
326                            pcmFloat.size());
327 
328     return pcmI16;
329 }
330 
331 // https://en.wikipedia.org/wiki/Busy_signal
332 struct BusySignalGenerator {
BusySignalGeneratorandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::BusySignalGenerator333     explicit BusySignalGenerator(const uint32_t sampleRateHz) : mSampleRateHz(sampleRateHz) {
334         // 24/480 = 31/620, mValues must contain 50ms of audio samples
335         const size_t sz = sampleRateHz / 20;
336         std::vector<float> pcm(sz);
337         for (unsigned i = 0; i < sz; ++i) {
338             const double a = double(i) * M_PI * 2 / sampleRateHz;
339             pcm[i] = .5 * (sin(480 * a) + sin(620 * a));
340         }
341         mValues = convertFloatsToInt16(pcm);
342     }
343 
operator ()android::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::BusySignalGenerator344     void operator()(int16_t* s, size_t n) {
345         const unsigned rate = mSampleRateHz;
346         const unsigned rateHalf = rate / 2;
347         const int16_t *const vals = mValues.data();
348         const size_t valsSz = mValues.size();
349         size_t i = mI;
350 
351         while (n > 0) {
352             size_t len;
353             if (i < rateHalf) {
354                 const size_t valsOff = i % valsSz;
355                 len = std::min(n, std::min(rateHalf - i, valsSz - valsOff));
356                 memcpy(s, vals + valsOff, len * sizeof(*s));
357             } else {
358                 len = std::min(n, rate - i);
359                 memset(s, 0, len * sizeof(*s));
360             }
361             s += len;
362             i = (i + len) % rate;
363             n -= len;
364         }
365 
366         mI = i;
367     }
368 
369 private:
370     const unsigned mSampleRateHz;
371     std::vector<int16_t> mValues;
372     size_t mI = 0;
373 };
374 
375 struct RepeatGenerator {
RepeatGeneratorandroid::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::RepeatGenerator376     explicit RepeatGenerator(const std::vector<float> &pcm)
377             : mValues(convertFloatsToInt16(pcm)) {}
378 
operator ()android::hardware::audio::CPP_VERSION::implementation::__anond756d68c0111::RepeatGenerator379     void operator()(int16_t* s, size_t n) {
380         const int16_t *const vals = mValues.data();
381         const size_t valsSz = mValues.size();
382         size_t i = mI;
383 
384         while (n > 0) {
385             const size_t len = std::min(n, valsSz - i);
386             memcpy(s, vals + i, len * sizeof(*s));
387             s += len;
388             i = (i + len) % valsSz;
389             n -= len;
390         }
391 
392         mI = i;
393     }
394 
395 private:
396     const std::vector<int16_t> mValues;
397     size_t mI = 0;
398 };
399 
generateSinePattern(uint32_t sampleRateHz,double freq,double amp)400 std::vector<float> generateSinePattern(uint32_t sampleRateHz,
401                                        double freq,
402                                        double amp) {
403     std::vector<float> result(3 * sampleRateHz / freq + .5);
404 
405     for (size_t i = 0; i < result.size(); ++i) {
406         const double a = double(i) * M_PI * 2 / sampleRateHz;
407         result[i] = amp * sin(a * freq);
408     }
409 
410     return result;
411 }
412 
413 template <class G> std::unique_ptr<GeneratedSource<G>>
createGeneratedSource(const AudioConfig & cfg,size_t writerBufferSizeHint,uint64_t & frames,G generator)414 createGeneratedSource(const AudioConfig &cfg,
415                       size_t writerBufferSizeHint,
416                       uint64_t &frames,
417                       G generator) {
418     return std::make_unique<GeneratedSource<G>>(cfg,
419                                                 writerBufferSizeHint,
420                                                 frames,
421                                                 std::move(generator));
422 }
423 
424 }  // namespace
425 
426 std::unique_ptr<DevicePortSource>
create(size_t writerBufferSizeHint,const DeviceAddress & address,const AudioConfig & cfg,const hidl_vec<AudioInOutFlag> & flags,uint64_t & frames)427 DevicePortSource::create(size_t writerBufferSizeHint,
428                          const DeviceAddress &address,
429                          const AudioConfig &cfg,
430                          const hidl_vec<AudioInOutFlag> &flags,
431                          uint64_t &frames) {
432     (void)flags;
433 
434     if (xsd::stringToAudioFormat(cfg.base.format) != xsd::AudioFormat::AUDIO_FORMAT_PCM_16_BIT) {
435         ALOGE("%s:%d, unexpected format: '%s'", __func__, __LINE__, cfg.base.format.c_str());
436         return FAILURE(nullptr);
437     }
438 
439     switch (xsd::stringToAudioDevice(address.deviceType)) {
440     case xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT:
441     case xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC:
442         if (GetBoolProperty("ro.boot.audio.tinyalsa.simulate_input", false)) {
443             return createGeneratedSource(
444                 cfg, writerBufferSizeHint, frames,
445                 RepeatGenerator(generateSinePattern(cfg.base.sampleRateHz, 300.0, 1.0)));
446         } else {
447             auto sourceptr = TinyalsaSource::create(talsa::kPcmCard, talsa::kPcmDevice,
448                                                     cfg, writerBufferSizeHint, frames);
449             if (sourceptr != nullptr) {
450                 return sourceptr;
451             } else {
452                 ALOGW("%s:%d failed to create alsa source for '%s'; creating a tone source instead.",
453                       __func__, __LINE__, address.deviceType.c_str());
454             }
455         }
456         break;
457 
458     case xsd::AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX:
459         return createGeneratedSource(cfg, writerBufferSizeHint, frames,
460                                      BusySignalGenerator(cfg.base.sampleRateHz));
461 
462     case xsd::AudioDevice::AUDIO_DEVICE_IN_FM_TUNER:
463         return createGeneratedSource(
464             cfg, writerBufferSizeHint, frames,
465             RepeatGenerator(generateSinePattern(cfg.base.sampleRateHz, 440.0, 1.0)));
466 
467     default:
468         ALOGW("%s:%d unsupported device: '%s', creating a tone source",
469               __func__, __LINE__, address.deviceType.c_str());
470         break;
471     }
472 
473     return createGeneratedSource(
474         cfg, writerBufferSizeHint, frames,
475         RepeatGenerator(generateSinePattern(cfg.base.sampleRateHz, 220.0, 1.0)));
476 }
477 
validateDeviceAddress(const DeviceAddress & address)478 bool DevicePortSource::validateDeviceAddress(const DeviceAddress& address) {
479     switch (xsd::stringToAudioDevice(address.deviceType)) {
480     default:
481         ALOGW("%s:%d unsupported device: '%s'", __func__, __LINE__, address.deviceType.c_str());
482         return FAILURE(false);
483 
484     case xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT:
485     case xsd::AudioDevice::AUDIO_DEVICE_IN_BUILTIN_MIC:
486     case xsd::AudioDevice::AUDIO_DEVICE_IN_TELEPHONY_RX:
487     case xsd::AudioDevice::AUDIO_DEVICE_IN_FM_TUNER:
488     case xsd::AudioDevice::AUDIO_DEVICE_IN_BUS:
489         break;
490     }
491 
492     return true;
493 }
494 
495 }  // namespace implementation
496 }  // namespace CPP_VERSION
497 }  // namespace audio
498 }  // namespace hardware
499 }  // namespace android
500