liboboe: general cleanup of core code, register threads

Simplify audio format.
Cleaner includes.
Some debug printing.
Add registration of audio threads with server.

Bug: 33347409
Test: test_oboe_api
Change-Id: I342eb745830d6623681ce55cb510513e7c5e2ead
Signed-off-by: Phil Burk <philburk@google.com>
diff --git a/media/liboboe/include/oboe/OboeAudio.h b/media/liboboe/include/oboe/OboeAudio.h
index 2181b8c..52e3f69 100644
--- a/media/liboboe/include/oboe/OboeAudio.h
+++ b/media/liboboe/include/oboe/OboeAudio.h
@@ -26,7 +26,6 @@
 extern "C" {
 #endif
 
-typedef int32_t OboeDeviceId;
 typedef oboe_handle_t OboeStream;
 typedef oboe_handle_t OboeStreamBuilder;
 
@@ -92,10 +91,18 @@
  *
  * By default, the primary device will be used.
  *
+ * @param builder handle provided by Oboe_createStreamBuilder()
+ * @param deviceId platform specific identifier or OBOE_DEVICE_UNSPECIFIED
  * @return OBOE_OK or a negative error.
  */
 OBOE_API oboe_result_t OboeStreamBuilder_setDeviceId(OboeStreamBuilder builder,
-                                                     OboeDeviceId deviceId);
+                                                     oboe_device_id_t deviceId);
+/**
+ * Passes back requested device ID.
+ * @return OBOE_OK or a negative error.
+ */
+OBOE_API oboe_result_t OboeStreamBuilder_getDeviceId(OboeStreamBuilder builder,
+                                                     oboe_device_id_t *deviceId);
 
 /**
  * Request a sample rate in Hz.
@@ -111,14 +118,14 @@
  * @return OBOE_OK or a negative error.
  */
 OBOE_API oboe_result_t OboeStreamBuilder_setSampleRate(OboeStreamBuilder builder,
-                                              oboe_sample_rate_t sampleRate);
+                                                       oboe_sample_rate_t sampleRate);
 
 /**
  * Returns sample rate in Hertz (samples per second).
  * @return OBOE_OK or a negative error.
  */
 OBOE_API oboe_result_t OboeStreamBuilder_getSampleRate(OboeStreamBuilder builder,
-                                              oboe_sample_rate_t *sampleRate);
+                                                       oboe_sample_rate_t *sampleRate);
 
 
 /**
@@ -362,6 +369,8 @@
 // High priority audio threads
 // ============================================================
 
+typedef void *(oboe_audio_thread_proc_t)(void *);
+
 /**
  * Create a thread associated with a stream. The thread has special properties for
  * low latency audio performance. This thread can be used to implement a callback API.
@@ -378,7 +387,8 @@
  */
 OBOE_API oboe_result_t OboeStream_createThread(OboeStream stream,
                                      oboe_nanoseconds_t periodNanoseconds,
-                                     void *(*startRoutine)(void *), void *arg);
+                                     oboe_audio_thread_proc_t *threadProc,
+                                     void *arg);
 
 /**
  * Wait until the thread exits or an error occurs.
@@ -475,6 +485,13 @@
 
 /**
  * @param stream handle provided by OboeStreamBuilder_openStream()
+ * @param deviceId pointer to variable to receive the actual device ID
+ * @return OBOE_OK or a negative error.
+ */
+OBOE_API oboe_result_t OboeStream_getDeviceId(OboeStream stream, oboe_device_id_t *deviceId);
+
+/**
+ * @param stream handle provided by OboeStreamBuilder_openStream()
  * @param format pointer to variable to receive the actual data format
  * @return OBOE_OK or a negative error.
  */
@@ -554,4 +571,4 @@
 }
 #endif
 
-#endif //NATIVEOBOE_OBOEAUDIO_H
+#endif //OBOE_OBOEAUDIO_H
diff --git a/media/liboboe/include/oboe/OboeDefinitions.h b/media/liboboe/include/oboe/OboeDefinitions.h
index d80c958..9d56a24 100644
--- a/media/liboboe/include/oboe/OboeDefinitions.h
+++ b/media/liboboe/include/oboe/OboeDefinitions.h
@@ -25,6 +25,10 @@
 
 typedef int32_t  oboe_handle_t; // negative handles are error codes
 typedef int32_t  oboe_result_t;
+/**
+ * A platform specific identifier for a device.
+ */
+typedef int32_t  oboe_device_id_t;
 typedef int32_t  oboe_sample_rate_t;
 /** This is used for small quantities such as the number of frames in a buffer. */
 typedef int32_t  oboe_size_frames_t;
