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/examples/write_sine/src/write_sine_threaded.cpp b/media/liboboe/examples/write_sine/src/write_sine_threaded.cpp
index aedcc6e..66f018b 100644
--- a/media/liboboe/examples/write_sine/src/write_sine_threaded.cpp
+++ b/media/liboboe/examples/write_sine/src/write_sine_threaded.cpp
@@ -27,6 +27,7 @@
 #include "SineGenerator.h"
 
 #define NUM_SECONDS   10
+
 #define SHARING_MODE  OBOE_SHARING_MODE_EXCLUSIVE
 //#define SHARING_MODE  OBOE_SHARING_MODE_LEGACY
 
@@ -133,15 +134,18 @@
     }
 
     oboe_result_t close() {
-        stop();
-        OboeStream_close(mStream);
-        mStream = OBOE_HANDLE_INVALID;
-        OboeStreamBuilder_delete(mBuilder);
-        mBuilder = OBOE_HANDLE_INVALID;
-        delete mOutputBuffer;
-        mOutputBuffer = nullptr;
-        delete mConversionBuffer;
-        mConversionBuffer = nullptr;
+        if (mStream != OBOE_HANDLE_INVALID) {
+            stop();
+            printf("call OboeStream_close(0x%08x)\n", mStream);  fflush(stdout);
+            OboeStream_close(mStream);
+            mStream = OBOE_HANDLE_INVALID;
+            OboeStreamBuilder_delete(mBuilder);
+            mBuilder = OBOE_HANDLE_INVALID;
+            delete mOutputBuffer;
+            mOutputBuffer = nullptr;
+            delete mConversionBuffer;
+            mConversionBuffer = nullptr;
+        }
         return OBOE_OK;
     }
 
@@ -274,9 +278,9 @@
     printf("player.getFramesPerSecond() = %d\n", player.getFramesPerSecond());
     printf("player.getSamplesPerFrame() = %d\n", player.getSamplesPerFrame());
     myData.sineOsc1.setup(440.0, 48000);
-    myData.sineOsc1.setSweep(300.0, 2000.0, 5.0);
+    myData.sineOsc1.setSweep(300.0, 600.0, 5.0);
     myData.sineOsc2.setup(660.0, 48000);
-    myData.sineOsc2.setSweep(400.0, 3000.0, 7.0);
+    myData.sineOsc2.setSweep(350.0, 900.0, 7.0);
     myData.samplesPerFrame = player.getSamplesPerFrame();
 
     result = player.start();
