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