@@ -38,7 +42,6 @@
 typedef int64_t  oboe_position_frames_t;
 
 typedef int64_t  oboe_nanoseconds_t;
-typedef uint32_t oboe_audio_format_t;
 
 /**
  * This is used to represent a value that has not been specified.
@@ -47,6 +50,7 @@
  * and would accept whatever it was given.
  */
 #define OBOE_UNSPECIFIED           0
+#define OBOE_DEVICE_UNSPECIFIED    ((oboe_device_id_t) -1)
 #define OBOE_NANOS_PER_MICROSECOND ((int64_t)1000)
 #define OBOE_NANOS_PER_MILLISECOND (OBOE_NANOS_PER_MICROSECOND * 1000)
 #define OBOE_MILLIS_PER_SECOND     1000
@@ -60,60 +64,15 @@
     OBOE_DIRECTION_COUNT // This should always be last.
 };
 
-enum oboe_datatype_t {
-    OBOE_AUDIO_DATATYPE_INT16,
-    OBOE_AUDIO_DATATYPE_INT32,
-    OBOE_AUDIO_DATATYPE_INT824,
-    OBOE_AUDIO_DATATYPE_UINT8,
-    OBOE_AUDIO_DATATYPE_FLOAT32, // Add new values below.
-    OBOE_AUDIO_DATATYPE_COUNT // This should always be last.
+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_FLOAT,
+    OBOE_AUDIO_FORMAT_PCM824, // TODO rename to _PCM_I8_24
+    OBOE_AUDIO_FORMAT_PCM32  // TODO rename to _PCM_I32
 };
 
-enum oboe_content_t {
-    OBOE_AUDIO_CONTENT_PCM,
-    OBOE_AUDIO_CONTENT_MP3,
-    OBOE_AUDIO_CONTENT_AAC,
-    OBOE_AUDIO_CONTENT_AC3,
-    OBOE_AUDIO_CONTENT_EAC3,
-    OBOE_AUDIO_CONTENT_DTS,
-    OBOE_AUDIO_CONTENT_DTSHD, // Add new values below.
-    OBOE_AUDIO_CONTENT_COUNT // This should always be last.
-};
-
-enum oboe_wrapper_t {
-    OBOE_AUDIO_WRAPPER_NONE,
-    OBOE_AUDIO_WRAPPER_IEC61937, // Add new values below.
-    OBOE_AUDIO_WRAPPER_COUNT // This should always be last.
-};
-
-/**
- * Fields packed into oboe_audio_format_t, from most to least significant bits.
- *   Invalid:1
- *   Reserved:7
- *   Wrapper:8
- *   Content:8
- *   Data Type:8
- */
-#define OBOE_AUDIO_FORMAT(dataType, content, wrapper) \
-    ((oboe_audio_format_t)((wrapper << 16) | (content << 8) | dataType))
-
-#define OBOE_AUDIO_FORMAT_RAW(dataType, content) \
-                OBOE_AUDIO_FORMAT(dataType, content, OBOE_AUDIO_WRAPPER_NONE)
-
-#define OBOE_AUDIO_FORMAT_DATA_TYPE(format) \
-    ((oboe_datatype_t)(format & 0x0FF))
-
-// Define some common formats.
-#define OBOE_AUDIO_FORMAT_PCM16  \
-                OBOE_AUDIO_FORMAT_RAW(OBOE_AUDIO_DATATYPE_INT16, OBOE_AUDIO_CONTENT_PCM)
-#define OBOE_AUDIO_FORMAT_PCM_FLOAT \
-                OBOE_AUDIO_FORMAT_RAW(OBOE_AUDIO_DATATYPE_FLOAT32, OBOE_AUDIO_CONTENT_PCM)
-#define OBOE_AUDIO_FORMAT_PCM824 \
-                OBOE_AUDIO_FORMAT_RAW(OBOE_AUDIO_DATATYPE_INT824, OBOE_AUDIO_CONTENT_PCM)
-#define OBOE_AUDIO_FORMAT_PCM32 \
-                OBOE_AUDIO_FORMAT_RAW(OBOE_AUDIO_DATATYPE_INT32, OBOE_AUDIO_CONTENT_PCM)
-#define OBOE_AUDIO_FORMAT_INVALID ((oboe_audio_format_t)-1)
-
 enum {
     OBOE_OK,
     OBOE_ERROR_BASE = -900, // TODO review
diff --git a/media/liboboe/src/core/AudioStream.cpp b/media/liboboe/src/core/AudioStream.cpp
index f154002..cc654c3 100644
--- a/media/liboboe/src/core/AudioStream.cpp
+++ b/media/liboboe/src/core/AudioStream.cpp
@@ -18,6 +18,7 @@
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
+#include <atomic>
 #include <stdint.h>
 #include <oboe/OboeAudio.h>
 
@@ -27,10 +28,10 @@
 
 using namespace oboe;
 
-/*
- * AudioStream
- */
 AudioStream::AudioStream() {
+    // mThread is a pthread_t of unknown size so we need memset.
+    memset(&mThread, 0, sizeof(mThread));
+    setPeriodNanoseconds(0);
 }
 
 oboe_result_t AudioStream::open(const AudioStreamBuilder& builder)
@@ -91,23 +92,51 @@
 
         state = getState();
     }
