Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c31847e authored by Eric Laurent's avatar Eric Laurent
Browse files

AudioSystem JNI: refactor audio effect descriptor conversion

Factorize native to JAVA audio effect descriptor conversion and
place in separate library so that it can be reused by components outside
of AudioEffect class.

Bug: 111438757
Test: make and run CTS tests for AudioEffects
Change-Id: I11eb13cfc08abb8d94ce30ab0d702df04943e1be
parent 1982ca78
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@ cc_library_shared {
        "android/graphics/pdf/PdfUtils.cpp",
        "android/graphics/text/LineBreaker.cpp",
        "android/graphics/text/MeasuredText.cpp",
        "android_media_AudioEffectDescriptor.cpp",
        "android_media_AudioRecord.cpp",
        "android_media_AudioSystem.cpp",
        "android_media_AudioTrack.cpp",
+2 −0
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ extern int register_android_hardware_UsbDeviceConnection(JNIEnv *env);
extern int register_android_hardware_UsbRequest(JNIEnv *env);
extern int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv* env);

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);
@@ -1456,6 +1457,7 @@ static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_android_hardware_UsbDeviceConnection),
    REG_JNI(register_android_hardware_UsbRequest),
    REG_JNI(register_android_hardware_location_ActivityRecognitionHardware),
    REG_JNI(register_android_media_AudioEffectDescriptor),
    REG_JNI(register_android_media_AudioSystem),
    REG_JNI(register_android_media_AudioRecord),
    REG_JNI(register_android_media_AudioTrack),
+123 −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.
 */

#include "core_jni_helpers.h"
#include "android_media_AudioErrors.h"
#include "media/AudioEffect.h"

using namespace android;

static jclass gAudioEffectDescriptorClass;
static jmethodID gAudioEffectDescriptorCstor;

namespace android {

jclass audioEffectDescriptorClass() {
    return gAudioEffectDescriptorClass;
}

jint convertAudioEffectDescriptorFromNative(JNIEnv* env, jobject* jDescriptor,
        const effect_descriptor_t* nDescriptor)
{
    jstring jType;
    jstring jUuid;
    jstring jConnect;
    jstring jName;
    jstring jImplementor;
    char str[EFFECT_STRING_LEN_MAX];

    if ((nDescriptor->flags & EFFECT_FLAG_TYPE_MASK)
        == EFFECT_FLAG_TYPE_AUXILIARY) {
        jConnect = env->NewStringUTF("Auxiliary");
    } else if ((nDescriptor->flags & EFFECT_FLAG_TYPE_MASK)
        == EFFECT_FLAG_TYPE_INSERT) {
        jConnect = env->NewStringUTF("Insert");
    } else if ((nDescriptor->flags & EFFECT_FLAG_TYPE_MASK)
        == EFFECT_FLAG_TYPE_PRE_PROC) {
        jConnect = env->NewStringUTF("Pre Processing");
    } else {
        return (jint) AUDIO_JAVA_BAD_VALUE;
    }

    AudioEffect::guidToString(&nDescriptor->type, str, EFFECT_STRING_LEN_MAX);
    jType = env->NewStringUTF(str);

    AudioEffect::guidToString(&nDescriptor->uuid, str, EFFECT_STRING_LEN_MAX);
    jUuid = env->NewStringUTF(str);

    jName = env->NewStringUTF(nDescriptor->name);
    jImplementor = env->NewStringUTF(nDescriptor->implementor);

    *jDescriptor = env->NewObject(gAudioEffectDescriptorClass,
                                  gAudioEffectDescriptorCstor,
                                  jType,
                                  jUuid,
                                  jConnect,
                                  jName,
                                  jImplementor);
    env->DeleteLocalRef(jType);
    env->DeleteLocalRef(jUuid);
    env->DeleteLocalRef(jConnect);
    env->DeleteLocalRef(jName);
    env->DeleteLocalRef(jImplementor);

    return (jint) AUDIO_JAVA_SUCCESS;
}

void convertAudioEffectDescriptorVectorFromNative(JNIEnv *env, jobjectArray *jDescriptors,
        const std::vector<effect_descriptor_t>& nDescriptors)
{
    jobjectArray temp = env->NewObjectArray(nDescriptors.size(),
                                            audioEffectDescriptorClass(), NULL);
    size_t actualSize = 0;
    for (size_t i = 0; i < nDescriptors.size(); i++) {
        jobject jdesc;
        if (convertAudioEffectDescriptorFromNative(env,
                                                   &jdesc,
                                                   &nDescriptors[i])
            != AUDIO_JAVA_SUCCESS) {
            continue;
        }

        env->SetObjectArrayElement(temp, actualSize++, jdesc);
        env->DeleteLocalRef(jdesc);
    }

    *jDescriptors = env->NewObjectArray(actualSize, audioEffectDescriptorClass(), NULL);
    for (size_t i = 0; i < actualSize; i++) {
        env->SetObjectArrayElement(*jDescriptors,
                                   i,
                                   env->GetObjectArrayElement(temp, i));
    }
    env->DeleteLocalRef(temp);
}

}; // namespace android

