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