xref: /aosp_15_r20/frameworks/av/media/libaudioclient/tests/audio_test_utils.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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