int register_android_media_AudioEffectDescriptor(JNIEnv* env) {
    jclass audioEffectDescriptorClass =
        FindClassOrDie(env, "android/media/audiofx/AudioEffect$Descriptor");
    gAudioEffectDescriptorClass =
        MakeGlobalRefOrDie(env, audioEffectDescriptorClass);
    gAudioEffectDescriptorCstor =
        GetMethodIDOrDie(env,
                         audioEffectDescriptorClass,
                         "<init>",
                         "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");

    env->DeleteLocalRef(audioEffectDescriptorClass);
    return 0;
}
+38 −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.
 */

#ifndef ANDROID_MEDIA_AUDIOEFFECT_DESCRIPTOR_H
#define ANDROID_MEDIA_AUDIOEFFECT_DESCRIPTOR_H

#include <system/audio.h>
#include <system/audio_effect.h>

#include "jni.h"

namespace android {

// Conversion from C effect_descriptor_t to Java AudioEffect.Descriptor object

extern jclass audioEffectDescriptorClass();

extern jint convertAudioEffectDescriptorFromNative(JNIEnv *env, jobject *jDescriptor,
        const effect_descriptor_t *nDescriptor);

extern void convertAudioEffectDescriptorVectorFromNative(JNIEnv *env, jobjectArray *jDescriptors,
        const std::vector<effect_descriptor_t>& nDescriptors);
} // namespace android

#endif
 No newline at end of file
+16 −146
Original line number Diff line number Diff line
@@ -14,7 +14,6 @@
 * limitations under the License.
 */

#include "android_media_AudioEffect.h"

#include <stdio.h>

@@ -29,6 +28,10 @@

#include <nativehelper/ScopedUtfChars.h>

#include "android_media_AudioEffect.h"
#include "android_media_AudioEffectDescriptor.h"
#include "android_media_AudioErrors.h"

using namespace android;

#define AUDIOEFFECT_SUCCESS                      0
@@ -49,8 +52,6 @@ struct fields_t {
    jmethodID midPostNativeEvent;   // event post callback method
    jfieldID  fidNativeAudioEffect; // stores in Java the native AudioEffect object
    jfieldID  fidJniData;           // stores in Java additional resources used by the native AudioEffect
    jclass    clazzDesc;            // AudioEffect.Descriptor class
    jmethodID midDescCstor;         // AudioEffect.Descriptor class constructor
};
static fields_t fields;

@@ -226,7 +227,6 @@ android_media_AudioEffect_native_init(JNIEnv *env)
    ALOGV("android_media_AudioEffect_native_init");

    fields.clazzEffect = NULL;
    fields.clazzDesc = NULL;

    // Get the AudioEffect class
    jclass clazz = env->FindClass(kClassPathName);