diff --git a/media/liboboe/include/oboe/OboeAudio.h b/media/liboboe/include/oboe/OboeAudio.h
index 52e3f69..7ad354c 100644
--- a/media/liboboe/include/oboe/OboeAudio.h
+++ b/media/liboboe/include/oboe/OboeAudio.h
@@ -154,7 +154,7 @@
 
 
 /**
- * Request a sample data format, for example OBOE_AUDIO_FORMAT_PCM16.
+ * Request a sample data format, for example OBOE_AUDIO_FORMAT_PCM_I16.
  * The application should query for the actual format after the stream is opened.
  *
  * @return OBOE_OK or a negative error.
diff --git a/media/liboboe/include/oboe/OboeDefinitions.h b/media/liboboe/include/oboe/OboeDefinitions.h
index 9d56a24..9ad7387 100644
--- a/media/liboboe/include/oboe/OboeDefinitions.h
+++ b/media/liboboe/include/oboe/OboeDefinitions.h
@@ -67,12 +67,17 @@
 enum oboe_audio_format_t {
     OBOE_AUDIO_FORMAT_INVALID = -1,
     OBOE_AUDIO_FORMAT_UNSPECIFIED = 0,
-    OBOE_AUDIO_FORMAT_PCM16, // TODO rename to _PCM_I16
+    OBOE_AUDIO_FORMAT_PCM_I16,
     OBOE_AUDIO_FORMAT_PCM_FLOAT,
-    OBOE_AUDIO_FORMAT_PCM824, // TODO rename to _PCM_I8_24
-    OBOE_AUDIO_FORMAT_PCM32  // TODO rename to _PCM_I32
+    OBOE_AUDIO_FORMAT_PCM_I8_24,
+    OBOE_AUDIO_FORMAT_PCM_I32
 };
 
+// TODO These are deprecated. Remove these aliases once all references are replaced.
+#define OBOE_AUDIO_FORMAT_PCM16    OBOE_AUDIO_FORMAT_PCM_I16
+#define OBOE_AUDIO_FORMAT_PCM824   OBOE_AUDIO_FORMAT_PCM_I8_24
+#define OBOE_AUDIO_FORMAT_PCM32    OBOE_AUDIO_FORMAT_PCM_I32
+
 enum {
     OBOE_OK,
     OBOE_ERROR_BASE = -900, // TODO review
@@ -93,7 +98,8 @@
     OBOE_ERROR_TIMEOUT,
     OBOE_ERROR_WOULD_BLOCK,
     OBOE_ERROR_INVALID_ORDER,
-    OBOE_ERROR_OUT_OF_RANGE
+    OBOE_ERROR_OUT_OF_RANGE,
+    OBOE_ERROR_NO_SERVICE
 };
 
 typedef enum {
diff --git a/media/liboboe/src/binding/IOboeAudioService.cpp b/media/liboboe/src/binding/IOboeAudioService.cpp
index a3437b2..2584bc9 100644
--- a/media/liboboe/src/binding/IOboeAudioService.cpp
+++ b/media/liboboe/src/binding/IOboeAudioService.cpp
@@ -20,6 +20,7 @@
 #include "binding/OboeStreamRequest.h"
 #include "binding/OboeStreamConfiguration.h"
 #include "binding/IOboeAudioService.h"
+#include "utility/OboeUtilities.h"
 
 namespace android {
 
@@ -44,7 +45,7 @@
         request.writeToParcel(&data);
         status_t err = remote()->transact(OPEN_STREAM, data, &reply);
         if (err != NO_ERROR) {
-            return OBOE_ERROR_INTERNAL; // TODO consider another error
+            return OboeConvert_androidToOboeResult(err);
         }
         // parse reply
         oboe_handle_t stream;
@@ -53,14 +54,14 @@
         return stream;
     }
 
-    virtual oboe_result_t closeStream(int32_t streamHandle) override {
+    virtual oboe_result_t closeStream(oboe_handle_t streamHandle) override {
         Parcel data, reply;
         // send command
         data.writeInterfaceToken(IOboeAudioService::getInterfaceDescriptor());
         data.writeInt32(streamHandle);
         status_t err = remote()->transact(CLOSE_STREAM, data, &reply);
         if (err != NO_ERROR) {
-            return OBOE_ERROR_INTERNAL; // TODO consider another error
+            return OboeConvert_androidToOboeResult(err);
         }
         // parse reply
         oboe_result_t res;
@@ -69,14 +70,14 @@
     }
 
     virtual oboe_result_t getStreamDescription(oboe_handle_t streamHandle,
-                                               AudioEndpointParcelable &parcelable)   {
+                                               oboe::AudioEndpointParcelable &parcelable)   {
         Parcel data, reply;
         // send command
         data.writeInterfaceToken(IOboeAudioService::getInterfaceDescriptor());
         data.writeInt32(streamHandle);
         status_t err = remote()->transact(GET_STREAM_DESCRIPTION, data, &reply);
         if (err != NO_ERROR) {
-            return OBOE_ERROR_INTERNAL; // TODO consider another error
+            return OboeConvert_androidToOboeResult(err);
         }
         // parse reply
         parcelable.readFromParcel(&reply);
@@ -97,7 +98,7 @@
         data.writeInt32(streamHandle);
         status_t err = remote()->transact(START_STREAM, data, &reply);
         if (err != NO_ERROR) {
-            return OBOE_ERROR_INTERNAL; // TODO consider another error
+            return OboeConvert_androidToOboeResult(err);
         }
         // parse reply
         oboe_result_t res;
@@ -112,7 +113,7 @@
         data.writeInt32(streamHandle);
         status_t err = remote()->transact(PAUSE_STREAM, data, &reply);
         if (err != NO_ERROR) {
-            return OBOE_ERROR_INTERNAL; // TODO consider another error
+            return OboeConvert_androidToOboeResult(err);
         }
         // parse reply
         oboe_result_t res;
@@ -127,7 +128,7 @@
         data.writeInt32(streamHandle);
         status_t err = remote()->transact(FLUSH_STREAM, data, &reply);
         if (err != NO_ERROR) {
-            return OBOE_ERROR_INTERNAL; // TODO consider another error
+            return OboeConvert_androidToOboeResult(err);
         }
         // parse reply
         oboe_result_t res;
@@ -135,13 +136,6 @@
         return res;
     }
 
-    virtual void tickle() override { // TODO remove after service thread implemented
-        Parcel data;
-        // send command
-        data.writeInterfaceToken(IOboeAudioService::getInterfaceDescriptor());
-        remote()->transact(TICKLE, data, nullptr);
-    }
-
     virtual oboe_result_t registerAudioThread(oboe_handle_t streamHandle, pid_t clientThreadId,
                                               oboe_nanoseconds_t periodNanoseconds)
     override {
@@ -153,7 +147,7 @@
         data.writeInt64(periodNanoseconds);
         status_t err = remote()->transact(REGISTER_AUDIO_THREAD, data, &reply);
         if (err != NO_ERROR) {
-            return OBOE_ERROR_INTERNAL; // TODO consider another error
+            return OboeConvert_androidToOboeResult(err);
         }
         // parse reply
         oboe_result_t res;
@@ -170,7 +164,7 @@
         data.writeInt32((int32_t) clientThreadId);
         status_t err = remote()->transact(UNREGISTER_AUDIO_THREAD, data, &reply);
         if (err != NO_ERROR) {
-            return OBOE_ERROR_INTERNAL; // TODO consider another error
+            return OboeConvert_androidToOboeResult(err);
         }
         // parse reply
         oboe_result_t res;
@@ -189,8 +183,8 @@
 status_t BnOboeAudioService::onTransact(uint32_t code, const Parcel& data,
                                         Parcel* reply, uint32_t flags) {
     OboeStream stream;
-    OboeStreamRequest request;
-    OboeStreamConfiguration configuration;
+    oboe::OboeStreamRequest request;
+    oboe::OboeStreamConfiguration configuration;
     pid_t pid;
     oboe_nanoseconds_t nanoseconds;
     oboe_result_t result;
@@ -201,7 +195,7 @@
         case OPEN_STREAM: {
             request.readFromParcel(&data);
             stream = openStream(request, configuration);
-            ALOGD("BnOboeAudioService::onTransact OPEN_STREAM 0x%08X", stream);
+            ALOGD("BnOboeAudioService::onTransact OPEN_STREAM server handle = 0x%08X", stream);
             reply->writeInt32(stream);
             configuration.writeToParcel(reply);
             return NO_ERROR;
@@ -221,12 +215,12 @@
             oboe::AudioEndpointParcelable parcelable;
             result = getStreamDescription(stream, parcelable);
             if (result != OBOE_OK) {
-                return -1; // FIXME
+                return OboeConvert_oboeToAndroidStatus(result);
             }
             parcelable.dump();
             result = parcelable.validate();
             if (result != OBOE_OK) {
-                return -1; // FIXME
+                return OboeConvert_oboeToAndroidStatus(result);
             }
             parcelable.writeToParcel(reply);
             reply->writeInt32(result);
@@ -281,12 +275,6 @@
             return NO_ERROR;
         } break;
 
-        case TICKLE: {
-            ALOGV("BnOboeAudioService::onTransact TICKLE");
-            tickle();
-            return NO_ERROR;
-        } break;
-
         default:
             // ALOGW("BnOboeAudioService::onTransact not handled %u", code);
             return BBinder::onTransact(code, data, reply, flags);
diff --git a/media/liboboe/src/binding/IOboeAudioService.h b/media/liboboe/src/binding/IOboeAudioService.h
index 4b4c99c..e2a9c15 100644
--- a/media/liboboe/src/binding/IOboeAudioService.h
+++ b/media/liboboe/src/binding/IOboeAudioService.h
@@ -29,13 +29,6 @@
 #include "binding/OboeStreamRequest.h"
 #include "binding/OboeStreamConfiguration.h"
 
-//using android::status_t;
-//using android::IInterface;
-//using android::BnInterface;
-
-using oboe::AudioEndpointParcelable;
-using oboe::OboeStreamRequest;
-using oboe::OboeStreamConfiguration;
 
 namespace android {
 
@@ -45,16 +38,16 @@
 
     DECLARE_META_INTERFACE(OboeAudioService);
 
-    virtual oboe_handle_t openStream(OboeStreamRequest &request,
-                                     OboeStreamConfiguration &configuration) = 0;
+    virtual oboe_handle_t openStream(oboe::OboeStreamRequest &request,
+                                     oboe::OboeStreamConfiguration &configuration) = 0;
 
-    virtual oboe_result_t closeStream(int32_t streamHandle) = 0;
+    virtual oboe_result_t closeStream(oboe_handle_t streamHandle) = 0;
 
     /* Get an immutable description of the in-memory queues
     * used to communicate with the underlying HAL or Service.
     */
     virtual oboe_result_t getStreamDescription(oboe_handle_t streamHandle,
-                                               AudioEndpointParcelable &parcelable) = 0;
+                                               oboe::AudioEndpointParcelable &parcelable) = 0;
 
     /**
      * Start the flow of data.
@@ -79,14 +72,6 @@
 
     virtual oboe_result_t unregisterAudioThread(oboe_handle_t streamHandle,
                                                 pid_t clientThreadId) = 0;
-
-    /**
-     * Poke server instead of running a background thread.
-     * Cooperative multi-tasking for early development only.
-     * TODO remove tickle() when service has its own thread.
-     */
-    virtual void tickle() { };
-
 };
 
 class BnOboeAudioService : public BnInterface<IOboeAudioService> {
diff --git a/media/liboboe/src/binding/OboeServiceDefinitions.h b/media/liboboe/src/binding/OboeServiceDefinitions.h
index ad00fe2..33a192f 100644
--- a/media/liboboe/src/binding/OboeServiceDefinitions.h
+++ b/media/liboboe/src/binding/OboeServiceDefinitions.h
@@ -37,8 +37,7 @@
     PAUSE_STREAM,
     FLUSH_STREAM,
     REGISTER_AUDIO_THREAD,
-    UNREGISTER_AUDIO_THREAD,
-    TICKLE
+    UNREGISTER_AUDIO_THREAD
 };
 
 } // namespace android