-    if (nextState != NULL) {
+    if (nextState != nullptr) {
         *nextState = state;
     }
     return (state == currentState) ? OBOE_ERROR_TIMEOUT : OBOE_OK;
 }
 
+// This registers the app's background audio thread with the server before
+// passing control to the app. This gives the server an opportunity to boost
+// the thread's performance characteristics.
+void* AudioStream::wrapUserThread() {
+    void* procResult = nullptr;
+    mThreadRegistrationResult = registerThread();
+    if (mThreadRegistrationResult == OBOE_OK) {
+        // Call application procedure. This may take a very long time.
+        procResult = mThreadProc(mThreadArg);
+        ALOGD("AudioStream::mThreadProc() returned");
+        mThreadRegistrationResult = unregisterThread();
+    }
+    return procResult;
+}
+
+// This is the entry point for the new thread created by createThread().
+// It converts the 'C' function call to a C++ method call.
+static void* AudioStream_internalThreadProc(void* threadArg) {
+    AudioStream *audioStream = (AudioStream *) threadArg;
+    return audioStream->wrapUserThread();
+}
+
 oboe_result_t AudioStream::createThread(oboe_nanoseconds_t periodNanoseconds,
-                                     void *(*startRoutine)(void *), void *arg)
+                                     oboe_audio_thread_proc_t *threadProc,
+                                     void* threadArg)
 {
     if (mHasThread) {
         return OBOE_ERROR_INVALID_STATE;
     }
-    if (startRoutine == NULL) {
+    if (threadProc == nullptr) {
         return OBOE_ERROR_NULL;
     }
-    int err = pthread_create(&mThread, NULL, startRoutine, arg);
+    // Pass input parameters to the background thread.
+    mThreadProc = threadProc;
+    mThreadArg = threadArg;
+    setPeriodNanoseconds(periodNanoseconds);
+    int err = pthread_create(&mThread, nullptr, AudioStream_internalThreadProc, this);
     if (err != 0) {
+        // TODO convert errno to oboe_result_t
         return OBOE_ERROR_INTERNAL;
     } else {
         mHasThread = true;
@@ -115,7 +144,7 @@
     }
 }
 
-oboe_result_t AudioStream::joinThread(void **returnArg, oboe_nanoseconds_t timeoutNanoseconds)
+oboe_result_t AudioStream::joinThread(void** returnArg, oboe_nanoseconds_t timeoutNanoseconds)
 {
     if (!mHasThread) {
         return OBOE_ERROR_INVALID_STATE;
@@ -128,7 +157,7 @@
     int err = pthread_join(mThread, returnArg);
 #endif
     mHasThread = false;
-    // TODO Just leaked a thread?
-    return err ? OBOE_ERROR_INTERNAL : OBOE_OK;
+    // TODO convert errno to oboe_result_t
+    return err ? OBOE_ERROR_INTERNAL : mThreadRegistrationResult;
 }
 
diff --git a/media/liboboe/src/core/AudioStream.h b/media/liboboe/src/core/AudioStream.h
index 8cbb091..c13ae9f 100644
--- a/media/liboboe/src/core/AudioStream.h
+++ b/media/liboboe/src/core/AudioStream.h
@@ -17,9 +17,11 @@
 #ifndef OBOE_AUDIOSTREAM_H
 #define OBOE_AUDIOSTREAM_H
 
-#include <unistd.h>
-#include <sys/types.h>
+#include <atomic>
+#include <stdint.h>
+#include <oboe/OboeDefinitions.h>
 #include <oboe/OboeAudio.h>
+
 #include "OboeUtilities.h"
 #include "MonotonicCounter.h"
 
@@ -83,10 +85,25 @@
     }
 
     virtual oboe_result_t createThread(oboe_nanoseconds_t periodNanoseconds,
-                                     void *(*start_routine)(void *), void *arg);
+                                       oboe_audio_thread_proc_t *threadProc,
+                                       void *threadArg);
 
     virtual oboe_result_t joinThread(void **returnArg, oboe_nanoseconds_t timeoutNanoseconds);
 