@@ -263,23 +263,6 @@ android_media_AudioEffect_native_init(JNIEnv *env)
        ALOGE("Can't find AudioEffect.%s", "mJniData");
        return;
    }

    clazz = env->FindClass("android/media/audiofx/AudioEffect$Descriptor");
    if (clazz == NULL) {
        ALOGE("Can't find android/media/audiofx/AudioEffect$Descriptor class");
        return;
    }
    fields.clazzDesc = (jclass)env->NewGlobalRef(clazz);

    fields.midDescCstor
            = env->GetMethodID(
                    fields.clazzDesc,
                    "<init>",
                    "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
    if (fields.midDescCstor == NULL) {
        ALOGE("Can't find android/media/audiofx/AudioEffect$Descriptor class constructor");
        return;
    }
}


@@ -297,12 +280,6 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t
    const char *uuidStr = NULL;
    effect_descriptor_t desc;
    jobject jdesc;
    char str[EFFECT_STRING_LEN_MAX];
    jstring jdescType;
    jstring jdescUuid;
    jstring jdescConnect;
    jstring jdescName;
    jstring jdescImplementor;

    ScopedUtfChars opPackageNameStr(env, opPackageName);

@@ -394,41 +371,12 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t
    // get the effect descriptor
    desc = lpAudioEffect->descriptor();

    AudioEffect::guidToString(&desc.type, str, EFFECT_STRING_LEN_MAX);
    jdescType = env->NewStringUTF(str);

    AudioEffect::guidToString(&desc.uuid, str, EFFECT_STRING_LEN_MAX);
    jdescUuid = env->NewStringUTF(str);

    if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
        jdescConnect = env->NewStringUTF("Auxiliary");
    } else if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC) {
        jdescConnect = env->NewStringUTF("Pre Processing");
    } else {
        jdescConnect = env->NewStringUTF("Insert");
    }

    jdescName = env->NewStringUTF(desc.name);
    jdescImplementor = env->NewStringUTF(desc.implementor);

    jdesc = env->NewObject(fields.clazzDesc,
                           fields.midDescCstor,
                           jdescType,
                           jdescUuid,
                           jdescConnect,
                           jdescName,
                           jdescImplementor);
    env->DeleteLocalRef(jdescType);
    env->DeleteLocalRef(jdescUuid);
    env->DeleteLocalRef(jdescConnect);
    env->DeleteLocalRef(jdescName);
    env->DeleteLocalRef(jdescImplementor);
    if (jdesc == NULL) {
        ALOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)");
    if (convertAudioEffectDescriptorFromNative(env, &jdesc, &desc) != AUDIO_JAVA_SUCCESS) {
        goto setup_failure;
    }

    env->SetObjectArrayElement(javadesc, 0, jdesc);
    env->DeleteLocalRef(jdesc);

    setAudioEffect(env, thiz, lpAudioEffect);