@@ -53,8 +52,7 @@
     PAUSE_STREAM,
     FLUSH_STREAM,
     REGISTER_AUDIO_THREAD,
-    UNREGISTER_AUDIO_THREAD,
-    TICKLE
+    UNREGISTER_AUDIO_THREAD
 };
 
 // TODO Expand this to include all the open parameters.
diff --git a/media/liboboe/src/binding/OboeStreamConfiguration.cpp b/media/liboboe/src/binding/OboeStreamConfiguration.cpp
index 4b8b5b2..124e964 100644
--- a/media/liboboe/src/binding/OboeStreamConfiguration.cpp
+++ b/media/liboboe/src/binding/OboeStreamConfiguration.cpp
@@ -65,10 +65,10 @@
     }
 
     switch (mAudioFormat) {
-    case OBOE_AUDIO_FORMAT_PCM16:
+    case OBOE_AUDIO_FORMAT_PCM_I16:
     case OBOE_AUDIO_FORMAT_PCM_FLOAT:
-    case OBOE_AUDIO_FORMAT_PCM824:
-    case OBOE_AUDIO_FORMAT_PCM32:
+    case OBOE_AUDIO_FORMAT_PCM_I8_24:
+    case OBOE_AUDIO_FORMAT_PCM_I32:
         break;
     default:
         ALOGE("OboeStreamConfiguration.validate() invalid audioFormat = %d", mAudioFormat);
diff --git a/media/liboboe/src/client/AudioStreamInternal.cpp b/media/liboboe/src/client/AudioStreamInternal.cpp
index 0d169e1..dc6fe90 100644
--- a/media/liboboe/src/client/AudioStreamInternal.cpp
+++ b/media/liboboe/src/client/AudioStreamInternal.cpp
@@ -22,6 +22,7 @@
 #include <assert.h>
 
 #include <binder/IServiceManager.h>
+#include <utils/Mutex.h>
 
 #include <oboe/OboeAudio.h>
 
@@ -40,16 +41,40 @@
 using android::IServiceManager;
 using android::defaultServiceManager;
 using android::interface_cast;
+using android::Mutex;
 
 using namespace oboe;
 
+static android::Mutex gServiceLock;
+static sp<IOboeAudioService>  gOboeService;
+
+#define OBOE_SERVICE_NAME   "OboeAudioService"
+
 // Helper function to get access to the "OboeAudioService" service.
-static sp<IOboeAudioService> getOboeAudioService() {
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16("OboeAudioService"));
-    // TODO: If the "OboeHack" service is not running, getService times out and binder == 0.
-    sp<IOboeAudioService> service = interface_cast<IOboeAudioService>(binder);
-    return service;
+// This code was modeled after frameworks/av/media/libaudioclient/AudioSystem.cpp
+static const sp<IOboeAudioService> getOboeAudioService() {
+    sp<IBinder> binder;
+    Mutex::Autolock _l(gServiceLock);
+    if (gOboeService == 0) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        // Try several times to get the service.
+        int retries = 4;
+        do {
+            binder = sm->getService(String16(OBOE_SERVICE_NAME)); // This will wait a while.
+            if (binder != 0) {
+                break;
+            }
+        } while (retries-- > 0);
+
+        if (binder != 0) {
+            // TODO Add linkToDeath() like in frameworks/av/media/libaudioclient/AudioSystem.cpp
+            // TODO Create a DeathRecipient that disconnects all active streams.
+            gOboeService = interface_cast<IOboeAudioService>(binder);
+        } else {
+            ALOGE("AudioStreamInternal could not get %s", OBOE_SERVICE_NAME);
+        }
+    }
+    return gOboeService;
 }
 
 AudioStreamInternal::AudioStreamInternal()
