aaudio: free endpoint to prevent crashes
Free the AudioEndpoint and check for nullptr to
prevent accessing shared memory that had been freed.
This is to protect against calls to the stream after
AAudioStream_release() has been called.
Bug: 154274446
Bug: 154274027
Test: libaaudio/tests/test_various.cpp
Change-Id: I194d502fd48c4d31602ffce76aca6b28753ad7d2
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index b50a512..1303daf 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -87,8 +87,8 @@
}
void AudioStreamInternalPlay::advanceClientToMatchServerPosition() {
- int64_t readCounter = mAudioEndpoint.getDataReadCounter();
- int64_t writeCounter = mAudioEndpoint.getDataWriteCounter();
+ int64_t readCounter = mAudioEndpoint->getDataReadCounter();
+ int64_t writeCounter = mAudioEndpoint->getDataWriteCounter();
// Bump offset so caller does not see the retrograde motion in getFramesRead().
int64_t offset = writeCounter - readCounter;
@@ -98,7 +98,7 @@
// Force writeCounter to match readCounter.
// This is because we cannot change the read counter in the hardware.
- mAudioEndpoint.setDataWriteCounter(readCounter);
+ mAudioEndpoint->setDataWriteCounter(readCounter);
}
void AudioStreamInternalPlay::onFlushFromServer() {
@@ -135,11 +135,11 @@
// If we have gotten this far then we have at least one timestamp from server.
// If a DMA channel or DSP is reading the other end then we have to update the readCounter.
- if (mAudioEndpoint.isFreeRunning()) {
+ if (mAudioEndpoint->isFreeRunning()) {
// Update data queue based on the timing model.
int64_t estimatedReadCounter = mClockModel.convertTimeToPosition(currentNanoTime);
// ALOGD("AudioStreamInternal::processDataNow() - estimatedReadCounter = %d", (int)estimatedReadCounter);
- mAudioEndpoint.setDataReadCounter(estimatedReadCounter);
+ mAudioEndpoint->setDataReadCounter(estimatedReadCounter);
}
if (mNeedCatchUp.isRequested()) {
@@ -151,7 +151,7 @@
// If the read index passed the write index then consider it an underrun.
// For shared streams, the xRunCount is passed up from the service.
- if (mAudioEndpoint.isFreeRunning() && mAudioEndpoint.getFullFramesAvailable() < 0) {
+ if (mAudioEndpoint->isFreeRunning() && mAudioEndpoint->getFullFramesAvailable() < 0) {
mXRunCount++;
if (ATRACE_ENABLED()) {
ATRACE_INT("aaUnderRuns", mXRunCount);
@@ -170,7 +170,7 @@
// Sleep if there is too much data in the buffer.
// Calculate an ideal time to wake up.
if (wakeTimePtr != nullptr
- && (mAudioEndpoint.getFullFramesAvailable() >= getBufferSize())) {
+ && (mAudioEndpoint->getFullFramesAvailable() >= getBufferSize())) {
// By default wake up a few milliseconds from now. // TODO review
int64_t wakeTime = currentNanoTime + (1 * AAUDIO_NANOS_PER_MILLISECOND);
aaudio_stream_state_t state = getState();
@@ -188,7 +188,7 @@
{
// Sleep until the readCounter catches up and we only have
// the getBufferSize() frames of data sitting in the buffer.
- int64_t nextReadPosition = mAudioEndpoint.getDataWriteCounter() - getBufferSize();
+ int64_t nextReadPosition = mAudioEndpoint->getDataWriteCounter() - getBufferSize();
wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
}
break;
@@ -210,7 +210,7 @@
uint8_t *byteBuffer = (uint8_t *) buffer;
int32_t framesLeft = numFrames;
- mAudioEndpoint.getEmptyFramesAvailable(&wrappingBuffer);
+ mAudioEndpoint->getEmptyFramesAvailable(&wrappingBuffer);
// Write data in one or two parts.
int partIndex = 0;
@@ -236,24 +236,28 @@
partIndex++;
}
int32_t framesWritten = numFrames - framesLeft;
- mAudioEndpoint.advanceWriteIndex(framesWritten);
+ mAudioEndpoint->advanceWriteIndex(framesWritten);
return framesWritten;
}
int64_t AudioStreamInternalPlay::getFramesRead() {
- const int64_t framesReadHardware = isClockModelInControl()
- ? mClockModel.convertTimeToPosition(AudioClock::getNanoseconds())
- : mAudioEndpoint.getDataReadCounter();
- // Add service offset and prevent retrograde motion.
- mLastFramesRead = std::max(mLastFramesRead, framesReadHardware + mFramesOffsetFromService);
+ if (mAudioEndpoint) {
+ const int64_t framesReadHardware = isClockModelInControl()
+ ? mClockModel.convertTimeToPosition(AudioClock::getNanoseconds())
+ : mAudioEndpoint->getDataReadCounter();
+ // Add service offset and prevent retrograde motion.
+ mLastFramesRead = std::max(mLastFramesRead, framesReadHardware + mFramesOffsetFromService);
+ }
return mLastFramesRead;
}
int64_t AudioStreamInternalPlay::getFramesWritten() {
- const int64_t framesWritten = mAudioEndpoint.getDataWriteCounter()
- + mFramesOffsetFromService;
- return framesWritten;
+ if (mAudioEndpoint) {
+ mLastFramesWritten = mAudioEndpoint->getDataWriteCounter()
+ + mFramesOffsetFromService;
+ }
+ return mLastFramesWritten;
}