OboeAudioService: add thread to service for passing timestamps
Cleanup several TODOs.
Test: test_aaudio in CTS
Change-Id: I7fc956b6a21cbb592f98e1e5a8f43ebd6926d796
Signed-off-by: Phil Burk <philburk@google.com>
diff --git a/media/liboboe/src/utility/AudioClock.h b/media/liboboe/src/utility/AudioClock.h
index 1a5c209..1779d8b 100644
--- a/media/liboboe/src/utility/AudioClock.h
+++ b/media/liboboe/src/utility/AudioClock.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef UTILITY_AUDIOCLOCK_H
-#define UTILITY_AUDIOCLOCK_H
+#ifndef UTILITY_AUDIO_CLOCK_H
+#define UTILITY_AUDIO_CLOCK_H
#include <stdint.h>
#include <time.h>
@@ -95,4 +95,4 @@
};
-#endif // UTILITY_AUDIOCLOCK_H
+#endif // UTILITY_AUDIO_CLOCK_H
diff --git a/media/liboboe/src/utility/HandleTracker.cpp b/media/liboboe/src/utility/HandleTracker.cpp
index bf5fb63..27cc1f8 100644
--- a/media/liboboe/src/utility/HandleTracker.cpp
+++ b/media/liboboe/src/utility/HandleTracker.cpp
@@ -19,13 +19,16 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <assert.h>
#include <new>
#include <stdint.h>
-#include <assert.h>
+#include <utils/Mutex.h>
#include <oboe/OboeDefinitions.h>
#include "HandleTracker.h"
+using android::Mutex;
+
// Handle format is: tgggiiii
// where each letter is 4 bits, t=type, g=generation, i=index
@@ -80,15 +83,17 @@
HandleTracker::~HandleTracker()
{
+ Mutex::Autolock _l(mLock);
delete[] mHandleAddresses;
delete[] mHandleHeaders;
+ mHandleAddresses = nullptr;
}
bool HandleTracker::isInitialized() const {
return mHandleAddresses != nullptr;
}
-handle_tracker_slot_t HandleTracker::allocateSlot() {
+handle_tracker_slot_t HandleTracker::allocateSlot_l() {
void **allocated = mNextFreeAddress;
if (allocated == nullptr) {
return SLOT_UNAVAILABLE;
@@ -98,7 +103,7 @@
return (allocated - mHandleAddresses);
}
-handle_tracker_generation_t HandleTracker::nextGeneration(handle_tracker_slot_t index) {
+handle_tracker_generation_t HandleTracker::nextGeneration_l(handle_tracker_slot_t index) {
handle_tracker_generation_t generation = (mHandleHeaders[index] + 1) & GENERATION_MASK;
// Avoid generation zero so that 0x0 is not a valid handle.
if (generation == GENERATION_INVALID) {
@@ -116,15 +121,17 @@
return static_cast<oboe_handle_t>(OBOE_ERROR_NO_MEMORY);
}
+ Mutex::Autolock _l(mLock);
+
// Find an empty slot.
- handle_tracker_slot_t index = allocateSlot();
+ handle_tracker_slot_t index = allocateSlot_l();
if (index == SLOT_UNAVAILABLE) {
ALOGE("HandleTracker::put() no room for more handles");
return static_cast<oboe_handle_t>(OBOE_ERROR_NO_FREE_HANDLES);
}
// Cycle the generation counter so stale handles can be detected.
- handle_tracker_generation_t generation = nextGeneration(index); // reads header table
+ handle_tracker_generation_t generation = nextGeneration_l(index); // reads header table
handle_tracker_header_t inputHeader = buildHeader(type, generation);
// These two writes may need to be observed by other threads or cores during get().
@@ -150,6 +157,8 @@
}
handle_tracker_generation_t handleGeneration = extractGeneration(handle);
handle_tracker_header_t inputHeader = buildHeader(type, handleGeneration);
+ // We do not need to synchronize this access to mHandleHeaders because it is constant for
+ // the lifetime of the handle.
if (inputHeader != mHandleHeaders[index]) {
ALOGE("HandleTracker::handleToIndex() inputHeader = 0x%08x != mHandleHeaders[%d] = 0x%08x",
inputHeader, index, mHandleHeaders[index]);
@@ -165,6 +174,8 @@
}
handle_tracker_slot_t index = handleToIndex(type, handle);
if (index >= 0) {
+ // We do not need to synchronize this access to mHandleHeaders because this slot
+ // is allocated and, therefore, not part of the linked list of free slots.
return mHandleAddresses[index];
} else {
return nullptr;
@@ -175,6 +186,9 @@
if (!isInitialized()) {
return nullptr;
}
+
+ Mutex::Autolock _l(mLock);
+
handle_tracker_slot_t index = handleToIndex(type,handle);
if (index >= 0) {
handle_tracker_address_t address = mHandleAddresses[index];
diff --git a/media/liboboe/src/utility/HandleTracker.h b/media/liboboe/src/utility/HandleTracker.h
index 4c08321..f1bead8 100644
--- a/media/liboboe/src/utility/HandleTracker.h
+++ b/media/liboboe/src/utility/HandleTracker.h
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#ifndef UTILITY_HANDLETRACKER_H
-#define UTILITY_HANDLETRACKER_H
+#ifndef UTILITY_HANDLE_TRACKER_H
+#define UTILITY_HANDLE_TRACKER_H
#include <stdint.h>
+#include <utils/Mutex.h>
typedef int32_t handle_tracker_type_t; // what kind of handle
typedef int32_t handle_tracker_slot_t; // index in allocation table
@@ -53,6 +54,8 @@
/**
* Store a pointer and return a handle that can be used to retrieve the pointer.
*
+ * It is safe to call put() or remove() from multiple threads.
+ *
* @param expectedType the type of the object to be tracked
* @param address pointer to be converted to a handle
* @return a valid handle or a negative error
@@ -75,6 +78,8 @@
* Free up the storage associated with the handle.
* Subsequent attempts to use the handle will fail.
*
+ * Do NOT remove() a handle while get() is being called for the same handle from another thread.
+ *
* @param expectedType shouldmatch the type we passed to put()
* @param handle to be removed from tracking
* @return address associated with handle or nullptr if not found
@@ -83,17 +88,28 @@
private:
const int32_t mMaxHandleCount; // size of array
- // This is const after initialization.
+ // This address is const after initialization.
handle_tracker_address_t * mHandleAddresses; // address of objects or a free linked list node
- // This is const after initialization.
+ // This address is const after initialization.
handle_tracker_header_t * mHandleHeaders; // combination of type and generation
- handle_tracker_address_t * mNextFreeAddress; // head of the linked list of free nodes in mHandleAddresses
+ // head of the linked list of free nodes in mHandleAddresses
+ handle_tracker_address_t * mNextFreeAddress;
+
+ // This Mutex protects the linked list of free nodes.
+ // The list is managed using mHandleAddresses and mNextFreeAddress.
+ // The data in mHandleHeaders is only changed by put() and remove().
+ android::Mutex mLock;
/**
* Pull slot off of a list of empty slots.
* @return index or a negative error
*/
- handle_tracker_slot_t allocateSlot();
+ handle_tracker_slot_t allocateSlot_l();
+
+ /**
+ * Increment the generation for the slot, avoiding zero.
+ */
+ handle_tracker_generation_t nextGeneration_l(handle_tracker_slot_t index);
/**
* Validate the handle and return the corresponding index.
@@ -107,7 +123,7 @@
* @param index slot index returned from allocateSlot
* @return handle or a negative error
*/
- oboe_handle_t buildHandle(handle_tracker_header_t header, handle_tracker_slot_t index);
+ static oboe_handle_t buildHandle(handle_tracker_header_t header, handle_tracker_slot_t index);
/**
* Combine a type and a generation field into a header.
@@ -129,11 +145,6 @@
*/
static handle_tracker_generation_t extractGeneration(oboe_handle_t handle);
- /**
- * Increment the generation for the slot, avoiding zero.
- */
- handle_tracker_generation_t nextGeneration(handle_tracker_slot_t index);
-
};
-#endif //UTILITY_HANDLETRACKER_H
+#endif //UTILITY_HANDLE_TRACKER_H
diff --git a/media/liboboe/src/utility/MonotonicCounter.h b/media/liboboe/src/utility/MonotonicCounter.h
index befad21..81d7f89 100644
--- a/media/liboboe/src/utility/MonotonicCounter.h
+++ b/media/liboboe/src/utility/MonotonicCounter.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef UTILITY_MONOTONICCOUNTER_H
-#define UTILITY_MONOTONICCOUNTER_H
+#ifndef UTILITY_MONOTONIC_COUNTER_H
+#define UTILITY_MONOTONIC_COUNTER_H
#include <stdint.h>
@@ -88,4 +88,4 @@
};
-#endif //UTILITY_MONOTONICCOUNTER_H
+#endif //UTILITY_MONOTONIC_COUNTER_H
diff --git a/media/liboboe/src/utility/OboeUtilities.cpp b/media/liboboe/src/utility/OboeUtilities.cpp
index d9d2e88..fcf4252 100644
--- a/media/liboboe/src/utility/OboeUtilities.cpp
+++ b/media/liboboe/src/utility/OboeUtilities.cpp
@@ -30,11 +30,11 @@
oboe_size_bytes_t OboeConvert_formatToSizeInBytes(oboe_audio_format_t format) {
oboe_size_bytes_t size = OBOE_ERROR_ILLEGAL_ARGUMENT;
switch (format) {
- case OBOE_AUDIO_FORMAT_PCM16:
+ case OBOE_AUDIO_FORMAT_PCM_I16:
size = sizeof(int16_t);
break;
- case OBOE_AUDIO_FORMAT_PCM32:
- case OBOE_AUDIO_FORMAT_PCM824:
+ case OBOE_AUDIO_FORMAT_PCM_I32:
+ case OBOE_AUDIO_FORMAT_PCM_I8_24:
size = sizeof(int32_t);
break;
case OBOE_AUDIO_FORMAT_PCM_FLOAT:
@@ -67,14 +67,47 @@
}
}
-oboe_result_t OboeConvert_androidToOboeError(status_t error) {
- if (error >= 0) {
- return error;
+status_t OboeConvert_oboeToAndroidStatus(oboe_result_t result) {
+ // This covers the case for OBOE_OK and for positive results.
+ if (result >= 0) {
+ return result;
+ }
+ status_t status;
+ switch (result) {
+ case OBOE_ERROR_DISCONNECTED:
+ case OBOE_ERROR_INVALID_HANDLE:
+ status = DEAD_OBJECT;
+ break;
+ case OBOE_ERROR_INVALID_STATE:
+ status = INVALID_OPERATION;
+ break;
+ case OBOE_ERROR_UNEXPECTED_VALUE: // TODO redundant?
+ case OBOE_ERROR_ILLEGAL_ARGUMENT:
+ status = BAD_VALUE;
+ break;
+ case OBOE_ERROR_WOULD_BLOCK:
+ status = WOULD_BLOCK;
+ break;
+ // TODO add more result codes
+ default:
+ status = UNKNOWN_ERROR;
+ break;
+ }
+ return status;
+}
+
+oboe_result_t OboeConvert_androidToOboeResult(status_t status) {
+ // This covers the case for OK and for positive result.
+ if (status >= 0) {
+ return status;
}
oboe_result_t result;
- switch (error) {
- case OK:
- result = OBOE_OK;
+ switch (status) {
+ case BAD_TYPE:
+ result = OBOE_ERROR_INVALID_HANDLE;
+ break;
+ case DEAD_OBJECT:
+ result = OBOE_ERROR_DISCONNECTED;
break;
case INVALID_OPERATION:
result = OBOE_ERROR_INVALID_STATE;
@@ -85,7 +118,7 @@
case WOULD_BLOCK:
result = OBOE_ERROR_WOULD_BLOCK;
break;
- // TODO add more error codes
+ // TODO add more status codes
default:
result = OBOE_ERROR_INTERNAL;
break;
@@ -96,16 +129,16 @@
audio_format_t OboeConvert_oboeToAndroidDataFormat(oboe_audio_format_t oboeFormat) {
audio_format_t androidFormat;
switch (oboeFormat) {
- case OBOE_AUDIO_FORMAT_PCM16:
+ case OBOE_AUDIO_FORMAT_PCM_I16:
androidFormat = AUDIO_FORMAT_PCM_16_BIT;
break;
case OBOE_AUDIO_FORMAT_PCM_FLOAT:
androidFormat = AUDIO_FORMAT_PCM_FLOAT;
break;
- case OBOE_AUDIO_FORMAT_PCM824:
+ case OBOE_AUDIO_FORMAT_PCM_I8_24:
androidFormat = AUDIO_FORMAT_PCM_8_24_BIT;
break;
- case OBOE_AUDIO_FORMAT_PCM32:
+ case OBOE_AUDIO_FORMAT_PCM_I32:
androidFormat = AUDIO_FORMAT_PCM_32_BIT;
break;
default:
@@ -120,16 +153,16 @@
oboe_audio_format_t oboeFormat = OBOE_AUDIO_FORMAT_INVALID;
switch (androidFormat) {
case AUDIO_FORMAT_PCM_16_BIT:
- oboeFormat = OBOE_AUDIO_FORMAT_PCM16;
+ oboeFormat = OBOE_AUDIO_FORMAT_PCM_I16;
break;
case AUDIO_FORMAT_PCM_FLOAT:
oboeFormat = OBOE_AUDIO_FORMAT_PCM_FLOAT;
break;
case AUDIO_FORMAT_PCM_32_BIT:
- oboeFormat = OBOE_AUDIO_FORMAT_PCM32;
+ oboeFormat = OBOE_AUDIO_FORMAT_PCM_I32;
break;
case AUDIO_FORMAT_PCM_8_24_BIT:
- oboeFormat = OBOE_AUDIO_FORMAT_PCM824;
+ oboeFormat = OBOE_AUDIO_FORMAT_PCM_I8_24;
break;
default:
oboeFormat = OBOE_AUDIO_FORMAT_INVALID;
diff --git a/media/liboboe/src/utility/OboeUtilities.h b/media/liboboe/src/utility/OboeUtilities.h
index 974ccf6..4096e2a 100644
--- a/media/liboboe/src/utility/OboeUtilities.h
+++ b/media/liboboe/src/utility/OboeUtilities.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef UTILITY_OBOEUTILITIES_H
-#define UTILITY_OBOEUTILITIES_H
+#ifndef UTILITY_OBOE_UTILITIES_H
+#define UTILITY_OBOE_UTILITIES_H
#include <stdint.h>
#include <sys/types.h>
@@ -25,7 +25,15 @@
#include "oboe/OboeDefinitions.h"
-oboe_result_t OboeConvert_androidToOboeError(android::status_t error);
+/**
+ * Convert an Oboe result into the closest matching Android status.
+ */
+android::status_t OboeConvert_oboeToAndroidStatus(oboe_result_t result);
+
+/**
+ * Convert an Android status into the closest matching Oboe result.
+ */
+oboe_result_t OboeConvert_androidToOboeResult(android::status_t status);
void OboeConvert_floatToPcm16(const float *source, int32_t numSamples, int16_t *destination);
@@ -51,4 +59,4 @@
*/
oboe_size_bytes_t OboeConvert_formatToSizeInBytes(oboe_audio_format_t format);
-#endif //UTILITY_OBOEUTILITIES_H
+#endif //UTILITY_OBOE_UTILITIES_H