@@ -59,9 +84,6 @@
         , mServiceStreamHandle(OBOE_HANDLE_INVALID)
         , mFramesPerBurst(16)
 {
-    // TODO protect against mService being NULL;
-    // TODO Model access to the service on frameworks/av/media/libaudioclient/AudioSystem.cpp
-    mService = getOboeAudioService();
 }
 
 AudioStreamInternal::~AudioStreamInternal() {
@@ -69,6 +91,9 @@
 
 oboe_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
 
+    const sp<IOboeAudioService>& service = getOboeAudioService();
+    if (service == 0) return OBOE_ERROR_NO_SERVICE;
+
     oboe_result_t result = OBOE_OK;
     OboeStreamRequest request;
     OboeStreamConfiguration configuration;
@@ -78,7 +103,7 @@
         return result;
     }
 
-    // Build the request.
+    // Build the request to send to the server.
     request.setUserId(getuid());
     request.setProcessId(getpid());
     request.getConfiguration().setDeviceId(getDeviceId());
@@ -87,7 +112,7 @@
     request.getConfiguration().setAudioFormat(getFormat());
     request.dump();
 
-    mServiceStreamHandle = mService->openStream(request, configuration);
+    mServiceStreamHandle = service->openStream(request, configuration);
     ALOGD("AudioStreamInternal.open(): openStream returned mServiceStreamHandle = 0x%08X",
          (unsigned int)mServiceStreamHandle);
     if (mServiceStreamHandle < 0) {
@@ -105,10 +130,10 @@
         setFormat(configuration.getAudioFormat());
 
         oboe::AudioEndpointParcelable parcelable;
-        result = mService->getStreamDescription(mServiceStreamHandle, parcelable);
+        result = service->getStreamDescription(mServiceStreamHandle, parcelable);
         if (result != OBOE_OK) {
             ALOGE("AudioStreamInternal.open(): getStreamDescriptor returns %d", result);
-            mService->closeStream(mServiceStreamHandle);
+            service->closeStream(mServiceStreamHandle);
             return result;
         }
         // resolve parcelable into a descriptor
@@ -133,11 +158,14 @@
 oboe_result_t AudioStreamInternal::close() {
     ALOGD("AudioStreamInternal.close(): mServiceStreamHandle = 0x%08X", mServiceStreamHandle);
     if (mServiceStreamHandle != OBOE_HANDLE_INVALID) {
-        mService->closeStream(mServiceStreamHandle);
+        oboe_handle_t serviceStreamHandle = mServiceStreamHandle;
         mServiceStreamHandle = OBOE_HANDLE_INVALID;
+        const sp<IOboeAudioService>& oboeService = getOboeAudioService();
+        if (oboeService == 0) return OBOE_ERROR_NO_SERVICE;
+        oboeService->closeStream(serviceStreamHandle);
         return OBOE_OK;
     } else {
-        return OBOE_ERROR_INVALID_STATE;
+        return OBOE_ERROR_INVALID_HANDLE;
     }
 }
 
@@ -148,11 +176,13 @@
     if (mServiceStreamHandle == OBOE_HANDLE_INVALID) {
         return OBOE_ERROR_INVALID_STATE;
     }
+    const sp<IOboeAudioService>& oboeService = getOboeAudioService();
+    if (oboeService == 0) return OBOE_ERROR_NO_SERVICE;
     startTime = Oboe_getNanoseconds(OBOE_CLOCK_MONOTONIC);
     mClockModel.start(startTime);
     processTimestamp(0, startTime);
     setState(OBOE_STREAM_STATE_STARTING);
-    return mService->startStream(mServiceStreamHandle);
+    return oboeService->startStream(mServiceStreamHandle);
 }
 
 oboe_result_t AudioStreamInternal::requestPause()
