Merge "Camera service: Fix dump() for treble path and rearrange it"
diff --git a/drm/libmediadrm/Android.mk b/drm/libmediadrm/Android.mk
index 7e77aac..14740e6 100644
--- a/drm/libmediadrm/Android.mk
+++ b/drm/libmediadrm/Android.mk
@@ -13,7 +13,7 @@
IDrmClient.cpp \
IMediaDrmService.cpp \
SharedLibrary.cpp
-ifeq ($(ENABLE_TREBLE_DRM), true)
+ifeq ($(ENABLE_TREBLE), true)
LOCAL_SRC_FILES += \
DrmHal.cpp \
CryptoHal.cpp
@@ -31,7 +31,7 @@
libmediautils \
libstagefright_foundation \
libutils
-ifeq ($(ENABLE_TREBLE_DRM), true)
+ifeq ($(ENABLE_TREBLE), true)
LOCAL_SHARED_LIBRARIES += \
android.hidl.base@1.0 \
android.hardware.drm@1.0 \
diff --git a/drm/libmediadrm/Drm.cpp b/drm/libmediadrm/Drm.cpp
index 07e9414..e3176e3 100644
--- a/drm/libmediadrm/Drm.cpp
+++ b/drm/libmediadrm/Drm.cpp
@@ -303,7 +303,8 @@
return true;
}
-status_t Drm::createPlugin(const uint8_t uuid[16]) {
+status_t Drm::createPlugin(const uint8_t uuid[16],
+ const String8& /* appPackageName */) {
Mutex::Autolock autoLock(mLock);
if (mPlugin != NULL) {
@@ -319,7 +320,12 @@
}
status_t result = mFactory->createDrmPlugin(uuid, &mPlugin);
- mPlugin->setListener(this);
+ if (mPlugin) {
+ mPlugin->setListener(this);
+ } else {
+ ALOGE("Failed to create plugin");
+ return UNEXPECTED_NULL;
+ }
return result;
}
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 304cdaf..42dce35 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -205,21 +205,22 @@
return factory;
}
-sp<IDrmPlugin> DrmHal::makeDrmPlugin(const uint8_t uuid[16]) {
+sp<IDrmPlugin> DrmHal::makeDrmPlugin(const uint8_t uuid[16],
+ const String8& appPackageName) {
if (mFactory == NULL){
return NULL;
}
sp<IDrmPlugin> plugin;
- Return<void> hResult = mFactory->createPlugin(uuid,
+ Return<void> hResult = mFactory->createPlugin(uuid, appPackageName.string(),
[&](Status status, const sp<IDrmPlugin>& hPlugin) {
- if (status != Status::OK) {
- ALOGD("Failed to make drm plugin");
- return;
- }
- plugin = hPlugin;
- }
- );
+ if (status != Status::OK) {
+ ALOGD("Failed to make drm plugin");
+ return;
+ }
+ plugin = hPlugin;
+ }
+ );
return plugin;
}
@@ -350,10 +351,11 @@
return result;
}
-status_t DrmHal::createPlugin(const uint8_t uuid[16]) {
+status_t DrmHal::createPlugin(const uint8_t uuid[16],
+ const String8& appPackageName) {
Mutex::Autolock autoLock(mLock);
- mPlugin = makeDrmPlugin(uuid);
+ mPlugin = makeDrmPlugin(uuid, appPackageName);
if (mPlugin == NULL) {
mInitCheck = ERROR_UNSUPPORTED;
@@ -597,8 +599,7 @@
}
status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
- Vector<uint8_t> &certificate,
- Vector<uint8_t> &wrappedKey) {
+ Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -783,10 +784,8 @@
}
status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output) {
+ Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -811,10 +810,8 @@
}
status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output) {
+ Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
+ Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -839,9 +836,8 @@
}
status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> &signature) {
+ Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
+ Vector<uint8_t> &signature) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -866,10 +862,8 @@
}
status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> const &signature,
- bool &match) {
+ Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
+ Vector<uint8_t> const &signature, bool &match) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
@@ -896,10 +890,8 @@
}
status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
- String8 const &algorithm,
- Vector<uint8_t> const &message,
- Vector<uint8_t> const &wrappedKey,
- Vector<uint8_t> &signature) {
+ String8 const &algorithm, Vector<uint8_t> const &message,
+ Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
Mutex::Autolock autoLock(mLock);
if (mInitCheck != OK) {
diff --git a/drm/libmediadrm/IDrm.cpp b/drm/libmediadrm/IDrm.cpp
index c4558c6..4e47112 100644
--- a/drm/libmediadrm/IDrm.cpp
+++ b/drm/libmediadrm/IDrm.cpp
@@ -88,13 +88,15 @@
return reply.readInt32() != 0;
}
- virtual status_t createPlugin(const uint8_t uuid[16]) {
+ virtual status_t createPlugin(const uint8_t uuid[16],
+ const String8& appPackageName) {
Parcel data, reply;
data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
data.write(uuid, 16);
-
+ data.writeString8(appPackageName);
status_t status = remote()->transact(CREATE_PLUGIN, data, &reply);
if (status != OK) {
+ ALOGE("createPlugin: binder call failed: %d", status);
return status;
}
@@ -585,7 +587,6 @@
data.read(uuid, sizeof(uuid));
String8 mimeType = data.readString8();
reply->writeInt32(isCryptoSchemeSupported(uuid, mimeType));
-
return OK;
}
@@ -594,7 +595,8 @@
CHECK_INTERFACE(IDrm, data, reply);
uint8_t uuid[16];
data.read(uuid, sizeof(uuid));
- reply->writeInt32(createPlugin(uuid));
+ String8 appPackageName = data.readString8();
+ reply->writeInt32(createPlugin(uuid, appPackageName));
return OK;
}
diff --git a/drm/mediadrm/plugins/clearkey/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/DrmFactory.cpp
index d27956c..c83321b 100644
--- a/drm/mediadrm/plugins/clearkey/DrmFactory.cpp
+++ b/drm/mediadrm/plugins/clearkey/DrmFactory.cpp
@@ -44,7 +44,8 @@
}
android::status_t DrmFactory::createDrmPlugin(
- const uint8_t uuid[16], android::DrmPlugin** plugin) {
+ const uint8_t uuid[16],
+ android::DrmPlugin** plugin) {
if (!isCryptoSchemeSupported(uuid)) {
*plugin = NULL;
return android::BAD_VALUE;
diff --git a/drm/mediadrm/plugins/clearkey/DrmFactory.h b/drm/mediadrm/plugins/clearkey/DrmFactory.h
index 87db982..0bc0843 100644
--- a/drm/mediadrm/plugins/clearkey/DrmFactory.h
+++ b/drm/mediadrm/plugins/clearkey/DrmFactory.h
@@ -35,7 +35,8 @@
virtual bool isContentTypeSupported(const android::String8 &mimeType);
virtual android::status_t createDrmPlugin(
- const uint8_t uuid[16], android::DrmPlugin** plugin);
+ const uint8_t uuid[16],
+ android::DrmPlugin** plugin);
private:
DISALLOW_EVIL_CONSTRUCTORS(DrmFactory);
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
index a38cca9..c82b9d9 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
@@ -56,7 +56,8 @@
return true;
}
- status_t MockDrmFactory::createDrmPlugin(const uint8_t /* uuid */[16], DrmPlugin **plugin)
+ status_t MockDrmFactory::createDrmPlugin(const uint8_t /* uuid */[16],
+ DrmPlugin **plugin)
{
*plugin = new MockDrmPlugin();
return OK;
@@ -729,7 +730,7 @@
ssize_t MockDrmPlugin::findSession(Vector<uint8_t> const &sessionId) const
{
- ALOGD("findSession: nsessions=%d, size=%d", mSessions.size(), sessionId.size());
+ ALOGD("findSession: nsessions=%u, size=%u", mSessions.size(), sessionId.size());
for (size_t i = 0; i < mSessions.size(); ++i) {
if (memcmp(mSessions[i].array(), sessionId.array(), sessionId.size()) == 0) {
return i;
@@ -740,7 +741,7 @@
ssize_t MockDrmPlugin::findKeySet(Vector<uint8_t> const &keySetId) const
{
- ALOGD("findKeySet: nkeySets=%d, size=%d", mKeySets.size(), keySetId.size());
+ ALOGD("findKeySet: nkeySets=%u, size=%u", mKeySets.size(), keySetId.size());
for (size_t i = 0; i < mKeySets.size(); ++i) {
if (memcmp(mKeySets[i].array(), keySetId.array(), keySetId.size()) == 0) {
return i;
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
index 98bdd69..9f8db17 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
@@ -33,7 +33,8 @@
bool isCryptoSchemeSupported(const uint8_t uuid[16]);
bool isContentTypeSupported(const String8 &mimeType);
- status_t createDrmPlugin(const uint8_t uuid[16], DrmPlugin **plugin);
+ status_t createDrmPlugin(const uint8_t uuid[16],
+ DrmPlugin **plugin);
};
class MockCryptoFactory : public CryptoFactory {
diff --git a/include/media/Drm.h b/include/media/Drm.h
index d40019b..fc869cc 100644
--- a/include/media/Drm.h
+++ b/include/media/Drm.h
@@ -40,7 +40,7 @@
virtual bool isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType);
- virtual status_t createPlugin(const uint8_t uuid[16]);
+ virtual status_t createPlugin(const uint8_t uuid[16], const String8 &appPackageName);
virtual status_t destroyPlugin();
diff --git a/include/media/DrmHal.h b/include/media/DrmHal.h
index aaea2c9..82d2555 100644
--- a/include/media/DrmHal.h
+++ b/include/media/DrmHal.h
@@ -49,7 +49,8 @@
virtual bool isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType);
- virtual status_t createPlugin(const uint8_t uuid[16]);
+ virtual status_t createPlugin(const uint8_t uuid[16],
+ const String8 &appPackageName);
virtual status_t destroyPlugin();
@@ -169,7 +170,8 @@
status_t mInitCheck;
sp<IDrmFactory> makeDrmFactory();
- sp<IDrmPlugin> makeDrmPlugin(const uint8_t uuid[16]);
+ sp<IDrmPlugin> makeDrmPlugin(const uint8_t uuid[16],
+ const String8 &appPackageName);
void writeByteArray(Parcel &obj, const hidl_vec<uint8_t>& array);
diff --git a/include/media/IDrm.h b/include/media/IDrm.h
index fd51fd0..a57e372 100644
--- a/include/media/IDrm.h
+++ b/include/media/IDrm.h
@@ -34,7 +34,8 @@
virtual bool isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) = 0;
- virtual status_t createPlugin(const uint8_t uuid[16]) = 0;
+ virtual status_t createPlugin(const uint8_t uuid[16],
+ const String8 &appPackageName) = 0;
virtual status_t destroyPlugin() = 0;
diff --git a/include/media/stagefright/OMXClient.h b/include/media/stagefright/OMXClient.h
index 6973405..6b86cbf 100644
--- a/include/media/stagefright/OMXClient.h
+++ b/include/media/stagefright/OMXClient.h
@@ -27,6 +27,7 @@
OMXClient();
status_t connect();
+ status_t connectTreble();
void disconnect();
sp<IOMX> interface() {
diff --git a/media/libaudiohal/EffectBufferHalLocal.cpp b/media/libaudiohal/EffectBufferHalLocal.cpp
index 7e6ee85..9fe2c7b 100644
--- a/media/libaudiohal/EffectBufferHalLocal.cpp
+++ b/media/libaudiohal/EffectBufferHalLocal.cpp
@@ -75,10 +75,10 @@
void EffectBufferHalLocal::commit() {
}
-void EffectBufferHalLocal::update(size_t size) {
+void EffectBufferHalLocal::update(size_t) {
}
-void EffectBufferHalLocal::commit(size_t size) {
+void EffectBufferHalLocal::commit(size_t) {
}
} // namespace android
diff --git a/media/libaudiohal/EffectsFactoryHalHidl.cpp b/media/libaudiohal/EffectsFactoryHalHidl.cpp
index 1ab5dad..ad12654 100644
--- a/media/libaudiohal/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/EffectsFactoryHalHidl.cpp
@@ -17,7 +17,9 @@
#define LOG_TAG "EffectsFactoryHalHidl"
//#define LOG_NDEBUG 0
+#include <android/hidl/memory/1.0/IAllocator.h>
#include <cutils/native_handle.h>
+#include <hidl/ServiceManagement.h>
#include <media/EffectsFactoryApi.h>
#include "ConversionHelperHidl.h"
@@ -45,6 +47,10 @@
EffectsFactoryHalHidl::EffectsFactoryHalHidl() : ConversionHelperHidl("EffectsFactory"){
mEffectsFactory = IEffectsFactory::getService("audio_effects_factory");
+ // TODO: Waiting should not be needed (b/34772726).
+ // Also remove include of IAllocator.h and ServiceManagement.h
+ android::hardware::details::waitForHwService(
+ hidl::memory::V1_0::IAllocator::descriptor, "ashmem");
}
EffectsFactoryHalHidl::~EffectsFactoryHalHidl() {
diff --git a/media/libmedia/TypeConverter.cpp b/media/libmedia/TypeConverter.cpp
index 25c29f2..8ce2b9f 100644
--- a/media/libmedia/TypeConverter.cpp
+++ b/media/libmedia/TypeConverter.cpp
@@ -186,6 +186,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_SBC),
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX),
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_APTX_HD),
+ MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_AC4),
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_LDAC),
TERMINATOR
};
@@ -211,6 +212,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_MONO),
MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_STEREO),
MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
+ MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_6),
MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO),
MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO),
MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_IN_VOICE_CALL_MONO),
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
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index c2407f7..d8f5106 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -113,7 +113,9 @@
libstagefright_foundation \
libdl \
libRScpp \
- libhidlbase \
+ libhidlbase \
+ android.hardware.media.omx@1.0 \
+ android.hardware.media.omx@1.0-utils \
LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libmedia
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index a29aff0..b4e694c 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -29,6 +29,8 @@
#include "include/OMX.h"
+#include "omx/hal/1.0/utils/WOmx.h"
+
namespace android {
OMXClient::OMXClient() {
@@ -53,6 +55,21 @@
return OK;
}
+status_t OMXClient::connectTreble() {
+ using namespace ::android::hardware::media::omx::V1_0;
+ sp<IOmx> tOmx = IOmx::getService("default");
+ if (tOmx.get() == nullptr) {
+ ALOGE("Cannot obtain Treble IOmx.");
+ return NO_INIT;
+ }
+ if (!tOmx->isRemote()) {
+ ALOGE("Treble IOmx is in passthrough mode.");
+ return NO_INIT;
+ }
+ mOMX = new utils::LWOmx(tOmx);
+ return OK;
+}
+
void OMXClient::disconnect() {
mOMX.clear();
}
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index a1c4979..6e7ef35 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -457,7 +457,10 @@
const uint8_t *nalStart;
size_t nalSize;
while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
- CHECK_GT(nalSize, 0u);
+ if (nalSize == 0u) {
+ ALOGW("skipping empty nal unit from potentially malformed bitstream");
+ continue;
+ }
unsigned nalType = nalStart[0] & 0x1f;
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index cdce932..7a9240b 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -172,7 +172,8 @@
return NULL;
}
- status_t err = drm->createPlugin(uuid);
+ String8 nullPackageName;
+ status_t err = drm->createPlugin(uuid, nullPackageName);
if (err != OK) {
return NULL;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index a248912..1b39e22 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1878,7 +1878,7 @@
config->channel_mask,
flags);
- if (*devices == AUDIO_DEVICE_NONE) {
+ if (devices == NULL || *devices == AUDIO_DEVICE_NONE) {
return BAD_VALUE;
}
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index a0a3383..f44fd08 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -47,43 +47,25 @@
status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListener> listener,
ServiceInteractionProxy* proxy) {
- int numProviders = 0;
- {
- std::lock_guard<std::mutex> lock(mInterfaceMutex);
- if (proxy == nullptr) {
- ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
- return BAD_VALUE;
- }
- mListener = listener;
- mServiceProxy = proxy;
-
- // Registering will trigger notifications for all already-known providers
- bool success = mServiceProxy->registerForNotifications(
- /* instance name, empty means no filter */ "",
- this);
- if (!success) {
- ALOGE("%s: Unable to register with hardware service manager for notifications "
- "about camera providers", __FUNCTION__);
- return INVALID_OPERATION;
- }
- numProviders = mProviders.size();
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+ if (proxy == nullptr) {
+ ALOGE("%s: No valid service interaction proxy provided", __FUNCTION__);
+ return BAD_VALUE;
}
+ mListener = listener;
+ mServiceProxy = proxy;
- if (numProviders == 0) {
- // Remote provider might have not been initialized
- // Wait for a bit and see if we get one registered
- std::mutex mtx;
- std::unique_lock<std::mutex> lock(mtx);
- mProviderRegistered.wait_for(lock, std::chrono::seconds(15));
- if (mProviders.size() == 0) {
- ALOGI("%s: Unable to get one registered provider within timeout!",
- __FUNCTION__);
- std::lock_guard<std::mutex> lock(mInterfaceMutex);
- // See if there's a passthrough HAL, but let's not complain if there's not
- addProvider(kLegacyProviderName, /*expected*/ false);
- }
+ // Registering will trigger notifications for all already-known providers
+ bool success = mServiceProxy->registerForNotifications(
+ /* instance name, empty means no filter */ "",
+ this);
+ if (!success) {
+ ALOGE("%s: Unable to register with hardware service manager for notifications "
+ "about camera providers", __FUNCTION__);
+ return INVALID_OPERATION;
}
-
+ // See if there's a passthrough HAL, but let's not complain if there's not
+ addProvider(kLegacyProviderName, /*expected*/ false);
return OK;
}
@@ -294,7 +276,6 @@
std::lock_guard<std::mutex> lock(mInterfaceMutex);
addProvider(name);
- mProviderRegistered.notify_one();
return hardware::Return<void>();
}
@@ -334,12 +315,11 @@
mServiceProxy->getService(newProvider);
if (interface == nullptr) {
+ ALOGW("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
+ newProvider.c_str());
if (expected) {
- ALOGW("%s: Camera provider HAL '%s' is not actually available", __FUNCTION__,
- newProvider.c_str());
return BAD_VALUE;
} else {
- // Not guaranteed to be found, so not an error if it wasn't
return OK;
}
}
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index f21e07d..5ae16cd 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -20,7 +20,6 @@
#include <vector>
#include <string>
#include <mutex>
-#include <condition_variable>
#include <camera/CameraParameters2.h>
#include <camera/CameraMetadata.h>
@@ -220,8 +219,6 @@
// All private members, unless otherwise noted, expect mInterfaceMutex to be locked before use
mutable std::mutex mInterfaceMutex;
- std::condition_variable mProviderRegistered;
-
// the status listener update callbacks will lock mStatusMutex
mutable std::mutex mStatusListenerMutex;
wp<StatusListener> mListener;
diff --git a/services/mediaanalytics/MediaAnalyticsService.cpp b/services/mediaanalytics/MediaAnalyticsService.cpp
index eacafdd..35c1f5b 100644
--- a/services/mediaanalytics/MediaAnalyticsService.cpp
+++ b/services/mediaanalytics/MediaAnalyticsService.cpp
@@ -280,6 +280,7 @@
nsecs_t ts_since = 0;
String16 clearOption("-clear");
String16 sinceOption("-since");
+ String16 helpOption("-help");
int n = args.size();
for (int i = 0; i < n; i++) {
String8 myarg(args[i]);
@@ -298,6 +299,16 @@
} else {
ts_since = 0;
}
+ // command line is milliseconds; internal units are nano-seconds
+ ts_since *= 1000*1000;
+ } else if (args[i] == helpOption) {
+ result.append("Recognized parameters:\n");
+ result.append("-help this help message\n");
+ result.append("-clear clears out saved records\n");
+ result.append("-since XXX include records since XXX\n");
+ result.append(" (XXX is milliseconds since the UNIX epoch)\n");
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
}
}
@@ -364,8 +375,6 @@
}
String8 MediaAnalyticsService::dumpQueue(List<MediaAnalyticsItem *> *theList, nsecs_t ts_since) {
- const size_t SIZE = 512;
- char buffer[SIZE];
String8 result;
int slot = 0;
@@ -379,12 +388,7 @@
continue;
}
AString entry = (*it)->toString();
- snprintf(buffer, sizeof(buffer), "%4d: %s",
- slot, entry.c_str());
- result.append(buffer);
- buffer[0] = '\n';
- buffer[1] = '\0';
- result.append(buffer);
+ result.appendFormat("%5d: %s\n", slot, entry.c_str());
slot++;
}
}
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index a5f0751..4cbf737 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -17,7 +17,8 @@
LOCAL_REQUIRED_MODULES_arm := mediacodec-seccomp.policy
LOCAL_SRC_FILES := main_codecservice.cpp minijail/minijail.cpp
LOCAL_SHARED_LIBRARIES := libmedia libmediacodecservice libbinder libutils \
- liblog libminijail
+ liblog libminijail libcutils \
+ android.hardware.media.omx@1.0
LOCAL_C_INCLUDES := \
$(TOP)/frameworks/av/media/libstagefright \
$(TOP)/frameworks/native/include/media/openmax
diff --git a/services/mediacodec/main_codecservice.cpp b/services/mediacodec/main_codecservice.cpp
index a2868c1..f6cde85 100644
--- a/services/mediacodec/main_codecservice.cpp
+++ b/services/mediacodec/main_codecservice.cpp
@@ -25,11 +25,14 @@
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
+#include <cutils/properties.h>
// from LOCAL_C_INCLUDES
#include "MediaCodecService.h"
#include "minijail/minijail.h"
+#include <android/hardware/media/omx/1.0/IOmx.h>
+
using namespace android;
int main(int argc __unused, char** argv)
@@ -42,6 +45,21 @@
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
MediaCodecService::instantiate();
+
+ // Treble
+ bool useTrebleOmx = bool(property_get_bool("debug.treble_omx", 0));
+ if (useTrebleOmx) {
+ using namespace ::android::hardware::media::omx::V1_0;
+ sp<IOmx> omx = IOmx::getService(true);
+ if (omx == nullptr) {
+ ALOGE("Cannot create a Treble IOmx service.");
+ } else if (omx->registerAsService("default") != OK) {
+ ALOGE("Cannot register a Treble IOmx service.");
+ } else {
+ ALOGV("Treble IOmx service created.");
+ }
+ }
+
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
diff --git a/services/mediadrm/Android.mk b/services/mediadrm/Android.mk
index f667068..2bf2201 100644
--- a/services/mediadrm/Android.mk
+++ b/services/mediadrm/Android.mk
@@ -24,9 +24,8 @@
libbinder \
liblog \
libmediadrm \
- libutils \
- libandroidfw
-ifeq ($(ENABLE_TREBLE_DRM), true)
+ libutils
+ifeq ($(ENABLE_TREBLE), true)
LOCAL_SHARED_LIBRARIES += \
libhidlbase \
libhidlmemory \
@@ -35,8 +34,8 @@
endif
LOCAL_CFLAGS += -Wall -Wextra -Werror
-ifeq ($(ENABLE_TREBLE_DRM), true)
-LOCAL_CFLAGS += -DENABLE_TREBLE_DRM=1
+ifeq ($(ENABLE_TREBLE), true)
+LOCAL_CFLAGS += -DENABLE_TREBLE=1
endif
LOCAL_MODULE:= mediadrmserver
diff --git a/services/mediadrm/MediaDrmService.cpp b/services/mediadrm/MediaDrmService.cpp
index c709b5e..e579dd8 100644
--- a/services/mediadrm/MediaDrmService.cpp
+++ b/services/mediadrm/MediaDrmService.cpp
@@ -24,7 +24,7 @@
#include <binder/IServiceManager.h>
#include <utils/Log.h>
-#ifdef ENABLE_TREBLE_DRM
+#ifdef ENABLE_TREBLE
#include <media/CryptoHal.h>
#include <media/DrmHal.h>
#else
@@ -40,7 +40,7 @@
}
sp<ICrypto> MediaDrmService::makeCrypto() {
-#ifdef ENABLE_TREBLE_DRM
+#ifdef ENABLE_TREBLE
return new CryptoHal;
#else
return new Crypto;
@@ -48,7 +48,7 @@
}
sp<IDrm> MediaDrmService::makeDrm() {
-#ifdef ENABLE_TREBLE_DRM
+#ifdef ENABLE_TREBLE
return new DrmHal;
#else
return new Drm;
diff --git a/services/oboeservice/Android.mk b/services/oboeservice/Android.mk
index 07b4d76..5a79b80 100644
--- a/services/oboeservice/Android.mk
+++ b/services/oboeservice/Android.mk
@@ -42,7 +42,9 @@
OboeAudioService.cpp \
OboeServiceStreamBase.cpp \
OboeServiceStreamFakeHal.cpp \
- OboeServiceMain.cpp
+ TimestampScheduler.cpp \
+ OboeServiceMain.cpp \
+ OboeThread.cpp
LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_CFLAGS += -Wall -Werror
diff --git a/services/oboeservice/OboeAudioService.cpp b/services/oboeservice/OboeAudioService.cpp
index caddc1d..001569c 100644
--- a/services/oboeservice/OboeAudioService.cpp
+++ b/services/oboeservice/OboeAudioService.cpp
@@ -34,11 +34,20 @@
typedef enum
{
+ OBOE_HANDLE_TYPE_DUMMY1, // TODO remove DUMMYs
+ OBOE_HANDLE_TYPE_DUMMY2, // make server handles different than client
OBOE_HANDLE_TYPE_STREAM,
OBOE_HANDLE_TYPE_COUNT
} oboe_service_handle_type_t;
static_assert(OBOE_HANDLE_TYPE_COUNT <= HANDLE_TRACKER_MAX_TYPES, "Too many handle types.");
+android::OboeAudioService::OboeAudioService()
+ : BnOboeAudioService() {
+}
+
+OboeAudioService::~OboeAudioService() {
+}
+
oboe_handle_t OboeAudioService::openStream(oboe::OboeStreamRequest &request,
oboe::OboeStreamConfiguration &configuration) {
OboeServiceStreamBase *serviceStream = new OboeServiceStreamFakeHal();
@@ -61,7 +70,7 @@
OboeServiceStreamBase *serviceStream = (OboeServiceStreamBase *)
mHandleTracker.remove(OBOE_HANDLE_TYPE_STREAM,
streamHandle);
- ALOGI("OboeAudioService.closeStream(0x%08X)", streamHandle);
+ ALOGD("OboeAudioService.closeStream(0x%08X)", streamHandle);
if (serviceStream != nullptr) {
ALOGD("OboeAudioService::closeStream(): deleting serviceStream = %p", serviceStream);
delete serviceStream;
@@ -79,9 +88,8 @@
oboe_result_t OboeAudioService::getStreamDescription(
oboe_handle_t streamHandle,
oboe::AudioEndpointParcelable &parcelable) {
- ALOGI("OboeAudioService::getStreamDescriptor(), streamHandle = 0x%08x", streamHandle);
OboeServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- ALOGI("OboeAudioService::getStreamDescriptor(), serviceStream = %p", serviceStream);
+ ALOGD("OboeAudioService::getStreamDescription(), serviceStream = %p", serviceStream);
if (serviceStream == nullptr) {
return OBOE_ERROR_INVALID_HANDLE;
}
@@ -90,45 +98,38 @@
oboe_result_t OboeAudioService::startStream(oboe_handle_t streamHandle) {
OboeServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- ALOGI("OboeAudioService::startStream(), serviceStream = %p", serviceStream);
+ ALOGD("OboeAudioService::startStream(), serviceStream = %p", serviceStream);
if (serviceStream == nullptr) {
return OBOE_ERROR_INVALID_HANDLE;
}
- mLatestHandle = streamHandle;
- return serviceStream->start();
+ oboe_result_t result = serviceStream->start();
+ return result;
}
oboe_result_t OboeAudioService::pauseStream(oboe_handle_t streamHandle) {
OboeServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- ALOGI("OboeAudioService::pauseStream(), serviceStream = %p", serviceStream);
+ ALOGD("OboeAudioService::pauseStream(), serviceStream = %p", serviceStream);
if (serviceStream == nullptr) {
return OBOE_ERROR_INVALID_HANDLE;
}
- return serviceStream->pause();
+ oboe_result_t result = serviceStream->pause();
+ return result;
}
oboe_result_t OboeAudioService::flushStream(oboe_handle_t streamHandle) {
OboeServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- ALOGI("OboeAudioService::flushStream(), serviceStream = %p", serviceStream);
+ ALOGD("OboeAudioService::flushStream(), serviceStream = %p", serviceStream);
if (serviceStream == nullptr) {
return OBOE_ERROR_INVALID_HANDLE;
}
return serviceStream->flush();
}
-void OboeAudioService::tickle() {
- OboeServiceStreamBase *serviceStream = convertHandleToServiceStream(mLatestHandle);
- //ALOGI("OboeAudioService::tickle(), serviceStream = %p", serviceStream);
- if (serviceStream != nullptr) {
- serviceStream->tickle();
- }
-}
-
oboe_result_t OboeAudioService::registerAudioThread(oboe_handle_t streamHandle,
pid_t clientThreadId,
oboe_nanoseconds_t periodNanoseconds) {
OboeServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
- ALOGI("OboeAudioService::registerAudioThread(), serviceStream = %p", serviceStream);
+ ALOGD("OboeAudioService::registerAudioThread(), serviceStream = %p", serviceStream);
if (serviceStream == nullptr) {
ALOGE("OboeAudioService::registerAudioThread(), serviceStream == nullptr");
return OBOE_ERROR_INVALID_HANDLE;
diff --git a/services/oboeservice/OboeAudioService.h b/services/oboeservice/OboeAudioService.h
index df3cbf8..b196f1d 100644
--- a/services/oboeservice/OboeAudioService.h
+++ b/services/oboeservice/OboeAudioService.h
@@ -24,31 +24,32 @@
#include <oboe/OboeDefinitions.h>
#include <oboe/OboeAudio.h>
-#include "HandleTracker.h"
+#include "utility/HandleTracker.h"
#include "IOboeAudioService.h"
-#include "OboeService.h"
#include "OboeServiceStreamBase.h"
-using namespace android;
-namespace oboe {
+namespace android {
class OboeAudioService :
public BinderService<OboeAudioService>,
public BnOboeAudioService
{
- friend class BinderService<OboeAudioService>; // for OboeAudioService()
+ friend class BinderService<OboeAudioService>;
+
public:
-// TODO why does this fail? static const char* getServiceName() ANDROID_API { return "media.audio_oboe"; }
+ OboeAudioService();
+ virtual ~OboeAudioService();
+
static const char* getServiceName() { return "media.audio_oboe"; }
- virtual oboe_handle_t openStream(OboeStreamRequest &request,
- OboeStreamConfiguration &configuration);
+ virtual oboe_handle_t openStream(oboe::OboeStreamRequest &request,
+ oboe::OboeStreamConfiguration &configuration);
virtual oboe_result_t closeStream(oboe_handle_t streamHandle);
virtual oboe_result_t getStreamDescription(
oboe_handle_t streamHandle,
- AudioEndpointParcelable &parcelable);
+ oboe::AudioEndpointParcelable &parcelable);
virtual oboe_result_t startStream(oboe_handle_t streamHandle);
@@ -61,16 +62,14 @@
virtual oboe_result_t unregisterAudioThread(oboe_handle_t streamHandle, pid_t pid);
- virtual void tickle();
-
private:
- OboeServiceStreamBase *convertHandleToServiceStream(oboe_handle_t streamHandle) const;
+ oboe::OboeServiceStreamBase *convertHandleToServiceStream(oboe_handle_t streamHandle) const;
HandleTracker mHandleTracker;
- oboe_handle_t mLatestHandle = OBOE_ERROR_INVALID_HANDLE; // TODO until we have service threads
+
};
-} /* namespace oboe */
+} /* namespace android */
#endif //OBOE_OBOE_AUDIO_SERVICE_H
diff --git a/services/oboeservice/OboeServiceStreamBase.cpp b/services/oboeservice/OboeServiceStreamBase.cpp
index 6b7e4e5..15b70a5 100644
--- a/services/oboeservice/OboeServiceStreamBase.cpp
+++ b/services/oboeservice/OboeServiceStreamBase.cpp
@@ -40,12 +40,15 @@
}
OboeServiceStreamBase::~OboeServiceStreamBase() {
+ Mutex::Autolock _l(mLockUpMessageQueue);
delete mUpMessageQueue;
}
void OboeServiceStreamBase::sendServiceEvent(oboe_service_event_t event,
int32_t data1,
int64_t data2) {
+
+ Mutex::Autolock _l(mLockUpMessageQueue);
OboeServiceMessage command;
command.what = OboeServiceMessage::code::EVENT;
command.event.event = event;
diff --git a/services/oboeservice/OboeServiceStreamBase.h b/services/oboeservice/OboeServiceStreamBase.h
index 736c754..33857c6 100644
--- a/services/oboeservice/OboeServiceStreamBase.h
+++ b/services/oboeservice/OboeServiceStreamBase.h
@@ -17,12 +17,14 @@
#ifndef OBOE_OBOE_SERVICE_STREAM_BASE_H
#define OBOE_OBOE_SERVICE_STREAM_BASE_H
+#include <utils/Mutex.h>
+
#include "IOboeAudioService.h"
#include "OboeService.h"
-#include "AudioStream.h"
#include "fifo/FifoBuffer.h"
#include "SharedRingBuffer.h"
#include "AudioEndpointParcelable.h"
+#include "OboeThread.h"
namespace oboe {
@@ -30,7 +32,7 @@
// This should be way more than we need.
#define QUEUE_UP_CAPACITY_COMMANDS (128)
-class OboeServiceStreamBase {
+class OboeServiceStreamBase {
public:
OboeServiceStreamBase();
@@ -68,7 +70,11 @@
virtual oboe_result_t close() = 0;
- virtual void tickle() = 0;
+ virtual void sendCurrentTimestamp() = 0;
+
+ oboe_size_frames_t getFramesPerBurst() {
+ return mFramesPerBurst;
+ }
virtual void sendServiceEvent(oboe_service_event_t event,
int32_t data1 = 0,
@@ -77,6 +83,7 @@
virtual void setRegisteredThread(pid_t pid) {
mRegisteredClientThread = pid;
}
+
virtual pid_t getRegisteredThread() {
return mRegisteredClientThread;
}
@@ -92,6 +99,8 @@
oboe_size_frames_t mFramesPerBurst = 0;
oboe_size_frames_t mCapacityInFrames = 0;
oboe_size_bytes_t mCapacityInBytes = 0;
+
+ android::Mutex mLockUpMessageQueue;
};
} /* namespace oboe */
diff --git a/services/oboeservice/OboeServiceStreamFakeHal.cpp b/services/oboeservice/OboeServiceStreamFakeHal.cpp
index dbbc860..da4099d 100644
--- a/services/oboeservice/OboeServiceStreamFakeHal.cpp
+++ b/services/oboeservice/OboeServiceStreamFakeHal.cpp
@@ -18,6 +18,8 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <atomic>
+
#include "AudioClock.h"
#include "AudioEndpointParcelable.h"
@@ -41,6 +43,7 @@
: OboeServiceStreamBase()
, mStreamId(nullptr)
, mPreviousFrameCounter(0)
+ , mOboeThread()
{
}
@@ -86,7 +89,8 @@
// Fill in OboeStreamConfiguration
configuration.setSampleRate(mSampleRate);
configuration.setSamplesPerFrame(mmapInfo.channel_count);
- configuration.setAudioFormat(OBOE_AUDIO_FORMAT_PCM16);
+ configuration.setAudioFormat(OBOE_AUDIO_FORMAT_PCM_I16);
+
return OBOE_OK;
}
@@ -117,6 +121,10 @@
oboe_result_t result = fake_hal_start(mStreamId);
sendServiceEvent(OBOE_SERVICE_EVENT_STARTED);
mState = OBOE_STREAM_STATE_STARTED;
+ if (result == OBOE_OK) {
+ mThreadEnabled.store(true);
+ result = mOboeThread.start(this);
+ }
return result;
}
@@ -131,6 +139,8 @@
mState = OBOE_STREAM_STATE_PAUSED;
mFramesRead.reset32();
ALOGD("OboeServiceStreamFakeHal::pause() sent OBOE_SERVICE_EVENT_PAUSED");
+ mThreadEnabled.store(false);
+ result = mOboeThread.stop();
return result;
}
@@ -166,7 +176,7 @@
command.what = OboeServiceMessage::code::TIMESTAMP;
mFramesRead.update32(frameCounter);
command.timestamp.position = mFramesRead.get();
- ALOGV("OboeServiceStreamFakeHal::sendCurrentTimestamp() HAL frames = %d, pos = %d",
+ ALOGD("OboeServiceStreamFakeHal::sendCurrentTimestamp() HAL frames = %d, pos = %d",
frameCounter, (int)mFramesRead.get());
command.timestamp.timestamp = AudioClock::getNanoseconds();
mUpMessageQueue->getFifoBuffer()->write(&command, 1);
@@ -174,17 +184,18 @@
}
}
-void OboeServiceStreamFakeHal::tickle() {
- if (mStreamId != nullptr) {
- switch (mState) {
- case OBOE_STREAM_STATE_STARTING:
- case OBOE_STREAM_STATE_STARTED:
- case OBOE_STREAM_STATE_PAUSING:
- case OBOE_STREAM_STATE_STOPPING:
- sendCurrentTimestamp();
- break;
- default:
- break;
+// implement Runnable
+void OboeServiceStreamFakeHal::run() {
+ TimestampScheduler timestampScheduler;
+ timestampScheduler.setBurstPeriod(mFramesPerBurst, mSampleRate);
+ timestampScheduler.start(AudioClock::getNanoseconds());
+ while(mThreadEnabled.load()) {
+ oboe_nanoseconds_t nextTime = timestampScheduler.nextAbsoluteTime();
+ if (AudioClock::getNanoseconds() >= nextTime) {
+ sendCurrentTimestamp();
+ } else {
+ // Sleep until it is time to send the next timestamp.
+ AudioClock::sleepUntilNanoTime(nextTime);
}
}
}
diff --git a/services/oboeservice/OboeServiceStreamFakeHal.h b/services/oboeservice/OboeServiceStreamFakeHal.h
index b026d34..39b952a 100644
--- a/services/oboeservice/OboeServiceStreamFakeHal.h
+++ b/services/oboeservice/OboeServiceStreamFakeHal.h
@@ -22,10 +22,13 @@
#include "FakeAudioHal.h"
#include "MonotonicCounter.h"
#include "AudioEndpointParcelable.h"
+#include "TimestampScheduler.h"
namespace oboe {
-class OboeServiceStreamFakeHal : public OboeServiceStreamBase {
+class OboeServiceStreamFakeHal
+ : public OboeServiceStreamBase
+ , public Runnable {
public:
OboeServiceStreamFakeHal();
@@ -53,12 +56,10 @@
virtual oboe_result_t close() override;
- virtual void tickle() override;
-
-protected:
-
void sendCurrentTimestamp();
+ virtual void run() override; // to implement Runnable
+
private:
fake_hal_stream_ptr mStreamId; // Move to HAL
@@ -68,6 +69,9 @@
int mPreviousFrameCounter = 0; // from HAL
oboe_stream_state_t mState = OBOE_STREAM_STATE_UNINITIALIZED;
+
+ OboeThread mOboeThread;
+ std::atomic<bool> mThreadEnabled;
};
} // namespace oboe
diff --git a/services/oboeservice/OboeThread.cpp b/services/oboeservice/OboeThread.cpp
new file mode 100644
index 0000000..9ecfa90
--- /dev/null
+++ b/services/oboeservice/OboeThread.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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 "OboeService"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <pthread.h>
+
+#include <oboe/OboeDefinitions.h>
+
+#include "OboeThread.h"
+
+using namespace oboe;
+
+
+OboeThread::OboeThread() {
+ // mThread is a pthread_t of unknown size so we need memset.
+ memset(&mThread, 0, sizeof(mThread));
+}
+
+void OboeThread::dispatch() {
+ if (mRunnable != nullptr) {
+ mRunnable->run();
+ } else {
+ run();
+ }
+}
+
+// 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 * OboeThread_internalThreadProc(void *arg) {
+ OboeThread *oboeThread = (OboeThread *) arg;
+ oboeThread->dispatch();
+ return nullptr;
+}
+
+oboe_result_t OboeThread::start(Runnable *runnable) {
+ if (mHasThread) {
+ return OBOE_ERROR_INVALID_STATE;
+ }
+ mRunnable = runnable; // TODO use atomic?
+ int err = pthread_create(&mThread, nullptr, OboeThread_internalThreadProc, this);
+ if (err != 0) {
+ ALOGE("OboeThread::pthread_create() returned %d", err);
+ // TODO convert errno to oboe_result_t
+ return OBOE_ERROR_INTERNAL;
+ } else {
+ mHasThread = true;
+ return OBOE_OK;
+ }
+}
+
+oboe_result_t OboeThread::stop() {
+ if (!mHasThread) {
+ return OBOE_ERROR_INVALID_STATE;
+ }
+ int err = pthread_join(mThread, nullptr);
+ mHasThread = false;
+ // TODO convert errno to oboe_result_t
+ return err ? OBOE_ERROR_INTERNAL : OBOE_OK;
+}
+
diff --git a/services/oboeservice/OboeThread.h b/services/oboeservice/OboeThread.h
new file mode 100644
index 0000000..48fafc7
--- /dev/null
+++ b/services/oboeservice/OboeThread.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 OBOE_THREAD_H
+#define OBOE_THREAD_H
+
+#include <atomic>
+#include <pthread.h>
+
+#include <oboe/OboeDefinitions.h>
+
+namespace oboe {
+
+class Runnable {
+public:
+ Runnable() {};
+ virtual ~Runnable() = default;
+
+ virtual void run() {}
+};
+
+/**
+ * Abstraction for a host thread.
+ */
+class OboeThread
+{
+public:
+ OboeThread();
+ OboeThread(Runnable *runnable);
+ virtual ~OboeThread() = default;
+
+ /**
+ * Start the thread running.
+ */
+ oboe_result_t start(Runnable *runnable = nullptr);
+
+ /**
+ * Join the thread.
+ * The caller must somehow tell the thread to exit before calling join().
+ */
+ oboe_result_t stop();
+
+ /**
+ * This will get called in the thread.
+ * Override this or pass a Runnable to start().
+ */
+ virtual void run() {};
+
+ void dispatch(); // called internally from 'C' thread wrapper
+
+private:
+ Runnable* mRunnable = nullptr; // TODO make atomic with memory barrier?
+ bool mHasThread = false;
+ pthread_t mThread; // initialized in constructor
+
+};
+
+} /* namespace oboe */
+
+#endif ///OBOE_THREAD_H
diff --git a/services/oboeservice/TimestampScheduler.cpp b/services/oboeservice/TimestampScheduler.cpp
new file mode 100644
index 0000000..17d6c63
--- /dev/null
+++ b/services/oboeservice/TimestampScheduler.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+// for random()
+#include <stdlib.h>
+
+#include "TimestampScheduler.h"
+
+using namespace oboe;
+
+void TimestampScheduler::start(oboe_nanoseconds_t startTime) {
+ mStartTime = startTime;
+ mLastTime = startTime;
+}
+
+oboe_nanoseconds_t TimestampScheduler::nextAbsoluteTime() {
+ int64_t periodsElapsed = (mLastTime - mStartTime) / mBurstPeriod;
+ // This is an arbitrary schedule that could probably be improved.
+ // It starts out sending a timestamp on every period because we want to
+ // get an accurate picture when the stream starts. Then it slows down
+ // to the occasional timestamps needed to detect a slow drift.
+ int64_t minPeriodsToDelay = (periodsElapsed < 10) ? 1 :
+ (periodsElapsed < 100) ? 3 :
+ (periodsElapsed < 1000) ? 10 : 50;
+ oboe_nanoseconds_t sleepTime = minPeriodsToDelay * mBurstPeriod;
+ // Generate a random rectangular distribution one burst wide so that we get
+ // an uncorrelated sampling of the MMAP pointer.
+ sleepTime += (oboe_nanoseconds_t)(random() * mBurstPeriod / RAND_MAX);
+ mLastTime += sleepTime;
+ return mLastTime;
+}
diff --git a/services/oboeservice/TimestampScheduler.h b/services/oboeservice/TimestampScheduler.h
new file mode 100644
index 0000000..041e432
--- /dev/null
+++ b/services/oboeservice/TimestampScheduler.h
@@ -0,0 +1,76 @@
+/*
+ * 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 OBOE_TIMESTAMP_SCHEDULER_H
+#define OBOE_TIMESTAMP_SCHEDULER_H
+
+//#include <stdlib.h> // random()
+
+#include "IOboeAudioService.h"
+#include "OboeService.h"
+#include "AudioStream.h"
+#include "fifo/FifoBuffer.h"
+#include "SharedRingBuffer.h"
+#include "AudioEndpointParcelable.h"
+
+namespace oboe {
+
+/**
+ * Schedule wakeup time for monitoring the position
+ * of an MMAP/NOIRQ buffer.
+ *
+ * Note that this object is not thread safe. Only call it from a single thread.
+ */
+class TimestampScheduler
+{
+public:
+ TimestampScheduler() {};
+ virtual ~TimestampScheduler() = default;
+
+ /**
+ * Start the schedule at the given time.
+ */
+ void start(oboe_nanoseconds_t startTime);
+
+ /**
+ * Calculate the next time that the read position should be
+ * measured.
+ */
+ oboe_nanoseconds_t nextAbsoluteTime();
+
+ void setBurstPeriod(oboe_nanoseconds_t burstPeriod) {
+ mBurstPeriod = burstPeriod;
+ }
+
+ void setBurstPeriod(oboe_size_frames_t framesPerBurst,
+ oboe_sample_rate_t sampleRate) {
+ mBurstPeriod = OBOE_NANOS_PER_SECOND * framesPerBurst / sampleRate;
+ }
+
+ oboe_nanoseconds_t getBurstPeriod() {
+ return mBurstPeriod;
+ }
+
+private:
+ // Start with an arbitrary default so we do not divide by zero.
+ oboe_nanoseconds_t mBurstPeriod = OBOE_NANOS_PER_MILLISECOND;
+ oboe_nanoseconds_t mStartTime;
+ oboe_nanoseconds_t mLastTime;
+};
+
+} /* namespace oboe */
+
+#endif /* OBOE_TIMESTAMP_SCHEDULER_H */