summaryrefslogtreecommitdiffstats
path: root/core/jni
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2014-12-10 01:33:07 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-12-10 01:33:09 +0000
commit65bc1125b4bdb0e982b37e76ab8a9a66adefd2e0 (patch)
tree6b9e3c09ccef421e93dd1e916a528b7de261a277 /core/jni
parent37f271869ed9c9e9f0e7de7339017e0bb6719780 (diff)
parent7f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02 (diff)
downloadframeworks_base-65bc1125b4bdb0e982b37e76ab8a9a66adefd2e0.zip
frameworks_base-65bc1125b4bdb0e982b37e76ab8a9a66adefd2e0.tar.gz
frameworks_base-65bc1125b4bdb0e982b37e76ab8a9a66adefd2e0.tar.bz2
Merge "AudioSystem JNI: Add audio policy custom mixes registration" into lmp-mr1-dev
Diffstat (limited to 'core/jni')
-rw-r--r--core/jni/android_media_AudioSystem.cpp199
1 files changed, 199 insertions, 0 deletions
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index cabe200..fee1ead 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -25,6 +25,7 @@
#include <android_runtime/AndroidRuntime.h>
#include <media/AudioSystem.h>
+#include <media/AudioPolicy.h>
#include <system/audio.h>
#include <system/audio_policy.h>
@@ -40,6 +41,7 @@ static const char* const kClassPathName = "android/media/AudioSystem";
static jclass gArrayListClass;
static struct {
jmethodID add;
+ jmethodID toArray;
} gArrayListMethods;
static jclass gAudioHandleClass;
@@ -102,6 +104,42 @@ static struct {
// other fields unused by JNI
} gAudioPatchFields;
+static jclass gAudioMixClass;
+static struct {
+ jfieldID mRule;
+ jfieldID mFormat;
+ jfieldID mRouteFlags;
+ jfieldID mRegistrationId;
+ jfieldID mMixType;
+} gAudioMixFields;
+
+static jclass gAudioFormatClass;
+static struct {
+ jfieldID mEncoding;
+ jfieldID mSampleRate;
+ jfieldID mChannelMask;
+ // other fields unused by JNI
+} gAudioFormatFields;
+
+static jclass gAudioMixingRuleClass;
+static struct {
+ jfieldID mCriteria;
+ // other fields unused by JNI
+} gAudioMixingRuleFields;
+
+static jclass gAttributeMatchCriterionClass;
+static struct {
+ jfieldID mAttr;
+ jfieldID mRule;
+} gAttributeMatchCriterionFields;
+
+static jclass gAudioAttributesClass;
+static struct {
+ jfieldID mUsage;
+ jfieldID mSource;
+} gAudioAttributesFields;
+
+
static const char* const kEventHandlerClassPathName =
"android/media/AudioPortEventHandler";
static jmethodID gPostEventFromNative;
@@ -1322,6 +1360,128 @@ android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, ji
return (jint)AudioSystem::getAudioHwSyncForSession((audio_session_t)sessionId);
}
+
+
+
+static jint convertAudioMixToNative(JNIEnv *env,
+ AudioMix *nAudioMix,
+ const jobject jAudioMix)
+{
+ nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
+ nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
+
+ jstring jRegistrationId = (jstring)env->GetObjectField(jAudioMix,
+ gAudioMixFields.mRegistrationId);
+ const char *nRegistrationId = env->GetStringUTFChars(jRegistrationId, NULL);
+ nAudioMix->mRegistrationId = String8(nRegistrationId);
+ env->ReleaseStringUTFChars(jRegistrationId, nRegistrationId);
+ env->DeleteLocalRef(jRegistrationId);
+
+ jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
+ nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat,
+ gAudioFormatFields.mSampleRate);
+ nAudioMix->mFormat.channel_mask = outChannelMaskToNative(env->GetIntField(jFormat,
+ gAudioFormatFields.mChannelMask));
+ nAudioMix->mFormat.format = audioFormatToNative(env->GetIntField(jFormat,
+ gAudioFormatFields.mEncoding));
+ env->DeleteLocalRef(jFormat);
+
+ jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
+ jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
+ env->DeleteLocalRef(jRule);
+ jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria,
+ gArrayListMethods.toArray);
+ env->DeleteLocalRef(jRuleCriteria);
+
+ jint numCriteria = env->GetArrayLength(jCriteria);
+ if (numCriteria > MAX_CRITERIA_PER_MIX) {
+ numCriteria = MAX_CRITERIA_PER_MIX;
+ }
+
+ for (jint i = 0; i < numCriteria; i++) {
+ AttributeMatchCriterion nCriterion;
+
+ jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
+
+ nCriterion.mRule = env->GetIntField(jCriterion, gAttributeMatchCriterionFields.mRule);
+
+ jobject jAttributes = env->GetObjectField(jCriterion, gAttributeMatchCriterionFields.mAttr);
+ if (nCriterion.mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
+ nCriterion.mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
+ nCriterion.mAttr.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
+ gAudioAttributesFields.mUsage);
+ } else {
+ nCriterion.mAttr.mSource = (audio_source_t)env->GetIntField(jAttributes,
+ gAudioAttributesFields.mSource);
+ }
+ env->DeleteLocalRef(jAttributes);
+
+ nAudioMix->mCriteria.add(nCriterion);
+ env->DeleteLocalRef(jCriterion);
+ }
+
+ env->DeleteLocalRef(jCriteria);
+
+ return (jint)AUDIO_JAVA_SUCCESS;
+}
+
+static jint
+android_media_AudioSystem_registerPolicyMixes(JNIEnv *env, jobject clazz,
+ jobject jMixesList, jboolean registration)
+{
+ ALOGV("registerPolicyMixes");
+
+ if (jMixesList == NULL) {
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+ if (!env->IsInstanceOf(jMixesList, gArrayListClass)) {
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+ jobjectArray jMixes = (jobjectArray)env->CallObjectMethod(jMixesList,
+ gArrayListMethods.toArray);
+ jint numMixes = env->GetArrayLength(jMixes);
+ if (numMixes > MAX_MIXES_PER_POLICY) {
+ numMixes = MAX_MIXES_PER_POLICY;
+ }
+
+ status_t status;
+ jint jStatus;
+ jobject jAudioMix = NULL;
+ Vector <AudioMix> mixes;
+ for (jint i = 0; i < numMixes; i++) {
+ jAudioMix = env->GetObjectArrayElement(jMixes, i);
+ if (!env->IsInstanceOf(jAudioMix, gAudioMixClass)) {
+ jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
+ goto exit;
+ }
+ AudioMix mix;
+ jStatus = convertAudioMixToNative(env, &mix, jAudioMix);
+ env->DeleteLocalRef(jAudioMix);
+ jAudioMix = NULL;
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
+ goto exit;
+ }
+ mixes.add(mix);
+ }
+
+ ALOGV("AudioSystem::registerPolicyMixes numMixes %d registration %d", numMixes, registration);
+ status = AudioSystem::registerPolicyMixes(mixes, registration);
+ ALOGV("AudioSystem::registerPolicyMixes() returned %d", status);
+
+ jStatus = nativeToJavaStatus(status);
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
+ goto exit;
+ }
+
+exit:
+ if (jAudioMix != NULL) {
+ env->DeleteLocalRef(jAudioMix);
+ }
+ return jStatus;
+}
+
+
+
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@@ -1363,6 +1523,9 @@ static JNINativeMethod gMethods[] = {
(void *)android_media_AudioSystem_setAudioPortConfig},
{"getAudioHwSyncForSession", "(I)I",
(void *)android_media_AudioSystem_getAudioHwSyncForSession},
+ {"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
+ (void *)android_media_AudioSystem_registerPolicyMixes},
+
};
@@ -1381,6 +1544,7 @@ int register_android_media_AudioSystem(JNIEnv *env)
jclass arrayListClass = env->FindClass("java/util/ArrayList");
gArrayListClass = (jclass) env->NewGlobalRef(arrayListClass);
gArrayListMethods.add = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
+ gArrayListMethods.toArray = env->GetMethodID(arrayListClass, "toArray", "()[Ljava/lang/Object;");
jclass audioHandleClass = env->FindClass("android/media/AudioHandle");
gAudioHandleClass = (jclass) env->NewGlobalRef(audioHandleClass);
@@ -1462,6 +1626,41 @@ int register_android_media_AudioSystem(JNIEnv *env)
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
+ jclass audioMixClass = env->FindClass("android/media/audiopolicy/AudioMix");
+ gAudioMixClass = (jclass) env->NewGlobalRef(audioMixClass);
+ gAudioMixFields.mRule = env->GetFieldID(audioMixClass, "mRule",
+ "Landroid/media/audiopolicy/AudioMixingRule;");
+ gAudioMixFields.mFormat = env->GetFieldID(audioMixClass, "mFormat",
+ "Landroid/media/AudioFormat;");
+ gAudioMixFields.mRouteFlags = env->GetFieldID(audioMixClass, "mRouteFlags", "I");
+ gAudioMixFields.mRegistrationId = env->GetFieldID(audioMixClass, "mRegistrationId",
+ "Ljava/lang/String;");
+ gAudioMixFields.mMixType = env->GetFieldID(audioMixClass, "mMixType", "I");
+
+ jclass audioFormatClass = env->FindClass("android/media/AudioFormat");
+ gAudioFormatClass = (jclass) env->NewGlobalRef(audioFormatClass);
+ gAudioFormatFields.mEncoding = env->GetFieldID(audioFormatClass, "mEncoding", "I");
+ gAudioFormatFields.mSampleRate = env->GetFieldID(audioFormatClass, "mSampleRate", "I");
+ gAudioFormatFields.mChannelMask = env->GetFieldID(audioFormatClass, "mChannelMask", "I");
+
+ jclass audioMixingRuleClass = env->FindClass("android/media/audiopolicy/AudioMixingRule");
+ gAudioMixingRuleClass = (jclass) env->NewGlobalRef(audioMixingRuleClass);
+ gAudioMixingRuleFields.mCriteria = env->GetFieldID(audioMixingRuleClass, "mCriteria",
+ "Ljava/util/ArrayList;");
+
+ jclass attributeMatchCriterionClass =
+ env->FindClass("android/media/audiopolicy/AudioMixingRule$AttributeMatchCriterion");
+ gAttributeMatchCriterionClass = (jclass) env->NewGlobalRef(attributeMatchCriterionClass);
+ gAttributeMatchCriterionFields.mAttr = env->GetFieldID(attributeMatchCriterionClass, "mAttr",
+ "Landroid/media/AudioAttributes;");
+ gAttributeMatchCriterionFields.mRule = env->GetFieldID(attributeMatchCriterionClass, "mRule",
+ "I");
+
+ jclass audioAttributesClass = env->FindClass("android/media/AudioAttributes");
+ gAudioAttributesClass = (jclass) env->NewGlobalRef(audioAttributesClass);
+ gAudioAttributesFields.mUsage = env->GetFieldID(audioAttributesClass, "mUsage", "I");
+ gAudioAttributesFields.mSource = env->GetFieldID(audioAttributesClass, "mSource", "I");
+
AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
int status = AndroidRuntime::registerNativeMethods(env,