@@ -161,9 +191,11 @@
     if (mServiceStreamHandle == OBOE_HANDLE_INVALID) {
         return OBOE_ERROR_INVALID_STATE;
     }
+    const sp<IOboeAudioService>& oboeService = getOboeAudioService();
+    if (oboeService == 0) return OBOE_ERROR_NO_SERVICE;
     mClockModel.stop(Oboe_getNanoseconds(OBOE_CLOCK_MONOTONIC));
     setState(OBOE_STREAM_STATE_PAUSING);
-    return mService->pauseStream(mServiceStreamHandle);
+    return oboeService->pauseStream(mServiceStreamHandle);
 }
 
 oboe_result_t AudioStreamInternal::requestFlush() {
@@ -171,8 +203,10 @@
     if (mServiceStreamHandle == OBOE_HANDLE_INVALID) {
         return OBOE_ERROR_INVALID_STATE;
     }
-    setState(OBOE_STREAM_STATE_FLUSHING);
-    return mService->flushStream(mServiceStreamHandle);
+    const sp<IOboeAudioService>& oboeService = getOboeAudioService();
+    if (oboeService == 0) return OBOE_ERROR_NO_SERVICE;
+setState(OBOE_STREAM_STATE_FLUSHING);
+    return oboeService->flushStream(mServiceStreamHandle);
 }
 
 void AudioStreamInternal::onFlushFromServer() {
@@ -208,7 +242,9 @@
     if (mServiceStreamHandle == OBOE_HANDLE_INVALID) {
         return OBOE_ERROR_INVALID_STATE;
     }
-    return mService->registerAudioThread(mServiceStreamHandle,
+    const sp<IOboeAudioService>& oboeService = getOboeAudioService();
+    if (oboeService == 0) return OBOE_ERROR_NO_SERVICE;
+    return oboeService->registerAudioThread(mServiceStreamHandle,
                                          gettid(),
                                          getPeriodNanoseconds());
 }
@@ -218,7 +254,9 @@
     if (mServiceStreamHandle == OBOE_HANDLE_INVALID) {
         return OBOE_ERROR_INVALID_STATE;
     }
-    return mService->unregisterAudioThread(mServiceStreamHandle, gettid());
+    const sp<IOboeAudioService>& oboeService = getOboeAudioService();
+    if (oboeService == 0) return OBOE_ERROR_NO_SERVICE;
+    return oboeService->unregisterAudioThread(mServiceStreamHandle, gettid());
 }
 
 // TODO use oboe_clockid_t all the way down to AudioClock
