summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2019-01-28 20:19:31 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2019-01-28 20:19:31 +0000
commitf8728771ae90ca64f2197b51ba56b004c7bac1b3 (patch)
tree2b36b3cb913f174b318ee0508337d0454bc07f5f
parente98248eb050b5cbb0c4017bee0c5ca36dad0b3fc (diff)
parentb4691282f2e6da3fbb2a0befc4de5a7f270142d8 (diff)
Merge "audio: add JNI AudioAttribute helper class"
-rw-r--r--core/jni/Android.bp1
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android_media_AudioAttributes.cpp205
-rw-r--r--core/jni/android_media_AudioAttributes.h70
-rw-r--r--core/jni/android_media_AudioRecord.cpp41
-rw-r--r--core/jni/android_media_AudioSystem.cpp65
-rw-r--r--core/jni/android_media_AudioTrack.cpp52
7 files changed, 306 insertions, 130 deletions
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 0466aaaee9fd..9afd5d0bff03 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -166,6 +166,7 @@ cc_library_shared {
"android_media_AudioRecord.cpp",
"android_media_AudioSystem.cpp",
"android_media_AudioTrack.cpp",
+ "android_media_AudioAttributes.cpp",
"android_media_DeviceCallback.cpp",
"android_media_JetPlayer.cpp",
"android_media_MediaMetricsJNI.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f458299468b1..c90071a0de44 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -107,6 +107,7 @@ extern int register_android_media_AudioEffectDescriptor(JNIEnv *env);
extern int register_android_media_AudioRecord(JNIEnv *env);
extern int register_android_media_AudioSystem(JNIEnv *env);
extern int register_android_media_AudioTrack(JNIEnv *env);
+extern int register_android_media_AudioAttributes(JNIEnv *env);
extern int register_android_media_MicrophoneInfo(JNIEnv *env);
extern int register_android_media_JetPlayer(JNIEnv *env);
extern int register_android_media_ToneGenerator(JNIEnv *env);
@@ -1470,6 +1471,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_media_AudioSystem),
REG_JNI(register_android_media_AudioRecord),
REG_JNI(register_android_media_AudioTrack),
+ REG_JNI(register_android_media_AudioAttributes),
REG_JNI(register_android_media_JetPlayer),
REG_JNI(register_android_media_MicrophoneInfo),
REG_JNI(register_android_media_RemoteDisplay),
diff --git a/core/jni/android_media_AudioAttributes.cpp b/core/jni/android_media_AudioAttributes.cpp
new file mode 100644
index 000000000000..bfe61626c1a2
--- /dev/null
+++ b/core/jni/android_media_AudioAttributes.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2018 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_NDEBUG 0
+
+#define LOG_TAG "AudioAttributes-JNI"
+
+#include <inttypes.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include "core_jni_helpers.h"
+
+#include <utils/Log.h>
+#include <vector>
+
+#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedUtfChars.h>
+
+#include "android_media_AudioAttributes.h"
+#include "android_media_AudioErrors.h"
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+static const char* const kClassPathName = "android/media/AudioAttributes";
+
+static jclass gAudioAttributesClass;
+static struct {
+ jfieldID mUsage; // AudioAttributes.mUsage
+ jfieldID mSource; // AudioAttributes.mSource
+ jfieldID mContentType; // AudioAttributes.mContentType
+ jfieldID mFlags; // AudioAttributes.mFlags
+ jfieldID mFormattedTags; // AudioAttributes.mFormattedTags
+} gAudioAttributesFields;
+
+static jclass gAudioAttributesBuilderClass;
+static jmethodID gAudioAttributesBuilderCstor;
+static struct {
+ jmethodID build;
+ jmethodID setUsage;
+ jmethodID setInternalCapturePreset;
+ jmethodID setContentType;
+ jmethodID setFlags;
+ jmethodID addTag;
+} gAudioAttributesBuilderMethods;
+
+
+static jint nativeAudioAttributesFromJavaAudioAttributes(
+ JNIEnv* env, jobject jAudioAttributes, audio_attributes_t *aa)
+{
+ if (env == nullptr) {
+ return AUDIO_JAVA_DEAD_OBJECT;
+ }
+ if (jAudioAttributes == nullptr) {
+ ALOGE("Invalid AudioAttributes java object");
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+ if (!env->IsInstanceOf(jAudioAttributes, gAudioAttributesClass)) {
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+ const jstring jtags =
+ (jstring) env->GetObjectField(jAudioAttributes, gAudioAttributesFields.mFormattedTags);
+ if (jtags == nullptr) {
+ return AUDIO_JAVA_NO_INIT;
+ }
+ const char* tags = env->GetStringUTFChars(jtags, NULL);
+ // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
+ strncpy(aa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
+ env->ReleaseStringUTFChars(jtags, tags);
+
+ // Record ?
+ aa->source = (audio_source_t) env->GetIntField(jAudioAttributes,
+ gAudioAttributesFields.mSource);
+ // Track ?
+ aa->usage = (audio_usage_t) env->GetIntField(jAudioAttributes, gAudioAttributesFields.mUsage);
+
+ aa->content_type =
+ (audio_content_type_t) env->GetIntField(jAudioAttributes,
+ gAudioAttributesFields.mContentType);
+
+ aa->flags = (audio_flags_mask_t)env->GetIntField(jAudioAttributes,
+ gAudioAttributesFields.mFlags);
+
+ ALOGV("AudioAttributes for usage=%d content=%d source=%d tags=%s flags=%08x tags=%s",
+ aa->usage, aa->content_type, aa->source, aa->tags, aa->flags, aa->tags);
+ return (jint)AUDIO_JAVA_SUCCESS;
+}
+
+static jint nativeAudioAttributesToJavaAudioAttributes(
+ JNIEnv* env, jobject *jAudioAttributes, const audio_attributes_t &attributes)
+{
+ ScopedLocalRef<jobject> jAttributeBuilder(env, env->NewObject(gAudioAttributesBuilderClass,
+ gAudioAttributesBuilderCstor));
+ if (jAttributeBuilder.get() == nullptr) {
+ return (jint)AUDIO_JAVA_ERROR;
+ }
+ env->CallObjectMethod(jAttributeBuilder.get(),
+ gAudioAttributesBuilderMethods.setUsage,
+ attributes.usage);
+ env->CallObjectMethod(jAttributeBuilder.get(),
+ gAudioAttributesBuilderMethods.setInternalCapturePreset,
+ attributes.source);
+ env->CallObjectMethod(jAttributeBuilder.get(),
+ gAudioAttributesBuilderMethods.setContentType,
+ attributes.content_type);
+ env->CallObjectMethod(jAttributeBuilder.get(),
+ gAudioAttributesBuilderMethods.setFlags,
+ attributes.flags);
+ env->CallObjectMethod(jAttributeBuilder.get(),
+ gAudioAttributesBuilderMethods.addTag,
+ env->NewStringUTF(attributes.tags));
+
+ *jAudioAttributes = env->CallObjectMethod(jAttributeBuilder.get(),
+ gAudioAttributesBuilderMethods.build);
+ return (jint)AUDIO_JAVA_SUCCESS;
+}
+
+// ----------------------------------------------------------------------------
+JNIAudioAttributeHelper::UniqueAaPtr JNIAudioAttributeHelper::makeUnique()
+{
+ audio_attributes_t *aa = new (calloc(1, sizeof(audio_attributes_t)))
+ audio_attributes_t{AUDIO_ATTRIBUTES_INITIALIZER};
+ return UniqueAaPtr{aa, free};
+}
+
+jint JNIAudioAttributeHelper::nativeFromJava(JNIEnv* env, jobject jAudioAttributes,
+ audio_attributes_t *paa)
+{
+ return nativeAudioAttributesFromJavaAudioAttributes(env, jAudioAttributes, paa);
+}
+
+jint JNIAudioAttributeHelper::nativeToJava(
+ JNIEnv* env, jobject *jAudioAttributes, const audio_attributes_t &attributes)
+{
+ return nativeAudioAttributesToJavaAudioAttributes(env, jAudioAttributes, attributes);
+}
+
+jint JNIAudioAttributeHelper::getJavaArray(
+ JNIEnv* env, jobjectArray *jAudioAttributeArray, jint numAudioAttributes)
+{
+ *jAudioAttributeArray = env->NewObjectArray(numAudioAttributes, gAudioAttributesClass, NULL);
+ return jAudioAttributeArray == NULL? (jint)AUDIO_JAVA_ERROR : (jint)AUDIO_JAVA_SUCCESS;
+}
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gMethods[] = {
+ // n/a
+};
+
+int register_android_media_AudioAttributes(JNIEnv *env)
+{
+ jclass audioAttributesClass = FindClassOrDie(env, kClassPathName);
+ gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
+ gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
+ gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
+ gAudioAttributesFields.mContentType =
+ GetFieldIDOrDie(env, audioAttributesClass, "mContentType", "I");
+ gAudioAttributesFields.mFlags = GetFieldIDOrDie(env, audioAttributesClass, "mFlags", "I");
+ gAudioAttributesFields.mFormattedTags =
+ GetFieldIDOrDie(env, audioAttributesClass, "mFormattedTags", "Ljava/lang/String;");
+
+ jclass audioAttributesBuilderClass = FindClassOrDie(
+ env, "android/media/AudioAttributes$Builder");
+ gAudioAttributesBuilderClass = MakeGlobalRefOrDie(env, audioAttributesBuilderClass);
+ gAudioAttributesBuilderCstor = GetMethodIDOrDie(
+ env, audioAttributesBuilderClass, "<init>", "()V");
+ gAudioAttributesBuilderMethods.build = GetMethodIDOrDie(
+ env, audioAttributesBuilderClass, "build", "()Landroid/media/AudioAttributes;");
+ gAudioAttributesBuilderMethods.setUsage = GetMethodIDOrDie(
+ env, audioAttributesBuilderClass, "setUsage",
+ "(I)Landroid/media/AudioAttributes$Builder;");
+ gAudioAttributesBuilderMethods.setInternalCapturePreset = GetMethodIDOrDie(
+ env, audioAttributesBuilderClass, "setInternalCapturePreset",
+ "(I)Landroid/media/AudioAttributes$Builder;");
+ gAudioAttributesBuilderMethods.setContentType = GetMethodIDOrDie(
+ env, audioAttributesBuilderClass, "setContentType",
+ "(I)Landroid/media/AudioAttributes$Builder;");
+ gAudioAttributesBuilderMethods.setFlags = GetMethodIDOrDie(
+ env, audioAttributesBuilderClass, "setFlags",
+ "(I)Landroid/media/AudioAttributes$Builder;");
+ gAudioAttributesBuilderMethods.addTag = GetMethodIDOrDie(
+ env, audioAttributesBuilderClass, "addTag",
+ "(Ljava/lang/String;)Landroid/media/AudioAttributes$Builder;");
+
+ env->DeleteLocalRef(audioAttributesClass);
+
+ return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
+}
diff --git a/core/jni/android_media_AudioAttributes.h b/core/jni/android_media_AudioAttributes.h
new file mode 100644
index 000000000000..c55835222086
--- /dev/null
+++ b/core/jni/android_media_AudioAttributes.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include "jni.h"
+
+#include <memory.h>
+
+#include <system/audio.h>
+
+namespace android {
+
+class JNIAudioAttributeHelper
+{
+public:
+ using UniqueAaPtr = std::unique_ptr<audio_attributes_t, decltype(free)*>;
+
+ /**
+ * @brief makeUnique helper to prevent leak
+ * @return a unique ptr of 0-initialized native audio attributes structure
+ */
+ static UniqueAaPtr makeUnique();
+
+ /**
+ * @brief nativeFromJava Gets the underlying AudioAttributes from an AudioAttributes Java
+ * object.
+ * @param env
+ * @param jAudioAttributes JAVA AudioAttribute object
+ * @param paa native AudioAttribute pointer
+ * @return AUDIO_JAVA_SUCCESS on success, error code otherwise
+ */
+ static jint nativeFromJava(
+ JNIEnv* env, jobject jAudioAttributes, audio_attributes_t *attributes);
+
+ /**
+ * @brief nativeToJava AudioAttributes Java object from a native AudioAttributes.
+ * @param env
+ * @param jAudioAttributes JAVA AudioAttribute object
+ * @param attributes native AudioAttribute
+ * @return AUDIO_JAVA_SUCCESS on success, error code otherwise
+ */
+ static jint nativeToJava(
+ JNIEnv* env, jobject *jAudioAttributes, const audio_attributes_t &attributes);
+
+ /**
+ * @brief getJavaArray: creates an array of JAVA AudioAttributes objects
+ * @param env
+ * @param jAudioAttributeArray
+ * @param numAudioAttributes
+ * @return Array of AudioAttributes objects
+ */
+ static jint getJavaArray(
+ JNIEnv* env, jobjectArray *jAudioAttributeArray, jint numAudioAttributes);
+};
+
+}; // namespace android
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 67c306413bb2..02dffdc2ca25 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -35,6 +35,7 @@
#include "android_media_DeviceCallback.h"
#include "android_media_MediaMetricsJNI.h"
#include "android_media_MicrophoneInfo.h"
+#include "android_media_AudioAttributes.h"
// ----------------------------------------------------------------------------
@@ -42,7 +43,6 @@ using namespace android;
// ----------------------------------------------------------------------------
static const char* const kClassPathName = "android/media/AudioRecord";
-static const char* const kAudioAttributesClassPathName = "android/media/AudioAttributes";
static jclass gArrayListClass;
static struct {
@@ -56,12 +56,6 @@ struct audio_record_fields_t {
jfieldID nativeCallbackCookie; // provides access to the AudioRecord callback data
jfieldID nativeDeviceCallback; // provides access to the JNIDeviceCallback instance
};
-struct audio_attributes_fields_t {
- jfieldID fieldRecSource; // AudioAttributes.mSource
- jfieldID fieldFlags; // AudioAttributes.mFlags
- jfieldID fieldFormattedTags;// AudioAttributes.mFormattedTags
-};
-static audio_attributes_fields_t javaAudioAttrFields;
static audio_record_fields_t javaAudioRecordFields;
static struct {
jfieldID fieldFramePosition; // AudioTimestamp.framePosition
@@ -213,7 +207,6 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
nSession = NULL;
- audio_attributes_t *paa = NULL;
sp<AudioRecord> lpRecorder = 0;
audiorecord_callback_cookie *lpCallbackData = NULL;
@@ -275,15 +268,11 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
lpRecorder = new AudioRecord(String16(opPackageNameStr.c_str()));
// read the AudioAttributes values
- paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
- const jstring jtags =
- (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
- const char* tags = env->GetStringUTFChars(jtags, NULL);
- // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
- strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
- env->ReleaseStringUTFChars(jtags, tags);
- paa->source = (audio_source_t) env->GetIntField(jaa, javaAudioAttrFields.fieldRecSource);
- paa->flags = (audio_flags_mask_t)env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
+ auto paa = JNIAudioAttributeHelper::makeUnique();
+ jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
+ if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+ return jStatus;
+ }
ALOGV("AudioRecord_setup for source=%d tags=%s flags=%08x", paa->source, paa->tags, paa->flags);
audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE;
@@ -311,7 +300,7 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
AudioRecord::TRANSFER_DEFAULT,
flags,
-1, -1, // default uid, pid
- paa);
+ paa.get());
if (status != NO_ERROR) {
ALOGE("Error creating AudioRecord instance: initialization check failed with status %d.",
@@ -368,19 +357,10 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
// of the Java object (in mNativeCallbackCookie) so we can free the memory in finalize()
env->SetLongField(thiz, javaAudioRecordFields.nativeCallbackCookie, (jlong)lpCallbackData);
- if (paa != NULL) {
- // audio attributes were copied in AudioRecord creation
- free(paa);
- paa = NULL;
- }
-
return (jint) AUDIO_JAVA_SUCCESS;
// failure:
native_init_failure:
- if (paa != NULL) {
- free(paa);
- }
env->DeleteGlobalRef(lpCallbackData->audioRecord_class);
env->DeleteGlobalRef(lpCallbackData->audioRecord_ref);
delete lpCallbackData;
@@ -972,13 +952,6 @@ int register_android_media_AudioRecord(JNIEnv *env)
javaAudioRecordFields.nativeDeviceCallback = GetFieldIDOrDie(env,
audioRecordClass, JAVA_NATIVEDEVICECALLBACK_FIELD_NAME, "J");
- // Get the AudioAttributes class and fields
- jclass audioAttrClass = FindClassOrDie(env, kAudioAttributesClassPathName);
- javaAudioAttrFields.fieldRecSource = GetFieldIDOrDie(env, audioAttrClass, "mSource", "I");
- javaAudioAttrFields.fieldFlags = GetFieldIDOrDie(env, audioAttrClass, "mFlags", "I");
- javaAudioAttrFields.fieldFormattedTags = GetFieldIDOrDie(env,
- audioAttrClass, "mFormattedTags", "Ljava/lang/String;");
-
// Get the RecordTimestamp class and fields
jclass audioTimestampClass = FindClassOrDie(env, "android/media/AudioTimestamp");
javaAudioTimestampFields.fieldFramePosition =
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 0d8ede794b73..34abcd889644 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -36,6 +36,7 @@
#include "android_media_AudioFormat.h"
#include "android_media_AudioErrors.h"
#include "android_media_MicrophoneInfo.h"
+#include "android_media_AudioAttributes.h"
// ----------------------------------------------------------------------------
@@ -153,15 +154,6 @@ static struct {
jfieldID mRule;
} gAudioMixMatchCriterionFields;
-static jclass gAudioAttributesClass;
-static struct {
- jfieldID mUsage;
- jfieldID mSource;
- jfieldID mContentType;
- jfieldID mFlags;
- jfieldID mFormattedTags;
-} gAudioAttributesFields;
-
static const char* const kEventHandlerClassPathName =
"android/media/AudioPortEventHandler";
static struct {
@@ -705,27 +697,6 @@ static void convertAudioGainConfigToNative(JNIEnv *env,
env->DeleteLocalRef(jValues);
}
-static jint convertAudioAttributesToNative(JNIEnv *env,
- audio_attributes_t *nAudioAttributes,
- const jobject jAudioAttributes)
-{
- nAudioAttributes->usage = (audio_usage_t)env->GetIntField(jAudioAttributes,
- gAudioAttributesFields.mUsage);
- nAudioAttributes->source = (audio_source_t)env->GetIntField(jAudioAttributes,
- gAudioAttributesFields.mSource);
- nAudioAttributes->content_type = (audio_content_type_t)env->GetIntField(jAudioAttributes,
- gAudioAttributesFields.mContentType);
- nAudioAttributes->flags = env->GetIntField(jAudioAttributes,
- gAudioAttributesFields.mFlags);
- const jstring jtags = (jstring)env->GetObjectField(jAudioAttributes,
- gAudioAttributesFields.mFormattedTags);
- const char *tags = env->GetStringUTFChars(jtags, NULL);
- strncpy(nAudioAttributes->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
- env->ReleaseStringUTFChars(jtags, tags);
- return (jint)AUDIO_JAVA_SUCCESS;
-}
-
-
static jint convertAudioPortConfigToNative(JNIEnv *env,
struct audio_port_config *nAudioPortConfig,
const jobject jAudioPortConfig,
@@ -1705,22 +1676,19 @@ android_media_AudioSystem_startAudioSource(JNIEnv *env, jobject clazz,
if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
return AUDIO_JAVA_BAD_VALUE;
}
- if (!env->IsInstanceOf(jAudioAttributes, gAudioAttributesClass)) {
- return AUDIO_JAVA_BAD_VALUE;
- }
struct audio_port_config nAudioPortConfig = {};
jint jStatus = convertAudioPortConfigToNativeWithDevicePort(env,
&nAudioPortConfig, jAudioPortConfig, false);
if (jStatus != AUDIO_JAVA_SUCCESS) {
return jStatus;
}
- audio_attributes_t nAudioAttributes = {};
- jStatus = convertAudioAttributesToNative(env, &nAudioAttributes, jAudioAttributes);
- if (jStatus != AUDIO_JAVA_SUCCESS) {
+ auto paa = JNIAudioAttributeHelper::makeUnique();
+ jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jAudioAttributes, paa.get());
+ if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
return jStatus;
}
audio_port_handle_t handle;
- status_t status = AudioSystem::startAudioSource(&nAudioPortConfig, &nAudioAttributes, &handle);
+ status_t status = AudioSystem::startAudioSource(&nAudioPortConfig, paa.get(), &handle);
ALOGV("AudioSystem::startAudioSource() returned %d handle %d", status, handle);
return handle > 0 ? handle : nativeToJavaStatus(status);
}
@@ -1833,12 +1801,16 @@ static jint convertAudioMixToNative(JNIEnv *env,
case RULE_MATCH_ATTRIBUTE_USAGE:
case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: {
jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr);
+
+ auto paa = JNIAudioAttributeHelper::makeUnique();
+ jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jAttributes, paa.get());
+ if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+ return jStatus;
+ }
if (match_rule == RULE_MATCH_ATTRIBUTE_USAGE) {
- nCriterion.mValue.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
- gAudioAttributesFields.mUsage);
+ nCriterion.mValue.mUsage = paa->usage;
} else {
- nCriterion.mValue.mSource = (audio_source_t)env->GetIntField(jAttributes,
- gAudioAttributesFields.mSource);
+ nCriterion.mValue.mSource = paa->source;
}
env->DeleteLocalRef(jAttributes);
}
@@ -2395,17 +2367,6 @@ int register_android_media_AudioSystem(JNIEnv *env)
"I");
gAudioMixMatchCriterionFields.mRule = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mRule",
"I");
-
- jclass audioAttributesClass = FindClassOrDie(env, "android/media/AudioAttributes");
- gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
- gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
- gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
- gAudioAttributesFields.mContentType = GetFieldIDOrDie(env,
- audioAttributesClass, "mContentType", "I");
- gAudioAttributesFields.mFlags = GetFieldIDOrDie(env, audioAttributesClass, "mFlags", "I");
- gAudioAttributesFields.mFormattedTags = GetFieldIDOrDie(env,
- audioAttributesClass, "mFormattedTags", "Ljava/lang/String;");
-
// AudioTrackRoutingProxy methods
gClsAudioTrackRoutingProxy =
android::FindClassOrDie(env, "android/media/AudioTrackRoutingProxy");
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index a0d99ec95b55..f9f28dabc694 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -37,6 +37,7 @@
#include "android_media_PlaybackParams.h"
#include "android_media_DeviceCallback.h"
#include "android_media_VolumeShaper.h"
+#include "android_media_AudioAttributes.h"
#include <cinttypes>
@@ -48,7 +49,6 @@ using ::android::media::VolumeShaper;
// ----------------------------------------------------------------------------
static const char* const kClassPathName = "android/media/AudioTrack";
-static const char* const kAudioAttributesClassPathName = "android/media/AudioAttributes";
struct audio_track_fields_t {
// these fields provide access from C++ to the...
@@ -57,14 +57,7 @@ struct audio_track_fields_t {
jfieldID jniData; // stores in Java additional resources used by the native AudioTrack
jfieldID fieldStreamType; // ... mStreamType field in the AudioTrack Java object
};
-struct audio_attributes_fields_t {
- jfieldID fieldUsage; // AudioAttributes.mUsage
- jfieldID fieldContentType; // AudioAttributes.mContentType
- jfieldID fieldFlags; // AudioAttributes.mFlags
- jfieldID fieldFormattedTags;// AudioAttributes.mFormattedTags
-};
static audio_track_fields_t javaAudioTrackFields;
-static audio_attributes_fields_t javaAudioAttrFields;
static PlaybackParams::fields_t gPlaybackParamsFields;
static VolumeShaperHelper::fields_t gVolumeShaperFields;
@@ -249,8 +242,6 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job
AudioTrackJniStorage* lpJniStorage = NULL;
- audio_attributes_t *paa = NULL;
-
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
ALOGE("Can't find %s when setting up callback.", kClassPathName);
@@ -304,18 +295,11 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job
lpTrack = new AudioTrack();
// read the AudioAttributes values
- paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
- const jstring jtags =
- (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
- const char* tags = env->GetStringUTFChars(jtags, NULL);
- // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
- strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
- env->ReleaseStringUTFChars(jtags, tags);
- paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage);
- paa->content_type =
- (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType);
- paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
-
+ auto paa = JNIAudioAttributeHelper::makeUnique();
+ jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
+ if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+ return jStatus;
+ }
ALOGV("AudioTrack_setup for usage=%d content=%d flags=0x%#x tags=%s",
paa->usage, paa->content_type, paa->flags, paa->tags);
@@ -357,7 +341,7 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job
offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK : AudioTrack::TRANSFER_SYNC,
offload ? &offloadInfo : NULL,
-1, -1, // default uid, pid values
- paa);
+ paa.get());
break;
@@ -384,7 +368,7 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job
AudioTrack::TRANSFER_SHARED,
NULL, // default offloadInfo
-1, -1, // default uid, pid values
- paa);
+ paa.get());
break;
default:
@@ -452,20 +436,11 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job
// since we had audio attributes, the stream type was derived from them during the
// creation of the native AudioTrack: push the same value to the Java object
env->SetIntField(thiz, javaAudioTrackFields.fieldStreamType, (jint) lpTrack->streamType());
- if (paa != NULL) {
- // audio attributes were copied in AudioTrack creation
- free(paa);
- paa = NULL;
- }
-
return (jint) AUDIO_JAVA_SUCCESS;
// failures:
native_init_failure:
- if (paa != NULL) {
- free(paa);
- }
if (nSession != NULL) {
env->ReleasePrimitiveArrayCritical(jSession, nSession, 0);
}
@@ -1470,17 +1445,6 @@ int register_android_media_AudioTrack(JNIEnv *env)
env->DeleteLocalRef(audioTrackClass);
- // Get the AudioAttributes class and fields
- jclass audioAttrClass = FindClassOrDie(env, kAudioAttributesClassPathName);
- javaAudioAttrFields.fieldUsage = GetFieldIDOrDie(env, audioAttrClass, "mUsage", "I");
- javaAudioAttrFields.fieldContentType = GetFieldIDOrDie(env,
- audioAttrClass, "mContentType", "I");
- javaAudioAttrFields.fieldFlags = GetFieldIDOrDie(env, audioAttrClass, "mFlags", "I");
- javaAudioAttrFields.fieldFormattedTags = GetFieldIDOrDie(env,
- audioAttrClass, "mFormattedTags", "Ljava/lang/String;");
-
- env->DeleteLocalRef(audioAttrClass);
-
// initialize PlaybackParams field info
gPlaybackParamsFields.init(env);