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