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