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