summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul McLean <pmclean@google.com>2016-03-04 14:04:28 -0700
committerPaul McLean <pmclean@google.com>2016-03-09 08:16:56 -0700
commit053b3c2696e5e1b28dd5e02c54b0e3aedc21168d (patch)
treed47246bb9b1f144f710e2581b1d71cb6af02e1e1
parent96c2d9fb5afbaca71e04afa1f5fb933aa28f06f7 (diff)
downloadandroid_frameworks_wilhelm-053b3c2696e5e1b28dd5e02c54b0e3aedc21168d.tar.gz
android_frameworks_wilhelm-053b3c2696e5e1b28dd5e02c54b0e3aedc21168d.tar.bz2
android_frameworks_wilhelm-053b3c2696e5e1b28dd5e02c54b0e3aedc21168d.zip
"Refinements" to Native Audio Routing API
Change method names to more generic "AcquireJavaProxy" to support (potentially) multiple proxy types. Add "Release" method. Remove JNIEnv* parameter from Acquire and Release methods. Add Type ID parameter to support (potential) multiple proxy types. Enforce "singleton" allocation for proxies. Disallow proxy acquisition for innapropriate players/recorders. Refactor to make the code clearer. Bug: 23899814 Change-Id: Iff354ba46547781e0998a9032de96f445d1474b8
-rw-r--r--include/SLES/OpenSLES_Android.h14
-rw-r--r--src/Android.mk3
-rw-r--r--src/itf/IAndroidConfiguration.c318
-rw-r--r--src/itfstruct.h4
4 files changed, 258 insertions, 81 deletions
diff --git a/include/SLES/OpenSLES_Android.h b/include/SLES/OpenSLES_Android.h
index 122b0af..dc85580 100644
--- a/include/SLES/OpenSLES_Android.h
+++ b/include/SLES/OpenSLES_Android.h
@@ -194,6 +194,11 @@ extern SL_API const SLInterfaceID SL_IID_ANDROIDCONFIGURATION;
struct SLAndroidConfigurationItf_;
typedef const struct SLAndroidConfigurationItf_ * const * SLAndroidConfigurationItf;
+/*
+ * Java Proxy Type IDs
+ */
+#define SL_ANDROID_JAVA_PROXY_ROUTING 0x0001
+
struct SLAndroidConfigurationItf_ {
SLresult (*SetConfiguration) (SLAndroidConfigurationItf self,
@@ -207,9 +212,12 @@ struct SLAndroidConfigurationItf_ {
void *pConfigValue
);
- SLresult (*AcquireJavaAudioRouting) (SLAndroidConfigurationItf self,
- JNIEnv* j_env,
- jobject *pObject);
+ SLresult (*AcquireJavaProxy) (SLAndroidConfigurationItf self,
+ SLuint32 proxyType,
+ jobject *pProxyObj);
+
+ SLresult (*ReleaseJavaProxy) (SLAndroidConfigurationItf self,
+ SLuint32 proxyType);
};
diff --git a/src/Android.mk b/src/Android.mk
index a40a8e5..6d1f8ba 100644
--- a/src/Android.mk
+++ b/src/Android.mk
@@ -186,7 +186,8 @@ LOCAL_SHARED_LIBRARIES := \
libcutils \
libgui \
libdl \
- libeffects
+ libeffects \
+ libandroid_runtime
# For Brillo, we do not want this dependency as it significantly increases the
# size of the checkout. Also, the library is dependent on Java (which is not
diff --git a/src/itf/IAndroidConfiguration.c b/src/itf/IAndroidConfiguration.c
index 506e2cc..9465269 100644
--- a/src/itf/IAndroidConfiguration.c
+++ b/src/itf/IAndroidConfiguration.c
@@ -16,9 +16,13 @@
/* AndroidConfiguration implementation */
+#include <android/log.h>
+
#include "sles_allinclusive.h"
#include <SLES/OpenSLES_Android.h>
+#include <android_runtime/AndroidRuntime.h>
+
static SLresult IAndroidConfiguration_SetConfiguration(SLAndroidConfigurationItf self,
const SLchar *configKey,
const void *pConfigValue,
@@ -98,104 +102,191 @@ static SLresult IAndroidConfiguration_GetConfiguration(SLAndroidConfigurationItf
/*
* Native Routing API
*/
+static SLresult ValidatePlayerConfig(IAndroidConfiguration* iConfig) {
+ SLresult result;
+
+ if (iConfig->mRoutingProxy != NULL) {
+ result = SL_RESULT_PRECONDITIONS_VIOLATED;
+ SL_LOGE("Error creating routing object - Routing Proxy Already Acquired.");
+ }
+ else {
+ IObject* configObj = iConfig->mThis; // get corresponding object
+ CAudioPlayer* player = (CAudioPlayer*)configObj; // get the native player
+
+ switch (player->mAndroidObjType) {
+ case AUDIOPLAYER_FROM_PCM_BUFFERQUEUE:
+ if (player->mObject.mState != SL_OBJECT_STATE_REALIZED) {
+ // Make sure the player has been realized.
+ result = SL_RESULT_PRECONDITIONS_VIOLATED;
+ SL_LOGE("Error creating routing object - Player not realized.");
+ } else {
+ android::AudioTrack* pAudioTrack = player->mAudioTrack.get();
+ if (pAudioTrack == NULL) {
+ result = SL_RESULT_INTERNAL_ERROR;
+ SL_LOGE("Error creating routing object - Couldn't get AudioTrack.");
+ } else {
+ result = SL_RESULT_SUCCESS;
+ }
+ }
+ break;
+
+ default:
+ result = SL_RESULT_PARAMETER_INVALID;
+ SL_LOGE("Error creating routing object - Player is not a buffer-queue player.");
+ break;
+ }
+ }
+
+ return result;
+}
+
+static SLresult AllocPlayerRoutingProxy(IAndroidConfiguration* iConfig, jobject* proxyObj) {
+ SLresult result;
+
+ IObject* configObj = iConfig->mThis; // get corresponding object
+ android::AudioTrack* pAudioTrack = ((CAudioPlayer*)configObj)->mAudioTrack.get();
+
+ JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
+
+ // Get the constructor for (Java) AudioTrackRoutingProxy
+ jclass clsAudioTrackRoutingProxy =
+ j_env->FindClass("android/media/AudioTrackRoutingProxy");
+ jmethodID midAudioTrackRoutingProxy_ctor =
+ j_env->GetMethodID(clsAudioTrackRoutingProxy, "<init>", "(J)V");
+
+ j_env->ExceptionClear();
+
+ jobject localObjRef =
+ j_env->NewObject(clsAudioTrackRoutingProxy,
+ midAudioTrackRoutingProxy_ctor,
+ (uintptr_t)pAudioTrack /*audioTrackObjInLong*/);
+ *proxyObj = j_env->NewGlobalRef(localObjRef);
+
+ if (j_env->ExceptionCheck()) {
+ SL_LOGE("Java exception creating player routing object.");
+ result = SL_RESULT_INTERNAL_ERROR;
+ } else {
+ // stash it in the Interface object
+ iConfig->mRoutingProxy = *proxyObj;
+ result = SL_RESULT_SUCCESS;
+ }
+
+ return result;
+}
+
+static SLresult ValidateRecorderConfig(IAndroidConfiguration* iConfig) {
+ SLresult result;
+
+ if (iConfig->mRoutingProxy != NULL) {
+ result = SL_RESULT_PRECONDITIONS_VIOLATED;
+ SL_LOGE("Error creating routing object - Routing Proxy Already Acquired.");
+ } else {
+ IObject* configObj = iConfig->mThis; // get corresponding object
+ CAudioRecorder* recorder = (CAudioRecorder*)configObj; // get the native recorder
+ switch (recorder->mAndroidObjType) {
+ case AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE:
+ if (recorder->mObject.mState != SL_OBJECT_STATE_REALIZED) {
+ // Make sure the recorder has been realized.
+ result = SL_RESULT_PRECONDITIONS_VIOLATED;
+ SL_LOGE("Error creating routing object - Recorder not realized.");
+ } else {
+ android::AudioRecord* pAudioRecord = recorder->mAudioRecord.get();
+ if (pAudioRecord == NULL) {
+ result = SL_RESULT_INTERNAL_ERROR;
+ SL_LOGE("Error creating routing object - Couldn't get AudioRecord.");
+ } else if (iConfig->mRoutingProxy != NULL) {
+ result = SL_RESULT_PRECONDITIONS_VIOLATED;
+ SL_LOGE("Error creating routing object - Routing Proxy Already Acquired.");
+ } else {
+ result = SL_RESULT_SUCCESS;
+ }
+ }
+ break;
+
+ default:
+ result = SL_RESULT_PARAMETER_INVALID;
+ SL_LOGE("Error creating routing object - Recorder is not a buffer-queue recorder.");
+ break;
+ }
+ }
+
+ return result;
+}
+
+static SLresult AllocRecorderRoutingProxy(IAndroidConfiguration* iConfig, jobject* proxyObj) {
+ SLresult result;
+
+ IObject* configObj = iConfig->mThis; // get corresponding object
+ android::AudioRecord* pAudioRecord = ((CAudioRecorder*)configObj)->mAudioRecord.get();
+
+ JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
+
+ // Get the constructor for (Java) AudioRecordRoutingProxy
+ jclass clsAudioRecordRoutingProxy =
+ j_env->FindClass("android/media/AudioRecordRoutingProxy");
+ jmethodID midAudioRecordRoutingProxy_ctor =
+ j_env->GetMethodID(clsAudioRecordRoutingProxy, "<init>", "(J)V");
+
+ j_env->ExceptionClear();
+ jobject localObjRef =
+ j_env->NewObject(clsAudioRecordRoutingProxy,
+ midAudioRecordRoutingProxy_ctor,
+ (uintptr_t)pAudioRecord /*audioRecordObjInLong*/);
+ *proxyObj = j_env->NewGlobalRef(localObjRef);
+ if (j_env->ExceptionCheck()) {
+ SL_LOGE("Java exception creating recorder routing object.");
+ result = SL_RESULT_INTERNAL_ERROR;
+ } else {
+ // stash it in the Interface object
+ iConfig->mRoutingProxy = *proxyObj;
+ result = SL_RESULT_SUCCESS;
+ }
+
+ return result;
+}
/*
- * Acquires a Java AudioRouting object (interface implementation) which can be used to control
- * the routing of the associated native player or recorder. Note that the Java Routing object
- * can not be acquired until the AudioTrack or AudioRecorder associated with the
- * SLAndroidConfigurationItf has been realized (i.e. SLPlayItf::realize() or
- * SLRecordItf::realize() has been called).
+ * Acquires a Java proxy object, such as AudioRouting object which can be used to control
+ * aspects of the associated native player or recorder.
* Parameters:
* self An SLAndroidConfigurationItf obtained from either an OpenSL ES AudioPlayer
* or AudioRecorder.
* j_env The Java Environment pointer (passed in to the calling JNI function).
- * pObject Points to the jobject to receive the acquired AudioRouting interface
- * implementation.
- * Returns SL_RESULT_SUCCESS is the AudioRouting is acquired, SL_RESULT_PARAMETER_INVALID if
+ * proxyType Specifies the type of proxy desired. Currently only SL_ANDROID_JAVA_PROXY_ROUTING
+ * is supported.
+ * proxyObj
+ * Points to the jobject to receive the acquired Java proxy object (as a GlobalRef).
+ * Returns SL_RESULT_SUCCESS is the proxy object is acquired, SL_RESULT_PARAMETER_INVALID if
* there is a problem with the arguments causing the function to fail,
+ * <working on this>
* SL_RESULT_PRECONDITIONS_VIOLATED it the AudioPlayer or AudioRecorder object associated
* with the ConfigurationItf has not been realized.
*/
-static SLresult IAndroidConfiguration_AcquireJavaAudioRouting(SLAndroidConfigurationItf self,
- JNIEnv *j_env, jobject *pObject)
+static SLresult IAndroidConfiguration_AcquireJavaProxy(SLAndroidConfigurationItf self,
+ SLuint32 proxyType,
+ jobject* proxyObj)
{
SL_ENTER_INTERFACE
- if (j_env == NULL || self == NULL || pObject == NULL) {
+ if (self == NULL || proxyObj == NULL || proxyType != SL_ANDROID_JAVA_PROXY_ROUTING) {
result = SL_RESULT_PARAMETER_INVALID;
} else {
- IObject *thisObject = InterfaceToIObject((IAndroidConfiguration *) self);
+ IAndroidConfiguration* iConfig = (IAndroidConfiguration*)self;
- switch (IObjectToObjectID(thisObject)) {
+ int objID = IObjectToObjectID(InterfaceToIObject(iConfig));
+ switch (objID) {
case SL_OBJECTID_AUDIOPLAYER:
- {
- // Get the constructor for (Java) AudioTrackRoutingProxy
- jclass clsAudioTrackRoutingProxy =
- j_env->FindClass("android/media/AudioTrackRoutingProxy");
- jmethodID midAudioTrackRoutingProxy_ctor =
- j_env->GetMethodID(clsAudioTrackRoutingProxy, "<init>", "(J)V");
-
- IAndroidConfiguration* configItf = (IAndroidConfiguration*)self; // Get internal struct
- IObject* configObj = configItf->mThis; // get corresponding object
- CAudioPlayer* player = (CAudioPlayer*)configObj; // get the native player
-
- // Make sure the player has been realized.
- if (player->mObject.mState != SL_OBJECT_STATE_REALIZED) {
- result = SL_RESULT_PRECONDITIONS_VIOLATED;
- SL_LOGE("Error creating routing object - Player not realized.");
- } else {
- android::AudioTrack* pAudioTrack = player->mAudioTrack.get();
- if (pAudioTrack == NULL) {
- result = SL_RESULT_INTERNAL_ERROR;
- } else {
- *pObject = j_env->NewObject(clsAudioTrackRoutingProxy,
- midAudioTrackRoutingProxy_ctor,
- (uintptr_t)pAudioTrack /*audioTrackObjInLong*/);
- if (j_env->ExceptionCheck()) {
- SL_LOGE("Java exception creating player routing object.");
- result = SL_RESULT_INTERNAL_ERROR;
- } else {
- result = SL_RESULT_SUCCESS;
- }
- }
+ result = ValidatePlayerConfig(iConfig);
+ if (result == SL_RESULT_SUCCESS) {
+ result = AllocPlayerRoutingProxy(iConfig, proxyObj);
}
- }
break;
case SL_OBJECTID_AUDIORECORDER:
- {
- // Get the constructor for (Java) AudioRecordRoutingProxy
- jclass clsAudioRecordRoutingProxy =
- j_env->FindClass("android/media/AudioRecordRoutingProxy");
- jmethodID midAudioRecordRoutingProxy_ctor =
- j_env->GetMethodID(clsAudioRecordRoutingProxy, "<init>", "(J)V");
-
- IAndroidConfiguration* configItf = (IAndroidConfiguration*)self; // Get internal struct
- IObject* configObj = configItf->mThis; // get corresponding object
- CAudioRecorder* recorder = (CAudioRecorder*)configObj; // get the native recorder
-
- // Make sure the recorder has been realized.
- if (recorder->mObject.mState != SL_OBJECT_STATE_REALIZED) {
- result = SL_RESULT_PRECONDITIONS_VIOLATED;
- SL_LOGE("Error creating routing object - Recorder not realized.");
- } else {
- android::AudioRecord* pAudioRecord = recorder->mAudioRecord.get();
- if (pAudioRecord == NULL) {
- result = SL_RESULT_INTERNAL_ERROR;
- } else {
- *pObject =
- j_env->NewObject(clsAudioRecordRoutingProxy,
- midAudioRecordRoutingProxy_ctor,
- (uintptr_t)pAudioRecord /*audioRecordObjInLong*/);
- if (j_env->ExceptionCheck()) {
- SL_LOGE("Java exception creating recorder routing object.");
- result = SL_RESULT_INTERNAL_ERROR;
- } else {
- result = SL_RESULT_SUCCESS;
- }
- }
+ result = ValidateRecorderConfig(iConfig);
+ if (result == SL_RESULT_SUCCESS) {
+ result = AllocRecorderRoutingProxy(iConfig, proxyObj);
}
- }
break;
default:
@@ -207,10 +298,83 @@ static SLresult IAndroidConfiguration_AcquireJavaAudioRouting(SLAndroidConfigura
SL_LEAVE_INTERFACE
}
+/*
+ * Release a Java proxy object, such as AudioRouting object, (and any resources it is holding).
+ * Parameters:
+ * self An SLAndroidConfigurationItf obtained from either an OpenSL ES AudioPlayer
+ * or AudioRecorder.
+ * j_env The Java Environment pointer (passed in to the calling JNI function).
+ * proxyType Specifies the type of proxy object. Currently only SL_ANDROID_JAVA_PROXY_ROUTING
+ * is supported.
+ * Returns SL_RESULT_SUCCESS is the proxy object is release, SL_RESULT_PARAMETER_INVALID if
+ * there is a problem with the arguments causing the function to fail,
+ */
+static SLresult IAndroidConfiguration_ReleaseJavaProxy(SLAndroidConfigurationItf self,
+ SLuint32 proxyType) {
+ SL_ENTER_INTERFACE
+
+ IAndroidConfiguration* iConfig = (IAndroidConfiguration*)self;
+
+ if (self == NULL ||
+ proxyType != SL_ANDROID_JAVA_PROXY_ROUTING ||
+ iConfig->mRoutingProxy == NULL) {
+ result = SL_RESULT_PARAMETER_INVALID;
+ } else {
+ int objID = IObjectToObjectID(InterfaceToIObject(iConfig));
+ switch (objID) {
+ case SL_OBJECTID_AUDIOPLAYER:
+ {
+ JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
+
+ // Get the release method for (Java) AudioTrackRoutingProxy
+ jclass clsAudioTrackRoutingProxy =
+ j_env->FindClass("android/media/AudioTrackRoutingProxy");
+ jmethodID midAudioTrackRoutingProxy_release =
+ j_env->GetMethodID(clsAudioTrackRoutingProxy, "native_release", "()V");
+
+ j_env->ExceptionClear();
+ j_env->CallVoidMethod(iConfig->mRoutingProxy, midAudioTrackRoutingProxy_release);
+ if (j_env->ExceptionCheck()) {
+ SL_LOGE("Java exception releasing recorder routing object.");
+ result = SL_RESULT_INTERNAL_ERROR;
+ }
+ j_env->DeleteGlobalRef(iConfig->mRoutingProxy);
+ iConfig->mRoutingProxy = NULL;
+ }
+ break;
+
+ case SL_OBJECTID_AUDIORECORDER:
+ {
+ JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
+
+ // Get the release method for (Java) AudioTrackRoutingProxy
+ jclass clsAudioRecordRoutingProxy =
+ j_env->FindClass("android/media/AudioRecordRoutingProxy");
+ jmethodID midAudioRecordRoutingProxy_release =
+ j_env->GetMethodID(clsAudioRecordRoutingProxy, "native_release", "()V");
+
+ j_env->ExceptionClear();
+ j_env->CallVoidMethod(iConfig->mRoutingProxy, midAudioRecordRoutingProxy_release);
+ if (j_env->ExceptionCheck()) {
+ SL_LOGE("Java exception releasing recorder routing object.");
+ result = SL_RESULT_INTERNAL_ERROR;
+ }
+ j_env->DeleteGlobalRef(iConfig->mRoutingProxy);
+ iConfig->mRoutingProxy = NULL;
+ }
+ break;
+ }
+ result = SL_RESULT_SUCCESS;
+ }
+
+ SL_LEAVE_INTERFACE
+}
+
static const struct SLAndroidConfigurationItf_ IAndroidConfiguration_Itf = {
IAndroidConfiguration_SetConfiguration,
IAndroidConfiguration_GetConfiguration,
- IAndroidConfiguration_AcquireJavaAudioRouting
+ IAndroidConfiguration_AcquireJavaProxy,
+ IAndroidConfiguration_ReleaseJavaProxy
};
void IAndroidConfiguration_init(void *self)
diff --git a/src/itfstruct.h b/src/itfstruct.h
index 815f21e..c1e111e 100644
--- a/src/itfstruct.h
+++ b/src/itfstruct.h
@@ -16,6 +16,8 @@
#include "Configuration.h"
#ifdef ANDROID
+#include <jni.h>
+
#include "media/AudioEffect.h"
#include "hardware/audio_effect.h"
#endif
@@ -662,6 +664,8 @@ typedef struct {
typedef struct {
const struct SLAndroidConfigurationItf_ *mItf;
IObject *mThis;
+ // only 1 each. When we support other Proxy types, we will need to get more clever about this.
+ jobject mRoutingProxy;
} IAndroidConfiguration;
typedef struct {