@@ -729,23 +677,16 @@ static jobjectArray
android_media_AudioEffect_native_queryEffects(JNIEnv *env, jclass clazz __unused)
{
    effect_descriptor_t desc;
    char str[EFFECT_STRING_LEN_MAX];
    uint32_t totalEffectsCount = 0;
    uint32_t returnedEffectsCount = 0;
    uint32_t i = 0;
    jstring jdescType;
    jstring jdescUuid;
    jstring jdescConnect;
    jstring jdescName;
    jstring jdescImplementor;
    jobject jdesc;
    jobjectArray ret;

    if (AudioEffect::queryNumberEffects(&totalEffectsCount) != NO_ERROR) {
        return NULL;
    }

    jobjectArray temp = env->NewObjectArray(totalEffectsCount, fields.clazzDesc, NULL);
    jobjectArray temp = env->NewObjectArray(totalEffectsCount, audioEffectDescriptorClass(), NULL);
    if (temp == NULL) {
        return temp;
    }
@@ -757,49 +698,18 @@ android_media_AudioEffect_native_queryEffects(JNIEnv *env, jclass clazz __unused
            goto queryEffects_failure;
        }

        if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
            jdescConnect = env->NewStringUTF("Auxiliary");
        } else if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT) {
            jdescConnect = env->NewStringUTF("Insert");
        } else if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC) {
            jdescConnect = env->NewStringUTF("Pre Processing");
        } else {
        jobject jdesc;
        if (convertAudioEffectDescriptorFromNative(env, &jdesc, &desc) != AUDIO_JAVA_SUCCESS) {
            continue;
        }

        AudioEffect::guidToString(&desc.type, str, EFFECT_STRING_LEN_MAX);
        jdescType = env->NewStringUTF(str);

        AudioEffect::guidToString(&desc.uuid, str, EFFECT_STRING_LEN_MAX);
        jdescUuid = env->NewStringUTF(str);

        jdescName = env->NewStringUTF(desc.name);
        jdescImplementor = env->NewStringUTF(desc.implementor);

        jdesc = env->NewObject(fields.clazzDesc,
                               fields.midDescCstor,
                               jdescType,
                               jdescUuid,
                               jdescConnect,
                               jdescName,
                               jdescImplementor);
        env->DeleteLocalRef(jdescType);
        env->DeleteLocalRef(jdescUuid);
        env->DeleteLocalRef(jdescConnect);
        env->DeleteLocalRef(jdescName);
        env->DeleteLocalRef(jdescImplementor);
        if (jdesc == NULL) {
            ALOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)");
            goto queryEffects_failure;
        }

        env->SetObjectArrayElement(temp, returnedEffectsCount++, jdesc);
        env->DeleteLocalRef(jdesc);
    }

    if (returnedEffectsCount == 0) {
        goto queryEffects_failure;
    }
    ret = env->NewObjectArray(returnedEffectsCount, fields.clazzDesc, NULL);
    ret = env->NewObjectArray(returnedEffectsCount, audioEffectDescriptorClass(), NULL);
    if (ret == NULL) {
        goto queryEffects_failure;
    }
@@ -835,50 +745,10 @@ android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz _
    }
    ALOGV("queryDefaultPreProcessing() got %d effects", numEffects);

    jobjectArray ret = env->NewObjectArray(numEffects, fields.clazzDesc, NULL);
    if (ret == NULL) {
        return ret;
    }

    char str[EFFECT_STRING_LEN_MAX];
    jstring jdescType;
    jstring jdescUuid;
    jstring jdescConnect;
    jstring jdescName;
    jstring jdescImplementor;
    jobject jdesc;

    for (uint32_t i = 0; i < numEffects; i++) {

        AudioEffect::guidToString(&descriptors[i].type, str, EFFECT_STRING_LEN_MAX);
        jdescType = env->NewStringUTF(str);
        AudioEffect::guidToString(&descriptors[i].uuid, str, EFFECT_STRING_LEN_MAX);
        jdescUuid = env->NewStringUTF(str);
        jdescConnect = env->NewStringUTF("Pre Processing");
        jdescName = env->NewStringUTF(descriptors[i].name);
        jdescImplementor = env->NewStringUTF(descriptors[i].implementor);

        jdesc = env->NewObject(fields.clazzDesc,
                               fields.midDescCstor,
                               jdescType,
                               jdescUuid,
                               jdescConnect,
                               jdescName,
                               jdescImplementor);
        env->DeleteLocalRef(jdescType);
        env->DeleteLocalRef(jdescUuid);
        env->DeleteLocalRef(jdescConnect);
        env->DeleteLocalRef(jdescName);
        env->DeleteLocalRef(jdescImplementor);
        if (jdesc == NULL) {
            ALOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)");
            env->DeleteLocalRef(ret);
            return NULL;
        }

        env->SetObjectArrayElement(ret, i, jdesc);
   }
    std::vector<effect_descriptor_t> descVector(descriptors.get(), descriptors.get() + numEffects);

    jobjectArray ret;
    convertAudioEffectDescriptorVectorFromNative(env, &ret, descVector);
    return ret;
}