+    virtual oboe_result_t registerThread() {
+        return OBOE_OK;
+    }
+
+    virtual oboe_result_t unregisterThread() {
+        return OBOE_OK;
+    }
+
+    /**
+     * Internal function used to call the audio thread passed by the user.
+     * It is unfortunately public because it needs to be called by a static 'C' function.
+     */
+    void* wrapUserThread();
+
     // ============== Queries ===========================
 
     virtual oboe_stream_state_t getState() const {
@@ -125,7 +142,7 @@
         return mSamplesPerFrame;
     }
 
-    OboeDeviceId getDeviceId() const {
+    oboe_device_id_t getDeviceId() const {
         return mDeviceId;
     }
 
@@ -220,21 +237,42 @@
         mState = state;
     }
 
+
+
+protected:
     MonotonicCounter     mFramesWritten;
     MonotonicCounter     mFramesRead;
 
+    void setPeriodNanoseconds(oboe_nanoseconds_t periodNanoseconds) {
+        mPeriodNanoseconds.store(periodNanoseconds, std::memory_order_release);
+    }
+
+    oboe_nanoseconds_t getPeriodNanoseconds() {
+        return mPeriodNanoseconds.load(std::memory_order_acquire);
+    }
+
 private:
     // These do not change after open().
     int32_t              mSamplesPerFrame = OBOE_UNSPECIFIED;
     oboe_sample_rate_t   mSampleRate = OBOE_UNSPECIFIED;
     oboe_stream_state_t  mState = OBOE_STREAM_STATE_UNINITIALIZED;
-    OboeDeviceId         mDeviceId = OBOE_UNSPECIFIED;
+    oboe_device_id_t     mDeviceId = OBOE_UNSPECIFIED;
     oboe_sharing_mode_t  mSharingMode = OBOE_SHARING_MODE_LEGACY;
-    oboe_audio_format_t  mFormat = OBOE_UNSPECIFIED;
+    oboe_audio_format_t  mFormat = OBOE_AUDIO_FORMAT_UNSPECIFIED;
     oboe_direction_t     mDirection = OBOE_DIRECTION_OUTPUT;
 
+    // background thread ----------------------------------
     bool                 mHasThread = false;
-    pthread_t            mThread;
+    pthread_t            mThread; // initialized in constructor
+
+    // These are set by the application thread and then read by the audio pthread.
+    std::atomic<oboe_nanoseconds_t>  mPeriodNanoseconds; // for tuning SCHED_FIFO threads
+    // TODO make atomic?
+    oboe_audio_thread_proc_t* mThreadProc = nullptr;
+    void*                mThreadArg = nullptr;
+    oboe_result_t        mThreadRegistrationResult = OBOE_OK;
+
+
 };
 
 } /* namespace oboe */
diff --git a/media/liboboe/src/core/AudioStreamBuilder.cpp b/media/liboboe/src/core/AudioStreamBuilder.cpp
index 56e6706..37e1378 100644
--- a/media/liboboe/src/core/AudioStreamBuilder.cpp
+++ b/media/liboboe/src/core/AudioStreamBuilder.cpp
@@ -18,11 +18,17 @@
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
-#include <sys/types.h>
-#include "AudioStream.h"
-#include "AudioStreamBuilder.h"
-#include "AudioStreamRecord.h"
-#include "AudioStreamTrack.h"
+#include <new>
+#include <stdint.h>
+
+#include <oboe/OboeDefinitions.h>
+#include <oboe/OboeAudio.h>
+
+#include "client/AudioStreamInternal.h"
+#include "core/AudioStream.h"
+#include "core/AudioStreamBuilder.h"
+#include "legacy/AudioStreamRecord.h"
+#include "legacy/AudioStreamTrack.h"
 
 using namespace oboe;
 
@@ -35,15 +41,15 @@
 AudioStreamBuilder::~AudioStreamBuilder() {
 }
 
