1 /*
2 * Copyright (C) 2021 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "AudioTestUtils"
19
20 #include <android-base/file.h>
21 #include <system/audio_config.h>
22 #include <utils/Log.h>
23
24 #include "audio_test_utils.h"
25
26 #define WAIT_PERIOD_MS 10 // from AudioTrack.cpp
27 #define MAX_WAIT_TIME_MS 5000
28
29 template <class T>
30 constexpr void (*xmlDeleter)(T* t);
31 template <>
32 constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;
33 template <>
__anon895eedb40102(xmlChar* s) 34 constexpr auto xmlDeleter<xmlChar> = [](xmlChar* s) { xmlFree(s); };
35
36 /** @return a unique_ptr with the correct deleter for the libxml2 object. */
37 template <class T>
make_xmlUnique(T * t)38 constexpr auto make_xmlUnique(T* t) {
39 // Wrap deleter in lambda to enable empty base optimization
40 auto deleter = [](T* t) { xmlDeleter<T>(t); };
41 return std::unique_ptr<T, decltype(deleter)>{t, deleter};
42 }
43
onAudioDeviceUpdate(audio_io_handle_t audioIo,audio_port_handle_t deviceId)44 void OnAudioDeviceUpdateNotifier::onAudioDeviceUpdate(audio_io_handle_t audioIo,
45 audio_port_handle_t deviceId) {
46 std::unique_lock<std::mutex> lock{mMutex};
47 ALOGD("%s audioIo=%d deviceId=%d", __func__, audioIo, deviceId);
48 mAudioIo = audioIo;
49 mDeviceId = deviceId;
50 mCondition.notify_all();
51 }
52
waitForAudioDeviceCb(audio_port_handle_t expDeviceId)53 status_t OnAudioDeviceUpdateNotifier::waitForAudioDeviceCb(audio_port_handle_t expDeviceId) {
54 std::unique_lock<std::mutex> lock{mMutex};
55 if (mAudioIo == AUDIO_IO_HANDLE_NONE ||
56 (expDeviceId != AUDIO_PORT_HANDLE_NONE && expDeviceId != mDeviceId)) {
57 mCondition.wait_for(lock, std::chrono::milliseconds(500));
58 if (mAudioIo == AUDIO_IO_HANDLE_NONE ||
59 (expDeviceId != AUDIO_PORT_HANDLE_NONE && expDeviceId != mDeviceId))
60 return TIMED_OUT;
61 }
62 return OK;
63 }
64
AudioPlayback(uint32_t sampleRate,audio_format_t format,audio_channel_mask_t channelMask,audio_output_flags_t flags,audio_session_t sessionId,AudioTrack::transfer_type transferType,audio_attributes_t * attributes,audio_offload_info_t * info)65 AudioPlayback::AudioPlayback(uint32_t sampleRate, audio_format_t format,
66 audio_channel_mask_t channelMask, audio_output_flags_t flags,
67 audio_session_t sessionId, AudioTrack::transfer_type transferType,
68 audio_attributes_t* attributes, audio_offload_info_t* info)
69 : mSampleRate(sampleRate),
70 mFormat(format),
71 mChannelMask(channelMask),
72 mFlags(flags),
73 mSessionId(sessionId),
74 mTransferType(transferType),
75 mAttributes(attributes),
76 mOffloadInfo(info) {
77 mStopPlaying = false;
78 mBytesUsedSoFar = 0;
79 mState = PLAY_NO_INIT;
80 mMemCapacity = 0;
81 mMemoryDealer = nullptr;
82 mMemory = nullptr;
83 }
84
~AudioPlayback()85 AudioPlayback::~AudioPlayback() {
86 stop();
87 }
88
create()89 status_t AudioPlayback::create() {
90 if (mState != PLAY_NO_INIT) return INVALID_OPERATION;
91 std::string packageName{"AudioPlayback"};
92 AttributionSourceState attributionSource;
93 attributionSource.packageName = packageName;
94 attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
95 attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
96 attributionSource.token = sp<BBinder>::make();
97 if (mTransferType == AudioTrack::TRANSFER_OBTAIN) {
98 mTrack = new AudioTrack(attributionSource);
99 mTrack->set(AUDIO_STREAM_MUSIC, mSampleRate, mFormat, mChannelMask, 0 /* frameCount */,
100 mFlags, nullptr /* callback */, 0 /* notificationFrames */,
101 nullptr /* sharedBuffer */, false /*canCallJava */, mSessionId, mTransferType,
102 mOffloadInfo, attributionSource, mAttributes);
103 } else if (mTransferType == AudioTrack::TRANSFER_SHARED) {
104 mTrack = new AudioTrack(AUDIO_STREAM_MUSIC, mSampleRate, mFormat, mChannelMask, mMemory,
105 mFlags, wp<AudioTrack::IAudioTrackCallback>::fromExisting(this), 0,
106 mSessionId, mTransferType, nullptr, attributionSource, mAttributes);
107 } else {
108 ALOGE("Test application is not handling transfer type %s",
109 AudioTrack::convertTransferToText(mTransferType));
110 return INVALID_OPERATION;
111 }
112 mTrack->setCallerName(packageName);
113 status_t status = mTrack->initCheck();
114 if (NO_ERROR == status) mState = PLAY_READY;
115 return status;
116 }
117
loadResource(const char * name)118 status_t AudioPlayback::loadResource(const char* name) {
119 status_t status = OK;
120 FILE* fp = fopen(name, "rbe");
121 struct stat buf {};
122 if (fp && !fstat(fileno(fp), &buf)) {
123 mMemCapacity = buf.st_size;
124 mMemoryDealer = new MemoryDealer(mMemCapacity, "AudioPlayback");
125 if (nullptr == mMemoryDealer.get()) {
126 ALOGE("couldn't get MemoryDealer!");
127 fclose(fp);
128 return NO_MEMORY;
129 }
130 mMemory = mMemoryDealer->allocate(mMemCapacity);
131 if (nullptr == mMemory.get()) {
132 ALOGE("couldn't get IMemory!");
133 fclose(fp);
134 return NO_MEMORY;
135 }
136 uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mMemory->unsecurePointer()));
137 fread(ipBuffer, sizeof(uint8_t), mMemCapacity, fp);
138 } else {
139 ALOGE("unable to open input file %s", name);
140 status = NAME_NOT_FOUND;
141 }
142 if (fp) fclose(fp);
143 return status;
144 }
145
getAudioTrackHandle()146 sp<AudioTrack> AudioPlayback::getAudioTrackHandle() {
147 return (PLAY_NO_INIT != mState) ? mTrack : nullptr;
148 }
149
start()150 status_t AudioPlayback::start() {
151 status_t status;
152 if (PLAY_READY != mState) {
153 return INVALID_OPERATION;
154 } else {
155 status = mTrack->start();
156 if (OK == status) {
157 mState = PLAY_STARTED;
158 LOG_FATAL_IF(false != mTrack->stopped());
159 }
160 }
161 return status;
162 }
163
onBufferEnd()164 void AudioPlayback::onBufferEnd() {
165 std::unique_lock<std::mutex> lock{mMutex};
166 mStopPlaying = true;
167 mCondition.notify_all();
168 }
169
fillBuffer()170 status_t AudioPlayback::fillBuffer() {
171 if (PLAY_STARTED != mState) return INVALID_OPERATION;
172 const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
173 int counter = 0;
174 uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mMemory->unsecurePointer()));
175 size_t nonContig = 0;
176 size_t bytesAvailable = mMemCapacity - mBytesUsedSoFar;
177 while (bytesAvailable > 0) {
178 AudioTrack::Buffer trackBuffer;
179 trackBuffer.frameCount = mTrack->frameCount() * 2;
180 status_t status = mTrack->obtainBuffer(&trackBuffer, 1, &nonContig);
181 if (OK == status) {
182 size_t bytesToCopy = std::min(bytesAvailable, trackBuffer.size());
183 if (bytesToCopy > 0) {
184 memcpy(trackBuffer.data(), ipBuffer + mBytesUsedSoFar, bytesToCopy);
185 }
186 mTrack->releaseBuffer(&trackBuffer);
187 mBytesUsedSoFar += bytesToCopy;
188 bytesAvailable = mMemCapacity - mBytesUsedSoFar;
189 counter = 0;
190 } else if (WOULD_BLOCK == status) {
191 // if not received a buffer for MAX_WAIT_TIME_MS, something has gone wrong
192 if (counter == maxTries) return TIMED_OUT;
193 counter++;
194 }
195 }
196 return OK;
197 }
198
waitForConsumption(bool testSeek)199 status_t AudioPlayback::waitForConsumption(bool testSeek) {
200 if (PLAY_STARTED != mState) return INVALID_OPERATION;
201
202 const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
203 int counter = 0;
204 size_t totalFrameCount = mMemCapacity / mTrack->frameSize();
205 while (!mStopPlaying && counter < maxTries) {
206 uint32_t currPosition;
207 mTrack->getPosition(&currPosition);
208 if (currPosition >= totalFrameCount) counter++;
209
210 if (testSeek && (currPosition > totalFrameCount * 0.6)) {
211 testSeek = false;
212 if (!mTrack->hasStarted()) return BAD_VALUE;
213 mTrack->pauseAndWait(std::chrono::seconds(2));
214 if (mTrack->hasStarted()) return BAD_VALUE;
215 mTrack->reload();
216 mTrack->getPosition(&currPosition);
217 if (currPosition != 0) return BAD_VALUE;
218 mTrack->start();
219 while (currPosition < totalFrameCount * 0.3) {
220 mTrack->getPosition(&currPosition);
221 }
222 mTrack->pauseAndWait(std::chrono::seconds(2));
223 uint32_t setPosition = totalFrameCount * 0.9;
224 mTrack->setPosition(setPosition);
225 uint32_t bufferPosition;
226 mTrack->getBufferPosition(&bufferPosition);
227 if (bufferPosition != setPosition) return BAD_VALUE;
228 mTrack->start();
229 }
230 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_PERIOD_MS));
231 }
232 if (!mStopPlaying && counter == maxTries) return TIMED_OUT;
233 return OK;
234 }
235
onProcess(bool testSeek)236 status_t AudioPlayback::onProcess(bool testSeek) {
237 if (mTransferType == AudioTrack::TRANSFER_SHARED)
238 return waitForConsumption(testSeek);
239 else if (mTransferType == AudioTrack::TRANSFER_OBTAIN)
240 return fillBuffer();
241 else
242 return INVALID_OPERATION;
243 }
244
stop()245 void AudioPlayback::stop() {
246 std::unique_lock<std::mutex> lock{mMutex};
247 mStopPlaying = true;
248 if (mState != PLAY_STOPPED && mState != PLAY_NO_INIT) {
249 int32_t msec = 0;
250 (void)mTrack->pendingDuration(&msec);
251 mTrack->stopAndJoinCallbacks();
252 LOG_FATAL_IF(true != mTrack->stopped());
253 mState = PLAY_STOPPED;
254 if (msec > 0) {
255 ALOGD("deleting recycled track, waiting for data drain (%d msec)", msec);
256 usleep(msec * 1000LL);
257 }
258 }
259 }
260
261 // hold pcm data sent by AudioRecord
RawBuffer(int64_t ptsPipeline,int64_t ptsManual,int32_t capacity)262 RawBuffer::RawBuffer(int64_t ptsPipeline, int64_t ptsManual, int32_t capacity)
263 : mData(capacity > 0 ? new uint8_t[capacity] : nullptr),
264 mPtsPipeline(ptsPipeline),
265 mPtsManual(ptsManual),
266 mCapacity(capacity) {}
267
268 // Simple AudioCapture
onMoreData(const AudioRecord::Buffer & buffer)269 size_t AudioCapture::onMoreData(const AudioRecord::Buffer& buffer) {
270 if (mState != REC_STARTED) {
271 ALOGE("Unexpected Callback from audiorecord, not reading data");
272 return 0;
273 }
274
275 // no more frames to read
276 if (mNumFramesReceived >= mNumFramesToRecord || mStopRecording) {
277 mStopRecording = true;
278 return 0;
279 }
280
281 int64_t timeUs = 0, position = 0, timeNs = 0;
282 ExtendedTimestamp ts;
283 ExtendedTimestamp::Location location;
284 const int32_t usPerSec = 1000000;
285
286 if (mRecord->getTimestamp(&ts) == OK &&
287 ts.getBestTimestamp(&position, &timeNs, ExtendedTimestamp::TIMEBASE_MONOTONIC, &location) ==
288 OK) {
289 // Use audio timestamp.
290 timeUs = timeNs / 1000 -
291 (position - mNumFramesReceived + mNumFramesLost) * usPerSec / mSampleRate;
292 } else {
293 // This should not happen in normal case.
294 ALOGW("Failed to get audio timestamp, fallback to use systemclock");
295 timeUs = systemTime() / 1000LL;
296 // Estimate the real sampling time of the 1st sample in this buffer
297 // from AudioRecord's latency. (Apply this adjustment first so that
298 // the start time logic is not affected.)
299 timeUs -= mRecord->latency() * 1000LL;
300 }
301
302 ALOGV("dataCallbackTimestamp: %" PRId64 " us", timeUs);
303
304 const size_t frameSize = mRecord->frameSize();
305 uint64_t numLostBytes = (uint64_t)mRecord->getInputFramesLost() * frameSize;
306 if (numLostBytes > 0) {
307 ALOGW("Lost audio record data: %" PRIu64 " bytes", numLostBytes);
308 }
309 std::deque<RawBuffer> tmpQueue;
310 while (numLostBytes > 0) {
311 uint64_t bufferSize = numLostBytes;
312 if (numLostBytes > mMaxBytesPerCallback) {
313 numLostBytes -= mMaxBytesPerCallback;
314 bufferSize = mMaxBytesPerCallback;
315 } else {
316 numLostBytes = 0;
317 }
318 const int64_t timestampUs =
319 ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
320 mRecord->getSampleRate();
321 RawBuffer emptyBuffer{timeUs, timestampUs, static_cast<int32_t>(bufferSize)};
322 memset(emptyBuffer.mData.get(), 0, bufferSize);
323 mNumFramesLost += bufferSize / frameSize;
324 mNumFramesReceived += bufferSize / frameSize;
325 tmpQueue.push_back(std::move(emptyBuffer));
326 }
327
328 if (buffer.size() == 0) {
329 ALOGW("Nothing is available from AudioRecord callback buffer");
330 } else {
331 const size_t bufferSize = buffer.size();
332 const int64_t timestampUs =
333 ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
334 mRecord->getSampleRate();
335 RawBuffer audioBuffer{timeUs, timestampUs, static_cast<int32_t>(bufferSize)};
336 memcpy(audioBuffer.mData.get(), buffer.data(), bufferSize);
337 mNumFramesReceived += bufferSize / frameSize;
338 tmpQueue.push_back(std::move(audioBuffer));
339 }
340
341 if (tmpQueue.size() > 0) {
342 std::unique_lock<std::mutex> lock{mMutex};
343 for (auto it = tmpQueue.begin(); it != tmpQueue.end(); it++)
344 mBuffersReceived.push_back(std::move(*it));
345 mCondition.notify_all();
346 }
347 return buffer.size();
348 }
349
onOverrun()350 void AudioCapture::onOverrun() {
351 ALOGV("received event overrun");
352 mBufferOverrun = true;
353 }
354
onMarker(uint32_t markerPosition)355 void AudioCapture::onMarker(uint32_t markerPosition) {
356 ALOGV("received Callback at position %d", markerPosition);
357 mReceivedCbMarkerAtPosition = markerPosition;
358 }
359
onNewPos(uint32_t markerPosition)360 void AudioCapture::onNewPos(uint32_t markerPosition) {
361 ALOGV("received Callback at position %d", markerPosition);
362 mReceivedCbMarkerCount++;
363 }
364
onNewIAudioRecord()365 void AudioCapture::onNewIAudioRecord() {
366 ALOGV("IAudioRecord is re-created");
367 }
368
AudioCapture(audio_source_t inputSource,uint32_t sampleRate,audio_format_t format,audio_channel_mask_t channelMask,audio_input_flags_t flags,audio_session_t sessionId,AudioRecord::transfer_type transferType,const audio_attributes_t * attributes)369 AudioCapture::AudioCapture(audio_source_t inputSource, uint32_t sampleRate, audio_format_t format,
370 audio_channel_mask_t channelMask, audio_input_flags_t flags,
371 audio_session_t sessionId, AudioRecord::transfer_type transferType,
372 const audio_attributes_t* attributes)
373 : mInputSource(inputSource),
374 mSampleRate(sampleRate),
375 mFormat(format),
376 mChannelMask(channelMask),
377 mFlags(flags),
378 mSessionId(sessionId),
379 mTransferType(transferType),
380 mAttributes(attributes) {
381 mFrameCount = 0;
382 mNotificationFrames = 0;
383 mNumFramesToRecord = 0;
384 mNumFramesReceived = 0;
385 mNumFramesLost = 0;
386 mBufferOverrun = false;
387 mMarkerPosition = 0;
388 mMarkerPeriod = 0;
389 mReceivedCbMarkerAtPosition = -1;
390 mReceivedCbMarkerCount = 0;
391 mState = REC_NO_INIT;
392 mStopRecording = false;
393 }
394
~AudioCapture()395 AudioCapture::~AudioCapture() {
396 if (mOutFileFd > 0) close(mOutFileFd);
397 stop();
398 }
399
create()400 status_t AudioCapture::create() {
401 if (mState != REC_NO_INIT) return INVALID_OPERATION;
402 // get Min Frame Count
403 size_t minFrameCount;
404 status_t status =
405 AudioRecord::getMinFrameCount(&minFrameCount, mSampleRate, mFormat, mChannelMask);
406 if (NO_ERROR != status) return status;
407 // Limit notificationFrames basing on client bufferSize
408 const int samplesPerFrame = audio_channel_count_from_in_mask(mChannelMask);
409 const int bytesPerSample = audio_bytes_per_sample(mFormat);
410 mNotificationFrames = mMaxBytesPerCallback / (samplesPerFrame * bytesPerSample);
411 // select frameCount to be at least minFrameCount
412 mFrameCount = 2 * mNotificationFrames;
413 while (mFrameCount < minFrameCount) {
414 mFrameCount += mNotificationFrames;
415 }
416 if (mFlags & AUDIO_INPUT_FLAG_FAST) {
417 ALOGW("Overriding all previous computations");
418 mFrameCount = 0;
419 mNotificationFrames = 0;
420 }
421 mNumFramesToRecord = (mSampleRate * 0.25); // record .25 sec
422 std::string packageName{"AudioCapture"};
423 AttributionSourceState attributionSource;
424 attributionSource.packageName = packageName;
425 attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
426 attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
427 attributionSource.token = sp<BBinder>::make();
428 if (mTransferType == AudioRecord::TRANSFER_OBTAIN) {
429 if (mSampleRate == 48000) { // test all available constructors
430 mRecord = new AudioRecord(mInputSource, mSampleRate, mFormat, mChannelMask,
431 attributionSource, mFrameCount, nullptr /* callback */,
432 mNotificationFrames, mSessionId, mTransferType, mFlags,
433 mAttributes);
434 } else {
435 mRecord = new AudioRecord(attributionSource);
436 status = mRecord->set(mInputSource, mSampleRate, mFormat, mChannelMask, mFrameCount,
437 nullptr /* callback */, 0 /* notificationFrames */,
438 false /* canCallJava */, mSessionId, mTransferType, mFlags,
439 attributionSource.uid, attributionSource.pid, mAttributes);
440 }
441 if (NO_ERROR != status) return status;
442 } else if (mTransferType == AudioRecord::TRANSFER_CALLBACK) {
443 mRecord = new AudioRecord(mInputSource, mSampleRate, mFormat, mChannelMask,
444 attributionSource, mFrameCount, this, mNotificationFrames,
445 mSessionId, mTransferType, mFlags, mAttributes);
446 } else {
447 ALOGE("Test application is not handling transfer type %s",
448 AudioRecord::convertTransferToText(mTransferType));
449 return NO_INIT;
450 }
451 mRecord->setCallerName(packageName);
452 status = mRecord->initCheck();
453 if (NO_ERROR == status) mState = REC_READY;
454 if (mFlags & AUDIO_INPUT_FLAG_FAST) {
455 mFrameCount = mRecord->frameCount();
456 mNotificationFrames = mRecord->getNotificationPeriodInFrames();
457 mMaxBytesPerCallback = mNotificationFrames * samplesPerFrame * bytesPerSample;
458 }
459 return status;
460 }
461
setRecordDuration(float durationInSec)462 status_t AudioCapture::setRecordDuration(float durationInSec) {
463 if (REC_READY != mState) {
464 return INVALID_OPERATION;
465 }
466 uint32_t sampleRate = mSampleRate == 0 ? mRecord->getSampleRate() : mSampleRate;
467 mNumFramesToRecord = (sampleRate * durationInSec);
468 return OK;
469 }
470
enableRecordDump()471 status_t AudioCapture::enableRecordDump() {
472 if (mOutFileFd != -1) {
473 return INVALID_OPERATION;
474 }
475 TemporaryFile tf("/data/local/tmp");
476 tf.DoNotRemove();
477 mOutFileFd = tf.release();
478 mFileName = std::string{tf.path};
479 return OK;
480 }
481
getAudioRecordHandle()482 sp<AudioRecord> AudioCapture::getAudioRecordHandle() {
483 return (REC_NO_INIT == mState) ? nullptr : mRecord;
484 }
485
start(AudioSystem::sync_event_t event,audio_session_t triggerSession)486 status_t AudioCapture::start(AudioSystem::sync_event_t event, audio_session_t triggerSession) {
487 status_t status;
488 if (REC_READY != mState) {
489 return INVALID_OPERATION;
490 } else {
491 status = mRecord->start(event, triggerSession);
492 if (OK == status) {
493 mState = REC_STARTED;
494 LOG_FATAL_IF(false != mRecord->stopped());
495 }
496 }
497 return status;
498 }
499
stop()500 status_t AudioCapture::stop() {
501 status_t status = OK;
502 mStopRecording = true;
503 if (mState != REC_STOPPED && mState != REC_NO_INIT) {
504 if (mInputSource != AUDIO_SOURCE_DEFAULT) {
505 bool state = false;
506 status = AudioSystem::isSourceActive(mInputSource, &state);
507 if (status == OK && !state) status = BAD_VALUE;
508 }
509 mRecord->stopAndJoinCallbacks();
510 mState = REC_STOPPED;
511 LOG_FATAL_IF(true != mRecord->stopped());
512 }
513 return status;
514 }
515
obtainBuffer(RawBuffer & buffer)516 status_t AudioCapture::obtainBuffer(RawBuffer& buffer) {
517 if (REC_STARTED != mState) return INVALID_OPERATION;
518 const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
519 int counter = 0;
520 size_t nonContig = 0;
521 while (mNumFramesReceived < mNumFramesToRecord) {
522 AudioRecord::Buffer recordBuffer;
523 recordBuffer.frameCount = mNotificationFrames;
524 status_t status = mRecord->obtainBuffer(&recordBuffer, 1, &nonContig);
525 if (OK == status) {
526 const int64_t timestampUs =
527 ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
528 mRecord->getSampleRate();
529 RawBuffer buff{-1, timestampUs, static_cast<int32_t>(recordBuffer.size())};
530 memcpy(buff.mData.get(), recordBuffer.data(), recordBuffer.size());
531 buffer = std::move(buff);
532 mNumFramesReceived += recordBuffer.size() / mRecord->frameSize();
533 mRecord->releaseBuffer(&recordBuffer);
534 counter = 0;
535 } else if (WOULD_BLOCK == status) {
536 // if not received a buffer for MAX_WAIT_TIME_MS, something has gone wrong
537 if (counter == maxTries) return TIMED_OUT;
538 counter++;
539 }
540 }
541 return OK;
542 }
543
obtainBufferCb(RawBuffer & buffer)544 status_t AudioCapture::obtainBufferCb(RawBuffer& buffer) {
545 if (REC_STARTED != mState) return INVALID_OPERATION;
546 const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
547 int counter = 0;
548 std::unique_lock<std::mutex> lock{mMutex};
549 while (mBuffersReceived.empty() && !mStopRecording && counter < maxTries) {
550 mCondition.wait_for(lock, std::chrono::milliseconds(WAIT_PERIOD_MS));
551 counter++;
552 }
553 if (!mBuffersReceived.empty()) {
554 auto it = mBuffersReceived.begin();
555 buffer = std::move(*it);
556 mBuffersReceived.erase(it);
557 } else {
558 if (!mStopRecording && counter == maxTries) return TIMED_OUT;
559 }
560 return OK;
561 }
562
audioProcess()563 status_t AudioCapture::audioProcess() {
564 RawBuffer buffer;
565 status_t status = OK;
566 while (mNumFramesReceived < mNumFramesToRecord && status == OK) {
567 if (mTransferType == AudioRecord::TRANSFER_CALLBACK)
568 status = obtainBufferCb(buffer);
569 else
570 status = obtainBuffer(buffer);
571 if (OK == status && mOutFileFd > 0) {
572 const char* ptr = static_cast<const char*>(static_cast<void*>(buffer.mData.get()));
573 write(mOutFileFd, ptr, buffer.mCapacity);
574 }
575 }
576 return OK;
577 }
578
listAudioPorts(std::vector<audio_port_v7> & portsVec)579 status_t listAudioPorts(std::vector<audio_port_v7>& portsVec) {
580 int attempts = 5;
581 status_t status;
582 unsigned int generation1, generation;
583 unsigned int numPorts = 0;
584 do {
585 if (attempts-- < 0) {
586 status = TIMED_OUT;
587 break;
588 }
589 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts,
590 nullptr, &generation1);
591 if (status != NO_ERROR) {
592 ALOGE("AudioSystem::listAudioPorts returned error %d", status);
593 break;
594 }
595 portsVec.resize(numPorts);
596 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts,
597 portsVec.data(), &generation);
598 } while (generation1 != generation && status == NO_ERROR);
599 if (status != NO_ERROR) {
600 numPorts = 0;
601 portsVec.clear();
602 }
603 return status;
604 }
605
getPortById(const audio_port_handle_t portId,audio_port_v7 & port)606 status_t getPortById(const audio_port_handle_t portId, audio_port_v7& port) {
607 std::vector<struct audio_port_v7> ports;
608 status_t status = listAudioPorts(ports);
609 if (status != OK) return status;
610 for (auto i = 0; i < ports.size(); i++) {
611 if (ports[i].id == portId) {
612 port = ports[i];
613 return OK;
614 }
615 }
616 return BAD_VALUE;
617 }
618
getPortByAttributes(audio_port_role_t role,audio_port_type_t type,audio_devices_t deviceType,const std::string & address,audio_port_v7 & port)619 status_t getPortByAttributes(audio_port_role_t role, audio_port_type_t type,
620 audio_devices_t deviceType, const std::string& address,
621 audio_port_v7& port) {
622 std::vector<struct audio_port_v7> ports;
623 status_t status = listAudioPorts(ports);
624 if (status != OK) return status;
625 for (auto i = 0; i < ports.size(); i++) {
626 if (ports[i].role == role && ports[i].type == type &&
627 ports[i].ext.device.type == deviceType &&
628 !strncmp(ports[i].ext.device.address, address.c_str(), AUDIO_DEVICE_MAX_ADDRESS_LEN)) {
629 port = ports[i];
630 return OK;
631 }
632 }
633 return BAD_VALUE;
634 }
635
listAudioPatches(std::vector<struct audio_patch> & patchesVec)636 status_t listAudioPatches(std::vector<struct audio_patch>& patchesVec) {
637 int attempts = 5;
638 status_t status;
639 unsigned int generation1, generation;
640 unsigned int numPatches = 0;
641 do {
642 if (attempts-- < 0) {
643 status = TIMED_OUT;
644 break;
645 }
646 status = AudioSystem::listAudioPatches(&numPatches, nullptr, &generation1);
647 if (status != NO_ERROR) {
648 ALOGE("AudioSystem::listAudioPatches returned error %d", status);
649 break;
650 }
651 patchesVec.resize(numPatches);
652 status = AudioSystem::listAudioPatches(&numPatches, patchesVec.data(), &generation);
653 } while (generation1 != generation && status == NO_ERROR);
654 if (status != NO_ERROR) {
655 numPatches = 0;
656 patchesVec.clear();
657 }
658 return status;
659 }
660
getPatchForOutputMix(audio_io_handle_t audioIo,audio_patch & patch)661 status_t getPatchForOutputMix(audio_io_handle_t audioIo, audio_patch& patch) {
662 std::vector<struct audio_patch> patches;
663 status_t status = listAudioPatches(patches);
664 if (status != OK) return status;
665
666 for (auto i = 0; i < patches.size(); i++) {
667 for (auto j = 0; j < patches[i].num_sources; j++) {
668 if (patches[i].sources[j].type == AUDIO_PORT_TYPE_MIX &&
669 patches[i].sources[j].ext.mix.handle == audioIo) {
670 patch = patches[i];
671 return OK;
672 }
673 }
674 }
675 return BAD_VALUE;
676 }
677
getPatchForInputMix(audio_io_handle_t audioIo,audio_patch & patch)678 status_t getPatchForInputMix(audio_io_handle_t audioIo, audio_patch& patch) {
679 std::vector<struct audio_patch> patches;
680 status_t status = listAudioPatches(patches);
681 if (status != OK) return status;
682
683 for (auto i = 0; i < patches.size(); i++) {
684 for (auto j = 0; j < patches[i].num_sinks; j++) {
685 if (patches[i].sinks[j].type == AUDIO_PORT_TYPE_MIX &&
686 patches[i].sinks[j].ext.mix.handle == audioIo) {
687 patch = patches[i];
688 return OK;
689 }
690 }
691 }
692 return BAD_VALUE;
693 }
694
patchContainsOutputDevice(audio_port_handle_t deviceId,audio_patch patch)695 bool patchContainsOutputDevice(audio_port_handle_t deviceId, audio_patch patch) {
696 for (auto j = 0; j < patch.num_sinks; j++) {
697 if (patch.sinks[j].type == AUDIO_PORT_TYPE_DEVICE && patch.sinks[j].id == deviceId) {
698 return true;
699 }
700 }
701 return false;
702 }
703
patchContainsInputDevice(audio_port_handle_t deviceId,audio_patch patch)704 bool patchContainsInputDevice(audio_port_handle_t deviceId, audio_patch patch) {
705 for (auto j = 0; j < patch.num_sources; j++) {
706 if (patch.sources[j].type == AUDIO_PORT_TYPE_DEVICE && patch.sources[j].id == deviceId) {
707 return true;
708 }
709 }
710 return false;
711 }
712
checkPatchPlayback(audio_io_handle_t audioIo,audio_port_handle_t deviceId)713 bool checkPatchPlayback(audio_io_handle_t audioIo, audio_port_handle_t deviceId) {
714 struct audio_patch patch;
715 if (getPatchForOutputMix(audioIo, patch) == OK) {
716 return patchContainsOutputDevice(deviceId, patch);
717 }
718 return false;
719 }
720
checkPatchCapture(audio_io_handle_t audioIo,audio_port_handle_t deviceId)721 bool checkPatchCapture(audio_io_handle_t audioIo, audio_port_handle_t deviceId) {
722 struct audio_patch patch;
723 if (getPatchForInputMix(audioIo, patch) == OK) {
724 return patchContainsInputDevice(deviceId, patch);
725 }
726 return false;
727 }
728
dumpPortConfig(const audio_port_config & port)729 std::string dumpPortConfig(const audio_port_config& port) {
730 std::ostringstream result;
731 std::string deviceInfo;
732 if (port.type == AUDIO_PORT_TYPE_DEVICE) {
733 if (port.ext.device.type & AUDIO_DEVICE_BIT_IN) {
734 InputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
735 } else {
736 OutputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
737 }
738 deviceInfo += std::string(", address = ") + port.ext.device.address;
739 }
740 result << "audio_port_handle_t = " << port.id << ", "
741 << "Role = " << (port.role == AUDIO_PORT_ROLE_SOURCE ? "source" : "sink") << ", "
742 << "Type = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix") << ", "
743 << "deviceInfo = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? deviceInfo : "") << ", "
744 << "config_mask = 0x" << std::hex << port.config_mask << std::dec << ", ";
745 if (port.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
746 result << "sample rate = " << port.sample_rate << ", ";
747 }
748 if (port.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
749 result << "channel mask = " << port.channel_mask << ", ";
750 }
751 if (port.config_mask & AUDIO_PORT_CONFIG_FORMAT) {
752 result << "format = " << port.format << ", ";
753 }
754 result << "input flags = " << port.flags.input << ", ";
755 result << "output flags = " << port.flags.output << ", ";
756 result << "mix io handle = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? 0 : port.ext.mix.handle)
757 << "\n";
758 return result.str();
759 }
760
dumpPatch(const audio_patch & patch)761 std::string dumpPatch(const audio_patch& patch) {
762 std::ostringstream result;
763 result << "----------------- Dumping Patch ------------ \n";
764 result << "Patch Handle: " << patch.id << ", sources: " << patch.num_sources
765 << ", sink: " << patch.num_sinks << "\n";
766 audio_port_v7 port;
767 for (uint32_t i = 0; i < patch.num_sources; i++) {
768 result << "----------------- Dumping Source Port Config @ index " << i
769 << " ------------ \n";
770 result << dumpPortConfig(patch.sources[i]);
771 result << "----------------- Dumping Source Port for id " << patch.sources[i].id
772 << " ------------ \n";
773 getPortById(patch.sources[i].id, port);
774 result << dumpPort(port);
775 }
776 for (uint32_t i = 0; i < patch.num_sinks; i++) {
777 result << "----------------- Dumping Sink Port Config @ index " << i << " ------------ \n";
778 result << dumpPortConfig(patch.sinks[i]);
779 result << "----------------- Dumping Sink Port for id " << patch.sinks[i].id
780 << " ------------ \n";
781 getPortById(patch.sinks[i].id, port);
782 result << dumpPort(port);
783 }
784 return result.str();
785 }
786
dumpPort(const audio_port_v7 & port)787 std::string dumpPort(const audio_port_v7& port) {
788 std::ostringstream result;
789 std::string deviceInfo;
790 if (port.type == AUDIO_PORT_TYPE_DEVICE) {
791 if (port.ext.device.type & AUDIO_DEVICE_BIT_IN) {
792 InputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
793 } else {
794 OutputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
795 }
796 deviceInfo += std::string(", address = ") + port.ext.device.address;
797 }
798 result << "audio_port_handle_t = " << port.id << ", "
799 << "Role = " << (port.role == AUDIO_PORT_ROLE_SOURCE ? "source" : "sink") << ", "
800 << "Type = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix") << ", "
801 << "deviceInfo = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? deviceInfo : "") << ", "
802 << "Name = " << port.name << ", "
803 << "num profiles = " << port.num_audio_profiles << ", "
804 << "mix io handle = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? 0 : port.ext.mix.handle)
805 << ", ";
806 for (int i = 0; i < port.num_audio_profiles; i++) {
807 result << "AudioProfile = " << i << " {";
808 result << "format = " << port.audio_profiles[i].format << ", ";
809 result << "samplerates = ";
810 for (int j = 0; j < port.audio_profiles[i].num_sample_rates; j++) {
811 result << port.audio_profiles[i].sample_rates[j] << ", ";
812 }
813 result << "channelmasks = ";
814 for (int j = 0; j < port.audio_profiles[i].num_channel_masks; j++) {
815 result << "0x" << std::hex << port.audio_profiles[i].channel_masks[j] << std::dec
816 << ", ";
817 }
818 result << "} ";
819 }
820 result << dumpPortConfig(port.active_config);
821 return result.str();
822 }
823
getXmlAttribute(const xmlNode * cur,const char * attribute)824 std::string getXmlAttribute(const xmlNode* cur, const char* attribute) {
825 auto charPtr = make_xmlUnique(xmlGetProp(cur, reinterpret_cast<const xmlChar*>(attribute)));
826 if (charPtr == NULL) {
827 return "";
828 }
829 std::string value(reinterpret_cast<const char*>(charPtr.get()));
830 return value;
831 }
832
parse_audio_policy_configuration_xml(std::vector<std::string> & attachedDevices,std::vector<MixPort> & mixPorts,std::vector<Route> & routes)833 status_t parse_audio_policy_configuration_xml(std::vector<std::string>& attachedDevices,
834 std::vector<MixPort>& mixPorts,
835 std::vector<Route>& routes) {
836 std::string path = audio_find_readable_configuration_file("audio_policy_configuration.xml");
837 if (path.length() == 0) return UNKNOWN_ERROR;
838 auto doc = make_xmlUnique(xmlParseFile(path.c_str()));
839 if (doc == nullptr) return UNKNOWN_ERROR;
840 xmlNode* root = xmlDocGetRootElement(doc.get());
841 if (root == nullptr) return UNKNOWN_ERROR;
842 if (xmlXIncludeProcess(doc.get()) < 0) return UNKNOWN_ERROR;
843 mixPorts.clear();
844 if (!xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>("audioPolicyConfiguration"))) {
845 std::string raw{getXmlAttribute(root, "version")};
846 for (auto* child = root->xmlChildrenNode; child != nullptr; child = child->next) {
847 if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("modules"))) {
848 xmlNode* root = child;
849 for (auto* child = root->xmlChildrenNode; child != nullptr; child = child->next) {
850 if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("module"))) {
851 xmlNode* root = child;
852 for (auto* child = root->xmlChildrenNode; child != nullptr;
853 child = child->next) {
854 if (!xmlStrcmp(child->name,
855 reinterpret_cast<const xmlChar*>("mixPorts"))) {
856 xmlNode* root = child;
857 for (auto* child = root->xmlChildrenNode; child != nullptr;
858 child = child->next) {
859 if (!xmlStrcmp(child->name,
860 reinterpret_cast<const xmlChar*>("mixPort"))) {
861 MixPort mixPort;
862 xmlNode* root = child;
863 mixPort.name = getXmlAttribute(root, "name");
864 mixPort.role = getXmlAttribute(root, "role");
865 mixPort.flags = getXmlAttribute(root, "flags");
866 if (mixPort.role == "source") mixPorts.push_back(mixPort);
867 }
868 }
869 } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(
870 "attachedDevices"))) {
871 xmlNode* root = child;
872 for (auto* child = root->xmlChildrenNode; child != nullptr;
873 child = child->next) {
874 if (!xmlStrcmp(child->name,
875 reinterpret_cast<const xmlChar*>("item"))) {
876 auto xmlValue = make_xmlUnique(xmlNodeListGetString(
877 child->doc, child->xmlChildrenNode, 1));
878 if (xmlValue == nullptr) {
879 raw = "";
880 } else {
881 raw = reinterpret_cast<const char*>(xmlValue.get());
882 }
883 std::string& value = raw;
884 attachedDevices.push_back(std::move(value));
885 }
886 }
887 } else if (!xmlStrcmp(child->name,
888 reinterpret_cast<const xmlChar*>("routes"))) {
889 xmlNode* root = child;
890 for (auto* child = root->xmlChildrenNode; child != nullptr;
891 child = child->next) {
892 if (!xmlStrcmp(child->name,
893 reinterpret_cast<const xmlChar*>("route"))) {
894 Route route;
895 xmlNode* root = child;
896 route.name = getXmlAttribute(root, "name");
897 route.sources = getXmlAttribute(root, "sources");
898 route.sink = getXmlAttribute(root, "sink");
899 routes.push_back(route);
900 }
901 }
902 }
903 }
904 }
905 }
906 }
907 }
908 }
909 return OK;
910 }
911