Loading core/jni/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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", Loading core/jni/AndroidRuntime.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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), Loading core/jni/android_media_AudioAttributes.cpp 0 → 100644 +205 −0 Original line number Diff line number Diff line /* * 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)); } core/jni/android_media_AudioAttributes.h 0 → 100644 +70 −0 Original line number Diff line number Diff line /* * 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 core/jni/android_media_AudioRecord.cpp +7 −34 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include "android_media_DeviceCallback.h" #include "android_media_MediaMetricsJNI.h" #include "android_media_MicrophoneInfo.h" #include "android_media_AudioAttributes.h" // ---------------------------------------------------------------------------- Loading @@ -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 { Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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.", Loading Loading @@ -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; Loading Loading @@ -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 = Loading Loading
core/jni/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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", Loading
core/jni/AndroidRuntime.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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), Loading
core/jni/android_media_AudioAttributes.cpp 0 → 100644 +205 −0 Original line number Diff line number Diff line /* * 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)); }
core/jni/android_media_AudioAttributes.h 0 → 100644 +70 −0 Original line number Diff line number Diff line /* * 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
core/jni/android_media_AudioRecord.cpp +7 −34 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ #include "android_media_DeviceCallback.h" #include "android_media_MediaMetricsJNI.h" #include "android_media_MicrophoneInfo.h" #include "android_media_AudioAttributes.h" // ---------------------------------------------------------------------------- Loading @@ -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 { Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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.", Loading Loading @@ -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; Loading Loading @@ -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 = Loading