@@ -305,9 +343,6 @@
 oboe_result_t AudioStreamInternal::processCommands() {
     oboe_result_t result = OBOE_OK;
 
-    // Let the service run in case it is a fake service simulator.
-    mService->tickle(); // TODO use real service thread
-
     while (result == OBOE_OK) {
         OboeServiceMessage message;
         if (mAudioEndpoint.readUpCommand(&message) != 1) {
diff --git a/media/liboboe/src/client/AudioStreamInternal.h b/media/liboboe/src/client/AudioStreamInternal.h
index 6f37761..9459f97 100644
--- a/media/liboboe/src/client/AudioStreamInternal.h
+++ b/media/liboboe/src/client/AudioStreamInternal.h
@@ -114,7 +114,6 @@
     AudioEndpoint            mAudioEndpoint;
     oboe_handle_t            mServiceStreamHandle;
     EndpointDescriptor       mEndpointDescriptor;
-    sp<IOboeAudioService>    mService;
     // Offset from underlying frame position.
     oboe_position_frames_t   mFramesOffsetFromService = 0;
     oboe_position_frames_t   mLastFramesRead = 0;
diff --git a/media/liboboe/src/core/OboeAudio.cpp b/media/liboboe/src/core/OboeAudio.cpp
index d98ca36..be563b5 100644
--- a/media/liboboe/src/core/OboeAudio.cpp
+++ b/media/liboboe/src/core/OboeAudio.cpp
@@ -96,6 +96,7 @@
         OBOE_CASE_ENUM(OBOE_ERROR_WOULD_BLOCK);
         OBOE_CASE_ENUM(OBOE_ERROR_INVALID_ORDER);
         OBOE_CASE_ENUM(OBOE_ERROR_OUT_OF_RANGE);
+        OBOE_CASE_ENUM(OBOE_ERROR_NO_SERVICE);
     }
     return "Unrecognized Oboe error.";
 }
@@ -285,7 +286,6 @@
 
 OBOE_API oboe_result_t  OboeStreamBuilder_delete(OboeStreamBuilder builder)
 {
-    // TODO protect the remove() with a Mutex
     AudioStreamBuilder *streamBuilder = (AudioStreamBuilder *)
             sHandleTracker.remove(OBOE_HANDLE_TYPE_STREAM_BUILDER, builder);
     if (streamBuilder != nullptr) {
@@ -297,9 +297,9 @@
 
 OBOE_API oboe_result_t  OboeStream_close(OboeStream stream)
 {
-    // TODO protect the remove() with a Mutex
     AudioStream *audioStream = (AudioStream *)
             sHandleTracker.remove(OBOE_HANDLE_TYPE_STREAM, (oboe_handle_t)stream);
+    ALOGD("OboeStream_close(0x%08X), audioStream = %p", stream, audioStream);
     if (audioStream != nullptr) {
         audioStream->close();
         delete audioStream;
diff --git a/media/liboboe/src/legacy/AudioStreamRecord.cpp b/media/liboboe/src/legacy/AudioStreamRecord.cpp
index 5854974..bf4bd36 100644
--- a/media/liboboe/src/legacy/AudioStreamRecord.cpp
+++ b/media/liboboe/src/legacy/AudioStreamRecord.cpp
@@ -90,7 +90,7 @@
     if (status != OK) {
         close();
         ALOGE("AudioStreamRecord::open(), initCheck() returned %d", status);
-        return OboeConvert_androidToOboeError(status);
+        return OboeConvert_androidToOboeResult(status);
     }
 
     // Get the actual rate.
@@ -121,11 +121,11 @@
     // Get current position so we can detect when the track is playing.
     status_t err = mAudioRecord->getPosition(&mPositionWhenStarting);
     if (err != OK) {
-        return OboeConvert_androidToOboeError(err);
+        return OboeConvert_androidToOboeResult(err);
     }
     err = mAudioRecord->start();
     if (err != OK) {
-        return OboeConvert_androidToOboeError(err);
+        return OboeConvert_androidToOboeResult(err);
     } else {
         setState(OBOE_STREAM_STATE_STARTING);
     }
@@ -160,7 +160,7 @@
     case OBOE_STREAM_STATE_STARTING:
         err = mAudioRecord->getPosition(&position);
         if (err != OK) {
-            result = OboeConvert_androidToOboeError(err);
+            result = OboeConvert_androidToOboeResult(err);
         } else if (position != mPositionWhenStarting) {
             setState(OBOE_STREAM_STATE_STARTED);
         }
@@ -193,7 +193,7 @@
     if (bytesRead == WOULD_BLOCK) {
         return 0;
     } else if (bytesRead < 0) {
-        return OboeConvert_androidToOboeError(bytesRead);
+        return OboeConvert_androidToOboeResult(bytesRead);
     }
     oboe_size_frames_t framesRead = (oboe_size_frames_t)(bytesRead / bytesPerFrame);
     return (oboe_result_t) framesRead;
diff --git a/media/liboboe/src/legacy/AudioStreamRecord.h b/media/liboboe/src/legacy/AudioStreamRecord.h
index 02ff220..a884ed2 100644
--- a/media/liboboe/src/legacy/AudioStreamRecord.h
+++ b/media/liboboe/src/legacy/AudioStreamRecord.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef LEGACY_AUDIOSTREAMRECORD_H
-#define LEGACY_AUDIOSTREAMRECORD_H
+#ifndef LEGACY_AUDIO_STREAM_RECORD_H
+#define LEGACY_AUDIO_STREAM_RECORD_H
 
 #include <media/AudioRecord.h>
 #include <oboe/OboeAudio.h>
@@ -75,4 +75,4 @@
 
 } /* namespace oboe */
 
-#endif /* LEGACY_AUDIOSTREAMRECORD_H */
+#endif /* LEGACY_AUDIO_STREAM_RECORD_H */
diff --git a/media/liboboe/src/legacy/AudioStreamTrack.cpp b/media/liboboe/src/legacy/AudioStreamTrack.cpp
index b2c4ee1..291e56c 100644
--- a/media/liboboe/src/legacy/AudioStreamTrack.cpp
+++ b/media/liboboe/src/legacy/AudioStreamTrack.cpp
@@ -87,12 +87,10 @@
     // Did we get a valid track?
     status_t status = mAudioTrack->initCheck();
     ALOGD("AudioStreamTrack::open(), initCheck() returned %d", status);
-    // FIXME - this should work - if (status != NO_ERROR) {
-    //         But initCheck() is returning 1 !
-    if (status < 0) {
+    if (status != NO_ERROR) {
         close();
         ALOGE("AudioStreamTrack::open(), initCheck() returned %d", status);
-        return OboeConvert_androidToOboeError(status);
+        return OboeConvert_androidToOboeResult(status);
     }
 
     // Get the actual values from the AudioTrack.
@@ -123,11 +121,11 @@
     // Get current position so we can detect when the track is playing.
     status_t err = mAudioTrack->getPosition(&mPositionWhenStarting);
     if (err != OK) {
-        return OboeConvert_androidToOboeError(err);
+        return OboeConvert_androidToOboeResult(err);
     }
     err = mAudioTrack->start();
     if (err != OK) {
-        return OboeConvert_androidToOboeError(err);
+        return OboeConvert_androidToOboeResult(err);
     } else {
         setState(OBOE_STREAM_STATE_STARTING);
     }
@@ -147,7 +145,7 @@
     mAudioTrack->pause();
     status_t err = mAudioTrack->getPosition(&mPositionWhenPausing);
     if (err != OK) {
-        return OboeConvert_androidToOboeError(err);
+        return OboeConvert_androidToOboeResult(err);
     }
     return OBOE_OK;
 }
@@ -191,7 +189,7 @@
         if (mAudioTrack->stopped()) {
             err = mAudioTrack->getPosition(&position);
             if (err != OK) {
-                return OboeConvert_androidToOboeError(err);
+                return OboeConvert_androidToOboeResult(err);
             } else if (position == mPositionWhenPausing) {
                 // Has stream really stopped advancing?
                 setState(OBOE_STREAM_STATE_PAUSED);
@@ -203,7 +201,7 @@
         {
             err = mAudioTrack->getPosition(&position);
             if (err != OK) {
-                return OboeConvert_androidToOboeError(err);
+                return OboeConvert_androidToOboeResult(err);
             } else if (position == 0) {
                 // Advance frames read to match written.
                 setState(OBOE_STREAM_STATE_FLUSHED);
@@ -239,7 +237,7 @@
         return 0;
     } else if (bytesWritten < 0) {
         ALOGE("invalid write, returned %d", (int)bytesWritten);
-        return OboeConvert_androidToOboeError(bytesWritten);
+        return OboeConvert_androidToOboeResult(bytesWritten);
     }
     oboe_size_frames_t framesWritten = (oboe_size_frames_t)(bytesWritten / bytesPerFrame);
     incrementFramesWritten(framesWritten);
@@ -251,7 +249,7 @@
 {
     ssize_t result = mAudioTrack->setBufferSizeInFrames(requestedFrames);
     if (result != OK) {
-        return OboeConvert_androidToOboeError(result);
+        return OboeConvert_androidToOboeResult(result);
     } else {
         *actualFrames = result;
         return OBOE_OK;
diff --git a/media/liboboe/src/legacy/AudioStreamTrack.h b/media/liboboe/src/legacy/AudioStreamTrack.h
index 8c40884..0c41331 100644
--- a/media/liboboe/src/legacy/AudioStreamTrack.h
+++ b/media/liboboe/src/legacy/AudioStreamTrack.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef LEGACY_AUDIOSTREAMTRACK_H
-#define LEGACY_AUDIOSTREAMTRACK_H
+#ifndef LEGACY_AUDIO_STREAM_TRACK_H
+#define LEGACY_AUDIO_STREAM_TRACK_H
 
 #include <media/AudioTrack.h>
 #include <oboe/OboeAudio.h>
@@ -75,4 +75,4 @@
 
 } /* namespace oboe */
 
-#endif /* LEGACY_AUDIOSTREAMTRACK_H */
+#endif /* LEGACY_AUDIO_STREAM_TRACK_H */
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