-oboe_result_t AudioStreamBuilder::build(AudioStream **streamPtr) {
+oboe_result_t AudioStreamBuilder::build(AudioStream** streamPtr) {
     // TODO Is there a better place to put the code that decides which class to use?
-    AudioStream *audioStream = nullptr;
+    AudioStream* audioStream = nullptr;
     const oboe_sharing_mode_t sharingMode = getSharingMode();
     switch (getDirection()) {
     case OBOE_DIRECTION_INPUT:
         switch (sharingMode) {
             case OBOE_SHARING_MODE_LEGACY:
-                audioStream = new AudioStreamRecord();
+                audioStream = new(std::nothrow) AudioStreamRecord();
                 break;
             default:
                 ALOGE("AudioStreamBuilder(): bad sharing mode = %d", sharingMode);
@@ -54,7 +60,10 @@
     case OBOE_DIRECTION_OUTPUT:
         switch (sharingMode) {
             case OBOE_SHARING_MODE_LEGACY:
-                audioStream = new AudioStreamTrack();
+                audioStream = new(std::nothrow) AudioStreamTrack();
+                break;
+            case OBOE_SHARING_MODE_EXCLUSIVE:
+                audioStream = new(std::nothrow) AudioStreamInternal();
                 break;
             default:
                 ALOGE("AudioStreamBuilder(): bad sharing mode = %d", sharingMode);
diff --git a/media/liboboe/src/core/AudioStreamBuilder.h b/media/liboboe/src/core/AudioStreamBuilder.h
index 3f98ebb..ec17eb6 100644
--- a/media/liboboe/src/core/AudioStreamBuilder.h
+++ b/media/liboboe/src/core/AudioStreamBuilder.h
@@ -17,7 +17,11 @@
 #ifndef OBOE_AUDIOSTREAMBUILDER_H
 #define OBOE_AUDIOSTREAMBUILDER_H
 
+#include <stdint.h>
+
+#include <oboe/OboeDefinitions.h>
 #include <oboe/OboeAudio.h>
+
 #include "AudioStream.h"
 
 namespace oboe {
@@ -38,7 +42,7 @@
     /**
      * This is also known as channelCount.
      */
-    AudioStreamBuilder *setSamplesPerFrame(int samplesPerFrame) {
+    AudioStreamBuilder* setSamplesPerFrame(int samplesPerFrame) {
         mSamplesPerFrame = samplesPerFrame;
         return this;
     }
@@ -47,7 +51,7 @@
         return mDirection;
     }
 
-    AudioStreamBuilder *setDirection(oboe_direction_t direction) {
+    AudioStreamBuilder* setDirection(oboe_direction_t direction) {
         mDirection = direction;
         return this;
     }
@@ -56,7 +60,7 @@
         return mSampleRate;
     }
 
-    AudioStreamBuilder *setSampleRate(oboe_sample_rate_t sampleRate) {
+    AudioStreamBuilder* setSampleRate(oboe_sample_rate_t sampleRate) {
         mSampleRate = sampleRate;
         return this;
     }
@@ -74,16 +78,16 @@
         return mSharingMode;
     }
 
-    AudioStreamBuilder *setSharingMode(oboe_sharing_mode_t sharingMode) {
+    AudioStreamBuilder* setSharingMode(oboe_sharing_mode_t sharingMode) {
         mSharingMode = sharingMode;
         return this;
     }
 
-    OboeDeviceId getDeviceId() const {
+    oboe_device_id_t getDeviceId() const {
         return mDeviceId;
     }
 
-    AudioStreamBuilder *setDeviceId(OboeDeviceId deviceId) {
+    AudioStreamBuilder* setDeviceId(oboe_device_id_t deviceId) {
         mDeviceId = deviceId;
         return this;
     }
@@ -93,9 +97,9 @@
 private:
     int32_t              mSamplesPerFrame = OBOE_UNSPECIFIED;
     oboe_sample_rate_t   mSampleRate = OBOE_UNSPECIFIED;
-    OboeDeviceId         mDeviceId = OBOE_UNSPECIFIED; // TODO need better default
+    oboe_device_id_t     mDeviceId = OBOE_DEVICE_UNSPECIFIED;
     oboe_sharing_mode_t  mSharingMode = OBOE_SHARING_MODE_LEGACY;
-    oboe_audio_format_t  mFormat = OBOE_UNSPECIFIED;
+    oboe_audio_format_t  mFormat = OBOE_AUDIO_FORMAT_UNSPECIFIED;
     oboe_direction_t     mDirection = OBOE_DIRECTION_OUTPUT;
 };
 
diff --git a/media/liboboe/src/core/OboeAudio.cpp b/media/liboboe/src/core/OboeAudio.cpp
index a02f226..d98ca36 100644
--- a/media/liboboe/src/core/OboeAudio.cpp
+++ b/media/liboboe/src/core/OboeAudio.cpp
@@ -23,21 +23,13 @@
 
 #include <oboe/OboeDefinitions.h>
 #include <oboe/OboeAudio.h>
+
 #include "AudioStreamBuilder.h"
 #include "AudioStream.h"
 #include "AudioClock.h"
+#include "client/AudioStreamInternal.h"
 #include "HandleTracker.h"
 
-// temporary, as I stage in the MMAP/NOIRQ support, do not review
-#ifndef OBOE_SUPPORT_MMAP
-#define OBOE_SUPPORT_MMAP 0
-#endif
-
-#if OBOE_SUPPORT_MMAP
-#include "AudioStreamInternal.h"
-#include "OboeServiceGateway.h"
-#endif
-
 using namespace oboe;
 
 // This is not the maximum theoretic possible number of handles that the HandlerTracker
@@ -71,6 +63,8 @@
         return OBOE_ERROR_NULL; \
     }
 
+// Static data.
+// TODO static constructors are discouraged, alternatives?
 static HandleTracker sHandleTracker(OBOE_MAX_HANDLES);
 
 typedef enum
@@ -81,9 +75,6 @@
 } oboe_handle_type_t;
 static_assert(OBOE_HANDLE_TYPE_COUNT <= HANDLE_TRACKER_MAX_TYPES, "Too many handle types.");
 
-#if OBOE_SUPPORT_MMAP
-static OboeServiceGateway sOboeServiceGateway;
-#endif
 
 #define OBOE_CASE_ENUM(name) case name: return #name
 
@@ -165,13 +156,21 @@
 }
 
 OBOE_API oboe_result_t OboeStreamBuilder_setDeviceId(OboeStreamBuilder builder,
-                                                     OboeDeviceId deviceId)
+                                                     oboe_device_id_t deviceId)
 {
     AudioStreamBuilder *streamBuilder = CONVERT_BUILDER_HANDLE_OR_RETURN();
     streamBuilder->setDeviceId(deviceId);
     return OBOE_OK;
 }
 
+OBOE_API oboe_result_t OboeStreamBuilder_getDeviceId(OboeStreamBuilder builder,
+                                              oboe_device_id_t *deviceId)
+{
+    AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(deviceId);
+    *deviceId = streamBuilder->getDeviceId();
+    return OBOE_OK;
+}
+
 OBOE_API oboe_result_t OboeStreamBuilder_setSampleRate(OboeStreamBuilder builder,
                                               oboe_sample_rate_t sampleRate)
 {
@@ -399,10 +398,10 @@
 
 OBOE_API oboe_result_t OboeStream_createThread(OboeStream stream,
                                      oboe_nanoseconds_t periodNanoseconds,
-                                     void *(*startRoutine)(void *), void *arg)
+                                     oboe_audio_thread_proc_t *threadProc, void *arg)
 {
     AudioStream *audioStream = CONVERT_STREAM_HANDLE_OR_RETURN();
-    return audioStream->createThread(periodNanoseconds, startRoutine, arg);
+    return audioStream->createThread(periodNanoseconds, threadProc, arg);
 }
 
 OBOE_API oboe_result_t OboeStream_joinThread(OboeStream stream,
@@ -513,6 +512,14 @@
     return OBOE_OK;
 }
 
+OBOE_API oboe_result_t OboeStream_getDeviceId(OboeStream stream,
+                                                 oboe_device_id_t *deviceId)
+{
+    AudioStream *audioStream = COMMON_GET_FROM_STREAM_OR_RETURN(deviceId);
+    *deviceId = audioStream->getDeviceId();
+    return OBOE_OK;
+}
+
 OBOE_API oboe_result_t OboeStream_getSharingMode(OboeStream stream,
                                                  oboe_sharing_mode_t *sharingMode)
 {
diff --git a/media/liboboe/src/legacy/AudioStreamRecord.cpp b/media/liboboe/src/legacy/AudioStreamRecord.cpp
index f130cad..5854974 100644
--- a/media/liboboe/src/legacy/AudioStreamRecord.cpp
+++ b/media/liboboe/src/legacy/AudioStreamRecord.cpp
@@ -57,7 +57,7 @@
                               ? 2 : getSamplesPerFrame();
     audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame);
 
-    AudioRecord::callback_t callback = NULL;
+    AudioRecord::callback_t callback = nullptr;
     audio_input_flags_t flags = (audio_input_flags_t) AUDIO_INPUT_FLAG_NONE;
 
     // TODO implement an unspecified Android format then use that.
@@ -75,14 +75,14 @@
 
             0,    //    size_t frameCount = 0,
             callback,
-            NULL, //    void* user = NULL,
+            nullptr, //    void* user = nullptr,
             0,    //    uint32_t notificationFrames = 0,
             AUDIO_SESSION_ALLOCATE,
             AudioRecord::TRANSFER_DEFAULT,
             flags
              //   int uid = -1,
              //   pid_t pid = -1,
-             //   const audio_attributes_t* pAttributes = NULL
+             //   const audio_attributes_t* pAttributes = nullptr
              );
 
     // Did we get a valid track?
@@ -115,7 +115,7 @@
 
 oboe_result_t AudioStreamRecord::requestStart()
 {
-    if (mAudioRecord.get() == NULL) {
+    if (mAudioRecord.get() == nullptr) {
         return OBOE_ERROR_INVALID_STATE;
     }
     // Get current position so we can detect when the track is playing.
@@ -142,7 +142,7 @@
 }
 
 oboe_result_t AudioStreamRecord::requestStop() {
-    if (mAudioRecord.get() == NULL) {
+    if (mAudioRecord.get() == nullptr) {
         return OBOE_ERROR_INVALID_STATE;
     }
     setState(OBOE_STREAM_STATE_STOPPING);
diff --git a/media/liboboe/src/legacy/AudioStreamTrack.cpp b/media/liboboe/src/legacy/AudioStreamTrack.cpp
index 5205fc5..b2c4ee1 100644
--- a/media/liboboe/src/legacy/AudioStreamTrack.cpp
+++ b/media/liboboe/src/legacy/AudioStreamTrack.cpp
@@ -58,10 +58,10 @@
     int32_t samplesPerFrame = (getSamplesPerFrame() == OBOE_UNSPECIFIED)
                               ? 2 : getSamplesPerFrame();
     audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(samplesPerFrame);
-    ALOGE("AudioStreamTrack::open(), samplesPerFrame = %d, channelMask = 0x%08x",
+    ALOGD("AudioStreamTrack::open(), samplesPerFrame = %d, channelMask = 0x%08x",
             samplesPerFrame, channelMask);
 
-    AudioTrack::callback_t callback = NULL;
+    AudioTrack::callback_t callback = nullptr;
     // TODO add more performance options
     audio_output_flags_t flags = (audio_output_flags_t) AUDIO_OUTPUT_FLAG_FAST;
     size_t frameCount = 0;
@@ -78,14 +78,15 @@
             frameCount,
             flags,
             callback,
-            NULL,    // user callback data
-            0,       // notificationFrames
+            nullptr,    // user callback data
+            0,          // notificationFrames
             AUDIO_SESSION_ALLOCATE,
             AudioTrack::transfer_type::TRANSFER_SYNC // TODO - this does not allow FAST
             );
 
     // 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) {
@@ -116,7 +117,7 @@
 
 oboe_result_t AudioStreamTrack::requestStart()
 {
-    if (mAudioTrack.get() == NULL) {
+    if (mAudioTrack.get() == nullptr) {
         return OBOE_ERROR_INVALID_STATE;
     }
     // Get current position so we can detect when the track is playing.
@@ -135,7 +136,7 @@
 
 oboe_result_t AudioStreamTrack::requestPause()
 {
-    if (mAudioTrack.get() == NULL) {
+    if (mAudioTrack.get() == nullptr) {
         return OBOE_ERROR_INVALID_STATE;
     } else if (getState() != OBOE_STREAM_STATE_STARTING
             && getState() != OBOE_STREAM_STATE_STARTED) {
@@ -152,7 +153,7 @@
 }
 
 oboe_result_t AudioStreamTrack::requestFlush() {
-    if (mAudioTrack.get() == NULL) {
+    if (mAudioTrack.get() == nullptr) {
         return OBOE_ERROR_INVALID_STATE;
     } else if (getState() != OBOE_STREAM_STATE_PAUSED) {
         return OBOE_ERROR_INVALID_STATE;
@@ -165,7 +166,7 @@
 }
 
 oboe_result_t AudioStreamTrack::requestStop() {
-    if (mAudioTrack.get() == NULL) {
+    if (mAudioTrack.get() == nullptr) {
         return OBOE_ERROR_INVALID_STATE;
     }
     setState(OBOE_STREAM_STATE_STOPPING);
diff --git a/media/liboboe/src/utility/AudioClock.h b/media/liboboe/src/utility/AudioClock.h
index da2f74a..1a5c209 100644
--- a/media/liboboe/src/utility/AudioClock.h
+++ b/media/liboboe/src/utility/AudioClock.h
@@ -17,10 +17,10 @@
 #ifndef UTILITY_AUDIOCLOCK_H
 #define UTILITY_AUDIOCLOCK_H
 
-#include <sys/types.h>
+#include <stdint.h>
 #include <time.h>
-#include "oboe/OboeDefinitions.h"
-#include "oboe/OboeAudio.h"
+
+#include <oboe/OboeDefinitions.h>
 
 class AudioClock {
 public:
diff --git a/media/liboboe/src/utility/HandleTracker.cpp b/media/liboboe/src/utility/HandleTracker.cpp
index be2a64c..bf5fb63 100644
--- a/media/liboboe/src/utility/HandleTracker.cpp
+++ b/media/liboboe/src/utility/HandleTracker.cpp
@@ -19,6 +19,7 @@
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
+#include <new>
 #include <stdint.h>
 #include <assert.h>
 
@@ -51,25 +52,28 @@
 
 HandleTracker::HandleTracker(uint32_t maxHandles)
         : mMaxHandleCount(maxHandles)
-        , mHandleAddresses(nullptr)
         , mHandleHeaders(nullptr)
 {
     assert(maxHandles <= HANDLE_TRACKER_MAX_HANDLES);
     // Allocate arrays to hold addresses and validation info.
-    mHandleAddresses = (handle_tracker_address_t *) new handle_tracker_address_t[maxHandles];
+    mHandleAddresses = (handle_tracker_address_t *)
+            new(std::nothrow) handle_tracker_address_t[maxHandles];
     if (mHandleAddresses != nullptr) {
-        mHandleHeaders = new handle_tracker_header_t[maxHandles];
+        mHandleHeaders = new(std::nothrow) handle_tracker_header_t[maxHandles];
+
         if (mHandleHeaders != nullptr) {
-            // Initialize linked list of free nodes. NULL terminated.
+            handle_tracker_header_t initialHeader = buildHeader(0, 1);
+            // Initialize linked list of free nodes. nullptr terminated.
             for (uint32_t i = 0; i < (maxHandles - 1); i++) {
                 mHandleAddresses[i] = &mHandleAddresses[i + 1]; // point to next node
-                mHandleHeaders[i] = 0;
+                mHandleHeaders[i] = initialHeader;
             }
             mNextFreeAddress = &mHandleAddresses[0];
             mHandleAddresses[maxHandles - 1] = nullptr;
             mHandleHeaders[maxHandles - 1] = 0;
         } else {
             delete[] mHandleAddresses; // so the class appears uninitialized
+            mHandleAddresses = nullptr;
         }
     }
 }
@@ -131,7 +135,7 @@
     // Generate a handle.
     oboe_handle_t handle = buildHandle(inputHeader, index);
 
-    //ALOGD("HandleTracker::put(%p) returns 0x%08x", address, handle);
+    ALOGV("HandleTracker::put(%p) returns 0x%08x", address, handle);
     return handle;
 }
 
diff --git a/media/liboboe/src/utility/OboeUtilities.cpp b/media/liboboe/src/utility/OboeUtilities.cpp
index b28f7c7..d9d2e88 100644
--- a/media/liboboe/src/utility/OboeUtilities.cpp
+++ b/media/liboboe/src/utility/OboeUtilities.cpp
@@ -28,24 +28,19 @@
 using namespace android;
 
 oboe_size_bytes_t OboeConvert_formatToSizeInBytes(oboe_audio_format_t format) {
-    oboe_datatype_t dataType = OBOE_AUDIO_FORMAT_DATA_TYPE(format);
-    oboe_size_bytes_t size;
-    switch (dataType) {
-        case OBOE_AUDIO_DATATYPE_UINT8:
-            size = sizeof(uint8_t);
-            break;
-        case OBOE_AUDIO_DATATYPE_INT16:
+    oboe_size_bytes_t size = OBOE_ERROR_ILLEGAL_ARGUMENT;
+    switch (format) {
+        case OBOE_AUDIO_FORMAT_PCM16:
             size = sizeof(int16_t);
             break;
-        case OBOE_AUDIO_DATATYPE_INT32:
-        case OBOE_AUDIO_DATATYPE_INT824:
+        case OBOE_AUDIO_FORMAT_PCM32:
+        case OBOE_AUDIO_FORMAT_PCM824:
             size = sizeof(int32_t);
             break;
-        case OBOE_AUDIO_DATATYPE_FLOAT32:
+        case OBOE_AUDIO_FORMAT_PCM_FLOAT:
             size = sizeof(float);
             break;
         default:
-            size = OBOE_ERROR_ILLEGAL_ARGUMENT;
             break;
     }
     return size;