/* * 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 #include #include #include "core_jni_helpers.h" #include #include #include #include #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 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}; } 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, "", "()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)); }