aaudio: fix ownership problems with file descriptors
Use unique_fd to track file descriptors.
Fix extra close of file descriptor in SharedMemoryParcelable.cpp.
This bug was causing unrelated file descriptors to be closed!
Bug: 64311216
Test: write_sine.cpp, FD should survive aaudio close
Change-Id: I4f38c83510a49ea22b79b96d970ee48153417249
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.cpp b/services/oboeservice/AAudioServiceStreamMMAP.cpp
index 970d734..68dcaff 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.cpp
+++ b/services/oboeservice/AAudioServiceStreamMMAP.cpp
@@ -31,6 +31,7 @@
#include "SharedMemoryProxy.h"
#include "utility/AAudioUtilities.h"
+using android::base::unique_fd;
using namespace android;
using namespace aaudio;
@@ -69,11 +70,6 @@
AudioClock::sleepForNanos(100 * AAUDIO_NANOS_PER_MILLISECOND);
}
- if (mAudioDataFileDescriptor != -1) {
- ::close(mAudioDataFileDescriptor);
- mAudioDataFileDescriptor = -1;
- }
-
return AAudioServiceStreamBase::close();
}
@@ -193,7 +189,13 @@
? audio_channel_count_from_out_mask(config.channel_mask)
: audio_channel_count_from_in_mask(config.channel_mask);
- mAudioDataFileDescriptor = mMmapBufferinfo.shared_memory_fd;
+ // AAudio creates a copy of this FD and retains ownership of the copy.
+ // Assume that AudioFlinger will close the original shared_memory_fd.
+ mAudioDataFileDescriptor.reset(dup(mMmapBufferinfo.shared_memory_fd));
+ if (mAudioDataFileDescriptor.get() == -1) {
+ ALOGE("AAudioServiceStreamMMAP::open() - could not dup shared_memory_fd");
+ return AAUDIO_ERROR_INTERNAL; // TODO review
+ }
mFramesPerBurst = mMmapBufferinfo.burst_size_frames;
mAudioFormat = AAudioConvert_androidToAAudioDataFormat(config.format);
mSampleRate = config.sample_rate;
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.h b/services/oboeservice/AAudioServiceStreamMMAP.h
index e6f8fad..e631fd3 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.h
+++ b/services/oboeservice/AAudioServiceStreamMMAP.h
@@ -19,6 +19,7 @@
#include <atomic>
+#include <android-base/unique_fd.h>
#include <media/audiohal/StreamHalInterface.h>
#include <media/MmapStreamCallback.h>
#include <media/MmapStreamInterface.h>
@@ -33,6 +34,7 @@
#include "TimestampScheduler.h"
#include "utility/MonotonicCounter.h"
+
namespace aaudio {
/**
@@ -133,9 +135,9 @@
MonotonicCounter mFramesWritten;
MonotonicCounter mFramesRead;
int32_t mPreviousFrameCounter = 0; // from HAL
- int mAudioDataFileDescriptor = -1;
int64_t mHardwareTimeOffsetNanos = 0; // TODO get from HAL
+
// Interface to the AudioFlinger MMAP support.
android::sp<android::MmapStreamInterface> mMmapStream;
struct audio_mmap_buffer_info mMmapBufferinfo;
@@ -143,6 +145,7 @@
audio_port_handle_t mDeviceId = AUDIO_PORT_HANDLE_NONE;
android::AudioClient mServiceClient;
bool mInService = false;
+ android::base::unique_fd mAudioDataFileDescriptor;
};
} // namespace aaudio
diff --git a/services/oboeservice/SharedRingBuffer.cpp b/services/oboeservice/SharedRingBuffer.cpp
index 6b3fb4c..83b25b3 100644
--- a/services/oboeservice/SharedRingBuffer.cpp
+++ b/services/oboeservice/SharedRingBuffer.cpp
@@ -35,11 +35,6 @@
munmap(mSharedMemory, mSharedMemorySizeInBytes);
mSharedMemory = nullptr;
}
- if (mFileDescriptor != -1) {
- ALOGV("SharedRingBuffer: LEAK? close(mFileDescriptor = %d)\n", mFileDescriptor);
- close(mFileDescriptor);
- mFileDescriptor = -1;
- }
}
aaudio_result_t SharedRingBuffer::allocate(fifo_frames_t bytesPerFrame,
@@ -49,17 +44,17 @@
// Create shared memory large enough to hold the data and the read and write counters.
mDataMemorySizeInBytes = bytesPerFrame * capacityInFrames;
mSharedMemorySizeInBytes = mDataMemorySizeInBytes + (2 * (sizeof(fifo_counter_t)));
- mFileDescriptor = ashmem_create_region("AAudioSharedRingBuffer", mSharedMemorySizeInBytes);
- ALOGV("SharedRingBuffer::allocate() LEAK? mFileDescriptor = %d\n", mFileDescriptor);
- if (mFileDescriptor < 0) {
+ mFileDescriptor.reset(ashmem_create_region("AAudioSharedRingBuffer", mSharedMemorySizeInBytes));
+ if (mFileDescriptor.get() == -1) {
ALOGE("SharedRingBuffer::allocate() ashmem_create_region() failed %d", errno);
return AAUDIO_ERROR_INTERNAL;
}
+ ALOGV("SharedRingBuffer::allocate() mFileDescriptor = %d\n", mFileDescriptor.get());
- int err = ashmem_set_prot_region(mFileDescriptor, PROT_READ|PROT_WRITE); // TODO error handling?
+ int err = ashmem_set_prot_region(mFileDescriptor.get(), PROT_READ|PROT_WRITE); // TODO error handling?
if (err < 0) {
ALOGE("SharedRingBuffer::allocate() ashmem_set_prot_region() failed %d", errno);
- close(mFileDescriptor);
+ mFileDescriptor.reset();
return AAUDIO_ERROR_INTERNAL; // TODO convert errno to a better AAUDIO_ERROR;
}
@@ -67,10 +62,10 @@
mSharedMemory = (uint8_t *) mmap(0, mSharedMemorySizeInBytes,
PROT_READ|PROT_WRITE,
MAP_SHARED,
- mFileDescriptor, 0);
+ mFileDescriptor.get(), 0);
if (mSharedMemory == MAP_FAILED) {
ALOGE("SharedRingBuffer::allocate() mmap() failed %d", errno);
- close(mFileDescriptor);
+ mFileDescriptor.reset();
return AAUDIO_ERROR_INTERNAL; // TODO convert errno to a better AAUDIO_ERROR;
}
diff --git a/services/oboeservice/SharedRingBuffer.h b/services/oboeservice/SharedRingBuffer.h
index a2c3766..79169bc 100644
--- a/services/oboeservice/SharedRingBuffer.h
+++ b/services/oboeservice/SharedRingBuffer.h
@@ -17,6 +17,7 @@
#ifndef AAUDIO_SHARED_RINGBUFFER_H
#define AAUDIO_SHARED_RINGBUFFER_H
+#include <android-base/unique_fd.h>
#include <stdint.h>
#include <cutils/ashmem.h>
#include <sys/mman.h>
@@ -51,12 +52,12 @@
}
private:
- int mFileDescriptor = -1;
- android::FifoBuffer *mFifoBuffer = nullptr;
- uint8_t *mSharedMemory = nullptr;
- int32_t mSharedMemorySizeInBytes = 0;
- int32_t mDataMemorySizeInBytes = 0;
- android::fifo_frames_t mCapacityInFrames = 0;
+ android::base::unique_fd mFileDescriptor;
+ android::FifoBuffer *mFifoBuffer = nullptr;
+ uint8_t *mSharedMemory = nullptr;
+ int32_t mSharedMemorySizeInBytes = 0;
+ int32_t mDataMemorySizeInBytes = 0;
+ android::fifo_frames_t mCapacityInFrames = 0;
};
} /* namespace aaudio */