aaudio: keep track of streams using strong pointers
Maintain strong pointer to service stream during service calls.
Use simple AAudioStreamTracker instead of complex HandleTracker.
Bug: 65280854
Test: affects all MMAP streams, run all CTS tests, etcetera
Change-Id: I3d2ed8b588ea39c216dacd4dea503b11c33f36f3
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index f41219e..f996f74 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -102,7 +102,7 @@
}
}
- ALOGD("AAudioEndpointManager.findExclusiveEndpoint_l(), found %p for device = %d",
+ ALOGV("AAudioEndpointManager.findExclusiveEndpoint_l(), found %p for device = %d",
endpoint.get(), configuration.getDeviceId());
return endpoint;
}
@@ -118,7 +118,7 @@
}
}
- ALOGD("AAudioEndpointManager.findSharedEndpoint_l(), found %p for device = %d",
+ ALOGV("AAudioEndpointManager.findSharedEndpoint_l(), found %p for device = %d",
endpoint.get(), configuration.getDeviceId());
return endpoint;
}
@@ -238,8 +238,6 @@
std::lock_guard<std::mutex> lock(mExclusiveLock);
int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
serviceEndpoint->setOpenCount(newRefCount);
- ALOGD("AAudioEndpointManager::closeExclusiveEndpoint(%p) newRefCount = %d",
- serviceEndpoint.get(), newRefCount);
// If no longer in use then close and delete it.
if (newRefCount <= 0) {
@@ -262,8 +260,6 @@
std::lock_guard<std::mutex> lock(mSharedLock);
int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
serviceEndpoint->setOpenCount(newRefCount);
- ALOGD("AAudioEndpointManager::closeSharedEndpoint(%p) newRefCount = %d",
- serviceEndpoint.get(), newRefCount);
// If no longer in use then close and delete it.
if (newRefCount <= 0) {
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index 5b34895..5a3488d 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -18,9 +18,9 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <iomanip>
+#include <iostream>
#include <sstream>
-//#include <time.h>
-//#include <pthread.h>
#include <aaudio/AAudio.h>
#include <mediautils/SchedulingPolicyService.h>
@@ -35,18 +35,13 @@
#include "AAudioServiceStreamMMAP.h"
#include "binding/IAAudioService.h"
#include "ServiceUtilities.h"
-#include "utility/HandleTracker.h"
using namespace android;
using namespace aaudio;
#define MAX_STREAMS_PER_PROCESS 8
-typedef enum
-{
- AAUDIO_HANDLE_TYPE_STREAM
-} aaudio_service_handle_type_t;
-static_assert(AAUDIO_HANDLE_TYPE_STREAM < HANDLE_TRACKER_MAX_TYPES, "Too many handle types.");
+using android::AAudioService;
android::AAudioService::AAudioService()
: BnAAudioService() {
@@ -70,7 +65,8 @@
result = ss.str();
ALOGW("%s", result.c_str());
} else {
- result = mHandleTracker.dump()
+ result = "------------ AAudio Service ------------\n"
+ + mStreamTracker.dump()
+ AAudioClientTracker::getInstance().dump()
+ AAudioEndpointManager::getInstance().dump();
}
@@ -125,7 +121,7 @@
// if SHARED requested or if EXCLUSIVE failed
if (sharingMode == AAUDIO_SHARING_MODE_SHARED
- || (serviceStream == nullptr && !sharingModeMatchRequired)) {
+ || (serviceStream.get() == nullptr && !sharingModeMatchRequired)) {
serviceStream = new AAudioServiceStreamShared(*this);
result = serviceStream->open(request);
}
@@ -136,18 +132,12 @@
result, AAudio_convertResultToText(result));
return result;
} else {
- aaudio_handle_t handle = mHandleTracker.put(AAUDIO_HANDLE_TYPE_STREAM, serviceStream.get());
- if (handle < 0) {
- ALOGE("AAudioService::openStream(): handle table full");
- serviceStream->close();
- serviceStream.clear();
- } else {
- ALOGD("AAudioService::openStream(): handle = 0x%08X", handle);
- serviceStream->setHandle(handle);
- pid_t pid = request.getProcessId();
- AAudioClientTracker::getInstance().registerClientStream(pid, serviceStream);
- configurationOutput.copyFrom(*serviceStream);
- }
+ aaudio_handle_t handle = mStreamTracker.addStreamForHandle(serviceStream.get());
+ ALOGD("AAudioService::openStream(): handle = 0x%08X", handle);
+ serviceStream->setHandle(handle);
+ pid_t pid = request.getProcessId();
+ AAudioClientTracker::getInstance().registerClientStream(pid, serviceStream);
+ configurationOutput.copyFrom(*serviceStream);
return handle;
}
}
@@ -155,30 +145,32 @@
aaudio_result_t AAudioService::closeStream(aaudio_handle_t streamHandle) {
// Check permission and ownership first.
sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
- ALOGE("AAudioService::startStream(), illegal stream handle = 0x%0x", streamHandle);
+ if (serviceStream.get() == nullptr) {
+ ALOGE("AAudioService::closeStream(0x%0x), illegal stream handle", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
ALOGD("AAudioService.closeStream(0x%08X)", streamHandle);
// Remove handle from tracker so that we cannot look up the raw address any more.
- serviceStream = (AAudioServiceStreamBase *)
- mHandleTracker.remove(AAUDIO_HANDLE_TYPE_STREAM,
- streamHandle);
- if (serviceStream != nullptr) {
+ // removeStreamByHandle() uses a lock so that if there are two simultaneous closes
+ // then only one will get the pointer and do the close.
+ serviceStream = mStreamTracker.removeStreamByHandle(streamHandle);
+ if (serviceStream.get() != nullptr) {
serviceStream->close();
pid_t pid = serviceStream->getOwnerProcessId();
AAudioClientTracker::getInstance().unregisterClientStream(pid, serviceStream);
return AAUDIO_OK;
+ } else {
+ ALOGW("AAudioService::closeStream(0x%0x) being handled by another thread", streamHandle);
+ return AAUDIO_ERROR_INVALID_HANDLE;
}
- return AAUDIO_ERROR_INVALID_HANDLE;
}
-AAudioServiceStreamBase *AAudioService::convertHandleToServiceStream(
- aaudio_handle_t streamHandle) const {
- AAudioServiceStreamBase *serviceStream = (AAudioServiceStreamBase *)
- mHandleTracker.get(AAUDIO_HANDLE_TYPE_STREAM, (aaudio_handle_t)streamHandle);
- if (serviceStream != nullptr) {
+
+sp<AAudioServiceStreamBase> AAudioService::convertHandleToServiceStream(
+ aaudio_handle_t streamHandle) {
+ sp<AAudioServiceStreamBase> serviceStream = mStreamTracker.getStreamByHandle(streamHandle);
+ if (serviceStream.get() != nullptr) {
// Only allow owner or the aaudio service to access the stream.
const uid_t callingUserId = IPCThreadState::self()->getCallingUid();
const uid_t ownerUserId = serviceStream->getOwnerUserId();
@@ -198,19 +190,20 @@
aaudio_result_t AAudioService::getStreamDescription(
aaudio_handle_t streamHandle,
aaudio::AudioEndpointParcelable &parcelable) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::getStreamDescription(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
+
aaudio_result_t result = serviceStream->getDescription(parcelable);
// parcelable.dump();
return result;
}
aaudio_result_t AAudioService::startStream(aaudio_handle_t streamHandle) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::startStream(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
@@ -219,8 +212,8 @@
}
aaudio_result_t AAudioService::pauseStream(aaudio_handle_t streamHandle) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::pauseStream(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
@@ -229,9 +222,9 @@
}
aaudio_result_t AAudioService::stopStream(aaudio_handle_t streamHandle) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
- ALOGE("AAudioService::pauseStream(), illegal stream handle = 0x%0x", streamHandle);
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
+ ALOGE("AAudioService::stopStream(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
aaudio_result_t result = serviceStream->stop();
@@ -239,8 +232,8 @@
}
aaudio_result_t AAudioService::flushStream(aaudio_handle_t streamHandle) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::flushStream(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
@@ -250,8 +243,8 @@
aaudio_result_t AAudioService::registerAudioThread(aaudio_handle_t streamHandle,
pid_t clientThreadId,
int64_t periodNanoseconds) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::registerAudioThread(), illegal stream handle = 0x%0x", streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
}
@@ -275,8 +268,8 @@
aaudio_result_t AAudioService::unregisterAudioThread(aaudio_handle_t streamHandle,
pid_t clientThreadId) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::unregisterAudioThread(), illegal stream handle = 0x%0x",
streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
@@ -292,8 +285,8 @@
aaudio_result_t AAudioService::startClient(aaudio_handle_t streamHandle,
const android::AudioClient& client,
audio_port_handle_t *clientHandle) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::startClient(), illegal stream handle = 0x%0x",
streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
@@ -303,8 +296,8 @@
aaudio_result_t AAudioService::stopClient(aaudio_handle_t streamHandle,
audio_port_handle_t clientHandle) {
- AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- if (serviceStream == nullptr) {
+ sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
+ if (serviceStream.get() == nullptr) {
ALOGE("AAudioService::stopClient(), illegal stream handle = 0x%0x",
streamHandle);
return AAUDIO_ERROR_INVALID_HANDLE;
diff --git a/services/oboeservice/AAudioService.h b/services/oboeservice/AAudioService.h
index ffaf538..eef0824 100644
--- a/services/oboeservice/AAudioService.h
+++ b/services/oboeservice/AAudioService.h
@@ -24,13 +24,13 @@
#include <media/AudioClient.h>
#include <aaudio/AAudio.h>
-#include "utility/HandleTracker.h"
-#include "binding/IAAudioService.h"
-#include "binding/AAudioServiceInterface.h"
-namespace aaudio {
- class AAudioServiceStreamBase;
-};
+#include "binding/AAudioCommon.h"
+#include "binding/AAudioServiceInterface.h"
+#include "binding/IAAudioService.h"
+
+#include "AAudioServiceStreamBase.h"
+#include "AAudioStreamTracker.h"
namespace android {
@@ -51,45 +51,53 @@
virtual void registerClient(const sp<IAAudioClient>& client);
- virtual aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
- aaudio::AAudioStreamConfiguration &configurationOutput);
+ aaudio::aaudio_handle_t openStream(const aaudio::AAudioStreamRequest &request,
+ aaudio::AAudioStreamConfiguration &configurationOutput)
+ override;
- virtual aaudio_result_t closeStream(aaudio_handle_t streamHandle);
+ aaudio_result_t closeStream(aaudio::aaudio_handle_t streamHandle) override;
- virtual aaudio_result_t getStreamDescription(
- aaudio_handle_t streamHandle,
- aaudio::AudioEndpointParcelable &parcelable);
+ aaudio_result_t getStreamDescription(
+ aaudio::aaudio_handle_t streamHandle,
+ aaudio::AudioEndpointParcelable &parcelable) override;
- virtual aaudio_result_t startStream(aaudio_handle_t streamHandle);
+ aaudio_result_t startStream(aaudio::aaudio_handle_t streamHandle) override;
- virtual aaudio_result_t pauseStream(aaudio_handle_t streamHandle);
+ aaudio_result_t pauseStream(aaudio::aaudio_handle_t streamHandle) override;
- virtual aaudio_result_t stopStream(aaudio_handle_t streamHandle);
+ aaudio_result_t stopStream(aaudio::aaudio_handle_t streamHandle) override;
- virtual aaudio_result_t flushStream(aaudio_handle_t streamHandle);
+ aaudio_result_t flushStream(aaudio::aaudio_handle_t streamHandle) override;
- virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
+ aaudio_result_t registerAudioThread(aaudio::aaudio_handle_t streamHandle,
pid_t tid,
- int64_t periodNanoseconds) ;
+ int64_t periodNanoseconds) override;
- virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
- pid_t tid);
+ aaudio_result_t unregisterAudioThread(aaudio::aaudio_handle_t streamHandle,
+ pid_t tid) override;
- virtual aaudio_result_t startClient(aaudio_handle_t streamHandle,
+ aaudio_result_t startClient(aaudio::aaudio_handle_t streamHandle,
const android::AudioClient& client,
- audio_port_handle_t *clientHandle);
+ audio_port_handle_t *clientHandle) override;
- virtual aaudio_result_t stopClient(aaudio_handle_t streamHandle,
- audio_port_handle_t clientHandle);
+ aaudio_result_t stopClient(aaudio::aaudio_handle_t streamHandle,
+ audio_port_handle_t clientHandle) override;
private:
- aaudio::AAudioServiceStreamBase *convertHandleToServiceStream(aaudio_handle_t streamHandle) const;
+ /**
+ * Lookup stream and then validate access to the stream.
+ * @param streamHandle
+ * @return
+ */
+ sp<aaudio::AAudioServiceStreamBase> convertHandleToServiceStream(
+ aaudio::aaudio_handle_t streamHandle);
- HandleTracker mHandleTracker;
android::AudioClient mAudioClient;
+ aaudio::AAudioStreamTracker mStreamTracker;
+
enum constants {
DEFAULT_AUDIO_PRIORITY = 2
};
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index cba5bc8..3095bc9 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -60,7 +60,7 @@
result << " Reference Count: " << mOpenCount << "\n";
result << " Requested Device Id: " << mRequestedDeviceId << "\n";
result << " Device Id: " << getDeviceId() << "\n";
- result << " Registered Streams: " << "\n";
+ result << " Registered Streams:" << "\n";
result << AAudioServiceStreamShared::dumpHeader() << "\n";
for (const auto stream : mRegisteredStreams) {
result << stream->dump() << "\n";
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.cpp b/services/oboeservice/AAudioServiceEndpointCapture.cpp
index 97558ca..c7d9b8e 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.cpp
+++ b/services/oboeservice/AAudioServiceEndpointCapture.cpp
@@ -84,30 +84,42 @@
std::lock_guard <std::mutex> lock(mLockStreams);
for (const auto clientStream : mRegisteredStreams) {
if (clientStream->isRunning()) {
- AAudioServiceStreamShared *streamShared =
+ int64_t clientFramesWritten = 0;
+ sp<AAudioServiceStreamShared> streamShared =
static_cast<AAudioServiceStreamShared *>(clientStream.get());
- FifoBuffer *fifo = streamShared->getDataFifoBuffer();
+ {
+ // Lock the AudioFifo to protect against close.
+ std::lock_guard <std::mutex> lock(streamShared->getAudioDataQueueLock());
- // Determine offset between framePosition in client's stream vs the underlying
- // MMAP stream.
- int64_t clientFramesWritten = fifo->getWriteCounter();
- // There are two indices that refer to the same frame.
- int64_t positionOffset = mmapFramesRead - clientFramesWritten;
- streamShared->setTimestampPositionOffset(positionOffset);
+ FifoBuffer *fifo = streamShared->getAudioDataFifoBuffer_l();
+ if (fifo != nullptr) {
- if (fifo->getFifoControllerBase()->getEmptyFramesAvailable() <
- getFramesPerBurst()) {
- underflowCount++;
- } else {
- fifo->write(mDistributionBuffer, getFramesPerBurst());
+ // Determine offset between framePosition in client's stream
+ // vs the underlying MMAP stream.
+ clientFramesWritten = fifo->getWriteCounter();
+ // There are two indices that refer to the same frame.
+ int64_t positionOffset = mmapFramesRead - clientFramesWritten;
+ streamShared->setTimestampPositionOffset(positionOffset);
+
+ if (fifo->getFifoControllerBase()->getEmptyFramesAvailable() <
+ getFramesPerBurst()) {
+ underflowCount++;
+ } else {
+ fifo->write(mDistributionBuffer, getFramesPerBurst());
+ }
+ clientFramesWritten = fifo->getWriteCounter();
+ }
}
- // This timestamp represents the completion of data being written into the
- // client buffer. It is sent to the client and used in the timing model
- // to decide when data will be available to read.
- Timestamp timestamp(fifo->getWriteCounter(), AudioClock::getNanoseconds());
- streamShared->markTransferTime(timestamp);
+ if (clientFramesWritten > 0) {
+ // This timestamp represents the completion of data being written into the
+ // client buffer. It is sent to the client and used in the timing model
+ // to decide when data will be available to read.
+ Timestamp timestamp(clientFramesWritten, AudioClock::getNanoseconds());
+ streamShared->markTransferTime(timestamp);
+ }
+
}
}
}
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index c42a6e2..9b1833a 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -81,32 +81,44 @@
std::lock_guard <std::mutex> lock(mLockStreams);
for (const auto clientStream : mRegisteredStreams) {
+ int64_t clientFramesRead = 0;
+
if (!clientStream->isRunning()) {
continue;
}
- AAudioServiceStreamShared *streamShared =
+ sp<AAudioServiceStreamShared> streamShared =
static_cast<AAudioServiceStreamShared *>(clientStream.get());
- FifoBuffer *fifo = streamShared->getDataFifoBuffer();
- // Determine offset between framePosition in client's stream vs the underlying
- // MMAP stream.
- int64_t clientFramesRead = fifo->getReadCounter();
- // These two indices refer to the same frame.
- int64_t positionOffset = mmapFramesWritten - clientFramesRead;
- streamShared->setTimestampPositionOffset(positionOffset);
+ {
+ // Lock the AudioFifo to protect against close.
+ std::lock_guard <std::mutex> lock(streamShared->getAudioDataQueueLock());
- float volume = 1.0; // to match legacy volume
- bool underflowed = mMixer.mix(index, fifo, volume);
+ FifoBuffer *fifo = streamShared->getAudioDataFifoBuffer_l();
+ if (fifo != nullptr) {
- // This timestamp represents the completion of data being read out of the
- // client buffer. It is sent to the client and used in the timing model
- // to decide when the client has room to write more data.
- Timestamp timestamp(fifo->getReadCounter(), AudioClock::getNanoseconds());
- streamShared->markTransferTime(timestamp);
+ // Determine offset between framePosition in client's stream
+ // vs the underlying MMAP stream.
+ clientFramesRead = fifo->getReadCounter();
+ // These two indices refer to the same frame.
+ int64_t positionOffset = mmapFramesWritten - clientFramesRead;
+ streamShared->setTimestampPositionOffset(positionOffset);
- if (underflowed) {
- streamShared->incrementXRunCount();
+ float volume = 1.0; // to match legacy volume
+ bool underflowed = mMixer.mix(index, fifo, volume);
+ if (underflowed) {
+ streamShared->incrementXRunCount();
+ }
+ clientFramesRead = fifo->getReadCounter();
+ }
+ }
+
+ if (clientFramesRead > 0) {
+ // This timestamp represents the completion of data being read out of the
+ // client buffer. It is sent to the client and used in the timing model
+ // to decide when the client has room to write more data.
+ Timestamp timestamp(clientFramesRead, AudioClock::getNanoseconds());
+ streamShared->markTransferTime(timestamp);
}
index++; // just used for labelling tracks in systrace
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index ca7b528..e670129 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -365,10 +365,17 @@
* used to communicate with the underlying HAL or Service.
*/
aaudio_result_t AAudioServiceStreamBase::getDescription(AudioEndpointParcelable &parcelable) {
- // Gather information on the message queue.
- mUpMessageQueue->fillParcelable(parcelable,
- parcelable.mUpMessageQueueParcelable);
- return getDownDataDescription(parcelable);
+ {
+ std::lock_guard<std::mutex> lock(mUpMessageQueueLock);
+ if (mUpMessageQueue == nullptr) {
+ ALOGE("getDescription(): mUpMessageQueue null! - stream not open");
+ return AAUDIO_ERROR_NULL;
+ }
+ // Gather information on the message queue.
+ mUpMessageQueue->fillParcelable(parcelable,
+ parcelable.mUpMessageQueueParcelable);
+ }
+ return getAudioDataDescription(parcelable);
}
void AAudioServiceStreamBase::onVolumeChanged(float volume) {
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index 6f61401..af435b4 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -32,7 +32,10 @@
#include "SharedRingBuffer.h"
#include "AAudioThread.h"
-#include "AAudioService.h"
+
+namespace android {
+ class AAudioService;
+}
namespace aaudio {
@@ -210,7 +213,7 @@
virtual aaudio_result_t getHardwareTimestamp(int64_t *positionFrames, int64_t *timeNanos) = 0;
- virtual aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable) = 0;
+ virtual aaudio_result_t getAudioDataDescription(AudioEndpointParcelable &parcelable) = 0;
aaudio_stream_state_t mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.cpp b/services/oboeservice/AAudioServiceStreamMMAP.cpp
index a629ed6..44ba1ca 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.cpp
+++ b/services/oboeservice/AAudioServiceStreamMMAP.cpp
@@ -168,7 +168,8 @@
/**
* Get an immutable description of the data queue from the HAL.
*/
-aaudio_result_t AAudioServiceStreamMMAP::getDownDataDescription(AudioEndpointParcelable &parcelable)
+aaudio_result_t AAudioServiceStreamMMAP::getAudioDataDescription(
+ AudioEndpointParcelable &parcelable)
{
sp<AAudioServiceEndpointMMAP> serviceEndpointMMAP{
static_cast<AAudioServiceEndpointMMAP *>(mServiceEndpoint.get())};
diff --git a/services/oboeservice/AAudioServiceStreamMMAP.h b/services/oboeservice/AAudioServiceStreamMMAP.h
index 83cd2ef..e2415d0 100644
--- a/services/oboeservice/AAudioServiceStreamMMAP.h
+++ b/services/oboeservice/AAudioServiceStreamMMAP.h
@@ -75,7 +75,7 @@
protected:
- aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable) override;
+ aaudio_result_t getAudioDataDescription(AudioEndpointParcelable &parcelable) override;
aaudio_result_t getFreeRunningPosition(int64_t *positionFrames, int64_t *timeNanos) override;
diff --git a/services/oboeservice/AAudioServiceStreamShared.cpp b/services/oboeservice/AAudioServiceStreamShared.cpp
index 348d407..084f996 100644
--- a/services/oboeservice/AAudioServiceStreamShared.cpp
+++ b/services/oboeservice/AAudioServiceStreamShared.cpp
@@ -167,14 +167,17 @@
goto error;
}
- // Create audio data shared memory buffer for client.
- mAudioDataQueue = new SharedRingBuffer();
- result = mAudioDataQueue->allocate(calculateBytesPerFrame(), getBufferCapacity());
- if (result != AAUDIO_OK) {
- ALOGE("AAudioServiceStreamShared::open() could not allocate FIFO with %d frames",
- getBufferCapacity());
- result = AAUDIO_ERROR_NO_MEMORY;
- goto error;
+ {
+ std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
+ // Create audio data shared memory buffer for client.
+ mAudioDataQueue = new SharedRingBuffer();
+ result = mAudioDataQueue->allocate(calculateBytesPerFrame(), getBufferCapacity());
+ if (result != AAUDIO_OK) {
+ ALOGE("AAudioServiceStreamShared::open() could not allocate FIFO with %d frames",
+ getBufferCapacity());
+ result = AAUDIO_ERROR_NO_MEMORY;
+ goto error;
+ }
}
ALOGD("AAudioServiceStreamShared::open() actual rate = %d, channels = %d, deviceId = %d",
@@ -197,8 +200,11 @@
aaudio_result_t AAudioServiceStreamShared::close() {
aaudio_result_t result = AAudioServiceStreamBase::close();
- delete mAudioDataQueue;
- mAudioDataQueue = nullptr;
+ {
+ std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
+ delete mAudioDataQueue;
+ mAudioDataQueue = nullptr;
+ }
return result;
}
@@ -206,8 +212,14 @@
/**
* Get an immutable description of the data queue created by this service.
*/
-aaudio_result_t AAudioServiceStreamShared::getDownDataDescription(AudioEndpointParcelable &parcelable)
+aaudio_result_t AAudioServiceStreamShared::getAudioDataDescription(
+ AudioEndpointParcelable &parcelable)
{
+ std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
+ if (mAudioDataQueue == nullptr) {
+ ALOGE("getAudioDataDescription(): mUpMessageQueue null! - stream not open");
+ return AAUDIO_ERROR_NULL;
+ }
// Gather information on the data queue.
mAudioDataQueue->fillParcelable(parcelable,
parcelable.mDownDataQueueParcelable);
diff --git a/services/oboeservice/AAudioServiceStreamShared.h b/services/oboeservice/AAudioServiceStreamShared.h
index bc86dcc..8499ea5 100644
--- a/services/oboeservice/AAudioServiceStreamShared.h
+++ b/services/oboeservice/AAudioServiceStreamShared.h
@@ -54,7 +54,21 @@
aaudio_result_t close() override;
- android::FifoBuffer *getDataFifoBuffer() { return mAudioDataQueue->getFifoBuffer(); }
+ /**
+ * This must be locked when calling getAudioDataFifoBuffer_l() and while
+ * using the FifoBuffer it returns.
+ */
+ std::mutex &getAudioDataQueueLock() {
+ return mAudioDataQueueLock;
+ }
+
+ /**
+ * This must only be call under getAudioDataQueueLock().
+ * @return
+ */
+ android::FifoBuffer *getAudioDataFifoBuffer_l() { return (mAudioDataQueue == nullptr)
+ ? nullptr
+ : mAudioDataQueue->getFifoBuffer(); }
/* Keep a record of when a buffer transfer completed.
* This allows for a more accurate timing model.
@@ -75,7 +89,7 @@
protected:
- aaudio_result_t getDownDataDescription(AudioEndpointParcelable &parcelable) override;
+ aaudio_result_t getAudioDataDescription(AudioEndpointParcelable &parcelable) override;
aaudio_result_t getFreeRunningPosition(int64_t *positionFrames, int64_t *timeNanos) override;
@@ -90,7 +104,8 @@
int32_t framesPerBurst);
private:
- SharedRingBuffer *mAudioDataQueue = nullptr;
+ SharedRingBuffer *mAudioDataQueue = nullptr; // protected by mAudioDataQueueLock
+ std::mutex mAudioDataQueueLock;
std::atomic<int64_t> mTimestampPositionOffset;
std::atomic<int32_t> mXRunCount;
diff --git a/services/oboeservice/AAudioStreamTracker.cpp b/services/oboeservice/AAudioStreamTracker.cpp
new file mode 100644
index 0000000..ef88b34
--- /dev/null
+++ b/services/oboeservice/AAudioStreamTracker.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AAudioStreamTracker"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+
+#include <aaudio/AAudio.h>
+#include <utils/String16.h>
+
+#include "AAudioStreamTracker.h"
+
+using namespace android;
+using namespace aaudio;
+
+sp<AAudioServiceStreamBase> AAudioStreamTracker::removeStreamByHandle(
+ aaudio_handle_t streamHandle) {
+ std::lock_guard<std::mutex> lock(mHandleLock);
+ sp<AAudioServiceStreamBase> serviceStream;
+ auto it = mStreamsByHandle.find(streamHandle);
+ if (it != mStreamsByHandle.end()) {
+ serviceStream = it->second;
+ mStreamsByHandle.erase(it);
+ }
+ return serviceStream;
+}
+
+sp<AAudioServiceStreamBase> AAudioStreamTracker::getStreamByHandle(
+ aaudio_handle_t streamHandle) {
+ std::lock_guard<std::mutex> lock(mHandleLock);
+ sp<AAudioServiceStreamBase> serviceStream;
+ auto it = mStreamsByHandle.find(streamHandle);
+ if (it != mStreamsByHandle.end()) {
+ serviceStream = it->second;
+ }
+ return serviceStream;
+}
+
+// advance to next legal handle value
+__attribute__((no_sanitize("integer")))
+aaudio_handle_t AAudioStreamTracker::bumpHandle(aaudio_handle_t handle) {
+ handle++;
+ // Only use positive integers.
+ if (handle <= 0) {
+ handle = 1;
+ }
+ return handle;
+}
+
+aaudio_handle_t AAudioStreamTracker::addStreamForHandle(sp<AAudioServiceStreamBase> serviceStream) {
+ std::lock_guard<std::mutex> lock(mHandleLock);
+ aaudio_handle_t handle = mPreviousHandle.load();
+ // Assign a unique handle.
+ while (true) {
+ handle = bumpHandle(handle);
+ sp<AAudioServiceStreamBase> oldServiceStream = mStreamsByHandle[handle];
+ // Is this an unused handle? It would be extremely unlikely to wrap
+ // around and collide with a very old handle. But just in case.
+ if (oldServiceStream.get() == nullptr) {
+ mStreamsByHandle[handle] = serviceStream;
+ break;
+ }
+ }
+ mPreviousHandle.store(handle);
+ return handle;
+}
+
+std::string AAudioStreamTracker::dump() const {
+ std::stringstream result;
+ const bool isLocked = AAudio_tryUntilTrue(
+ [this]()->bool { return mHandleLock.try_lock(); } /* f */,
+ 50 /* times */,
+ 20 /* sleepMs */);
+ if (!isLocked) {
+ result << "AAudioStreamTracker may be deadlocked\n";
+ } else {
+ result << "Stream Handles:\n";
+ for (const auto& it : mStreamsByHandle) {
+ aaudio_handle_t handle = it.second->getHandle();
+ result << " 0x" << std::setfill('0') << std::setw(8) << std::hex << handle
+ << std::dec << std::setfill(' ') << "\n";
+ }
+
+ mHandleLock.unlock();
+ }
+ return result.str();
+}
diff --git a/services/oboeservice/AAudioStreamTracker.h b/services/oboeservice/AAudioStreamTracker.h
new file mode 100644
index 0000000..70d440d
--- /dev/null
+++ b/services/oboeservice/AAudioStreamTracker.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAUDIO_AAUDIO_STREAM_TRACKER_H
+#define AAUDIO_AAUDIO_STREAM_TRACKER_H
+
+#include <time.h>
+#include <pthread.h>
+
+#include <aaudio/AAudio.h>
+
+#include "binding/AAudioCommon.h"
+
+#include "AAudioServiceStreamBase.h"
+
+namespace aaudio {
+
+class AAudioStreamTracker {
+
+public:
+ /**
+ * Remove the stream associated with the handle.
+ * @param streamHandle
+ * @return strong pointer to the stream if found or to nullptr
+ */
+ android::sp<AAudioServiceStreamBase> removeStreamByHandle(aaudio_handle_t streamHandle);
+
+ /**
+ * Look up a stream based on the handle.
+ * @param streamHandle
+ * @return strong pointer to the stream if found or to nullptr
+ */
+ android::sp<aaudio::AAudioServiceStreamBase> getStreamByHandle(aaudio_handle_t streamHandle);
+
+ /**
+ * Store a strong pointer to the stream and return a unique handle for future reference.
+ * The handle is guaranteed not to collide with an existing stream.
+ * @param serviceStream
+ * @return handle for identifying the stream
+ */
+ aaudio_handle_t addStreamForHandle(android::sp<AAudioServiceStreamBase> serviceStream);
+
+ /**
+ * @return string that can be added to dumpsys
+ */
+ std::string dump() const;
+
+private:
+ static aaudio_handle_t bumpHandle(aaudio_handle_t handle);
+
+ // Track stream using a unique handle that wraps. Only use positive half.
+ mutable std::mutex mHandleLock;
+ std::atomic<aaudio_handle_t> mPreviousHandle{0};
+ std::map<aaudio_handle_t, android::sp<aaudio::AAudioServiceStreamBase>> mStreamsByHandle;
+};
+
+
+} /* namespace aaudio */
+
+#endif /* AAUDIO_AAUDIO_STREAM_TRACKER_H */
diff --git a/services/oboeservice/Android.mk b/services/oboeservice/Android.mk
index 1b74ad3..584b2ef 100644
--- a/services/oboeservice/Android.mk
+++ b/services/oboeservice/Android.mk
@@ -22,7 +22,6 @@
$(TOP)/frameworks/av/media/libaaudio/src
LOCAL_SRC_FILES += \
- $(LIBAAUDIO_SRC_DIR)/utility/HandleTracker.cpp \
SharedMemoryProxy.cpp \
SharedRingBuffer.cpp \
AAudioClientTracker.cpp \
@@ -37,6 +36,7 @@
AAudioServiceStreamBase.cpp \
AAudioServiceStreamMMAP.cpp \
AAudioServiceStreamShared.cpp \
+ AAudioStreamTracker.cpp \
TimestampScheduler.cpp \
AAudioThread.cpp