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