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

Commit d5b51610 authored by Ari Hausman-Cohen's avatar Ari Hausman-Cohen Committed by Android (Google) Code Review
Browse files

Merge "Add Dynamic Source Effects"

parents c2cf7711 a555e741
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ package android.media.audiofx;
 * <p>Applications should not use the DefaultEffect class directly but one of its derived classes
 * to control specific types of defaults:
 * <ul>
 *   <li> {@link android.media.audiofx.SourceDefaultEffect}</li>
 *   <li> {@link android.media.audiofx.StreamDefaultEffect}</li>
 * </ul>
 * <p>Creating a DefaultEffect object will register the corresponding effect engine as a default
+118 −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.
 */

package android.media.audiofx;

import android.annotation.RequiresPermission;
import android.app.ActivityThread;
import android.util.Log;
import java.util.UUID;

/**
 * SourceDefaultEffect is a default effect that attaches automatically to all AudioRecord and
 * MediaRecorder instances of a given source type.
 * <p>see {@link android.media.audiofx.DefaultEffect} class for more details on default effects.
 * @hide
 */

public class SourceDefaultEffect extends DefaultEffect {
    static {
        System.loadLibrary("audioeffect_jni");
    }

    private final static String TAG = "SourceDefaultEffect-JAVA";

    /**
     * Class constructor.
     *
     * @param type type of effect engine to be default. This parameter is ignored if uuid is set,
     *             and can be set to {@link android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL}
     *             in that case.
     * @param uuid unique identifier of a particular effect implementation to be default. This
     *             parameter can be set to
     *             {@link android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL}, in which case only
     *             the type will be used to select the effect.
     * @param priority the priority level requested by the application for controlling the effect
     *             engine. As the same engine can be shared by several applications, this parameter
     *             indicates how much the requesting application needs control of effect parameters.
     *             The normal priority is 0, above normal is a positive number, below normal a
     *             negative number.
     * @param source a MediaRecorder.AudioSource.* constant from
     *             {@link android.media.MediaRecorder.AudioSource} indicating
     *             what sources the given effect should attach to by default. Note that similar
     *             sources may share defaults.
     *
     * @throws java.lang.IllegalArgumentException
     * @throws java.lang.UnsupportedOperationException
     * @throws java.lang.RuntimeException
     */
    @RequiresPermission(value = android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS,
                        conditional = true)  // Android Things uses an alternate permission.
    public SourceDefaultEffect(UUID type, UUID uuid, int priority, int source) {
        int[] id = new int[1];
        int initResult = native_setup(type.toString(),
                                      uuid.toString(),
                                      priority,
                                      source,
                                      ActivityThread.currentOpPackageName(),
                                      id);
        if (initResult != AudioEffect.SUCCESS) {
            Log.e(TAG, "Error code " + initResult + " when initializing SourceDefaultEffect");
            switch (initResult) {
                case AudioEffect.ERROR_BAD_VALUE:
                    throw (new IllegalArgumentException(
                            "Source, type uuid, or implementation uuid not supported."));
                case AudioEffect.ERROR_INVALID_OPERATION:
                    throw (new UnsupportedOperationException(
                            "Effect library not loaded"));
                default:
                    throw (new RuntimeException(
                            "Cannot initialize effect engine for type: " + type
                            + " Error: " + initResult));
            }
        }

        mId = id[0];
    }


    /**
     * Releases the native SourceDefaultEffect resources. It is a good practice to
     * release the default effect when done with use as control can be returned to
     * other applications or the native resources released.
     */
    public void release() {
        native_release(mId);
    }

    @Override
    protected void finalize() {
        release();
    }

    // ---------------------------------------------------------
    // Native methods called from the Java side
    // --------------------

    private native final int native_setup(String type,
                                          String uuid,
                                          int priority,
                                          int source,
                                          String opPackageName,
                                          int[] id);

    private native final void native_release(int id);
}
+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ cc_library_shared {

    srcs: [
        "android_media_AudioEffect.cpp",
        "android_media_SourceDefaultEffect.cpp",
        "android_media_StreamDefaultEffect.cpp",
        "android_media_Visualizer.cpp",
    ],
+6 −0
Original line number Diff line number Diff line
@@ -907,6 +907,7 @@ static const JNINativeMethod gMethods[] = {

// ----------------------------------------------------------------------------

extern int register_android_media_SourceDefaultEffect(JNIEnv *env);
extern int register_android_media_StreamDefaultEffect(JNIEnv *env);
extern int register_android_media_visualizer(JNIEnv *env);

@@ -932,6 +933,11 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved __unused)
        goto bail;
    }

    if (register_android_media_SourceDefaultEffect(env) < 0) {
        ALOGE("ERROR: SourceDefaultEffect native registration failed\n");
        goto bail;
    }

    if (register_android_media_StreamDefaultEffect(env) < 0) {
        ALOGE("ERROR: StreamDefaultEffect native registration failed\n");
        goto bail;
+142 −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 "SourceDefaultEffect-JNI"

#include <utils/Errors.h>
#include <utils/Log.h>
#include <jni.h>
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include "media/AudioEffect.h"

#include <nativehelper/ScopedUtfChars.h>

#include "android_media_AudioEffect.h"

using namespace android;

static const char* const kClassPathName = "android/media/audiofx/SourceDefaultEffect";

static jint android_media_SourceDefaultEffect_native_setup(JNIEnv *env,
                                                           jobject /*thiz*/,
                                                           jstring type,
                                                           jstring uuid,
                                                           jint priority,
                                                           jint source,
                                                           jstring opPackageName,
                                                           jintArray jId)
{
    ALOGV("android_media_SourceDefaultEffect_native_setup");
    status_t lStatus = NO_ERROR;
    jint* nId = NULL;
    const char *typeStr = NULL;
    const char *uuidStr = NULL;

    ScopedUtfChars opPackageNameStr(env, opPackageName);

    if (type != NULL) {
        typeStr = env->GetStringUTFChars(type, NULL);
        if (typeStr == NULL) {  // Out of memory
            lStatus = NO_MEMORY;
            jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
            goto setup_exit;
        }
    }

    if (uuid != NULL) {
        uuidStr = env->GetStringUTFChars(uuid, NULL);
        if (uuidStr == NULL) {  // Out of memory
            lStatus = NO_MEMORY;
            jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
            goto setup_exit;
        }
    }

    if (typeStr == NULL && uuidStr == NULL) {
        lStatus = BAD_VALUE;
        goto setup_exit;
    }

    nId = reinterpret_cast<jint *>(env->GetPrimitiveArrayCritical(jId, NULL));
    if (nId == NULL) {
        ALOGE("setup: Error retrieving id pointer");
        lStatus = BAD_VALUE;
        goto setup_exit;
    }

    // create the native SourceDefaultEffect.
    audio_unique_id_t id;
    lStatus = AudioEffect::addSourceDefaultEffect(typeStr,
                                                  String16(opPackageNameStr.c_str()),
                                                  uuidStr,
                                                  priority,
                                                  static_cast<audio_source_t>(source),
                                                  &id);
    if (lStatus != NO_ERROR) {
        ALOGE("setup: Error adding SourceDefaultEffect");
        goto setup_exit;
    }

    nId[0] = static_cast<jint>(id);

setup_exit:
    // Final cleanup and return.

    if (nId != NULL) {
        env->ReleasePrimitiveArrayCritical(jId, nId, 0);
        nId = NULL;
    }

    if (uuidStr != NULL) {
        env->ReleaseStringUTFChars(uuid, uuidStr);
        uuidStr = NULL;
    }

    if (typeStr != NULL) {
        env->ReleaseStringUTFChars(type, typeStr);
        typeStr = NULL;
    }

    return AudioEffectJni::translateNativeErrorToJava(lStatus);
}

static void android_media_SourceDefaultEffect_native_release(JNIEnv */*env*/,
                                                             jobject /*thiz*/,
                                                             jint id) {
    status_t lStatus = AudioEffect::removeSourceDefaultEffect(id);
    if (lStatus != NO_ERROR) {
        ALOGW("Error releasing SourceDefaultEffect: %d", lStatus);
    }
}

// ----------------------------------------------------------------------------

// Dalvik VM type signatures
static const JNINativeMethod gMethods[] = {
    {"native_setup",         "(Ljava/lang/String;Ljava/lang/String;IILjava/lang/String;[I)I",
                                         (void *)android_media_SourceDefaultEffect_native_setup},
    {"native_release",       "(I)V",      (void *)android_media_SourceDefaultEffect_native_release},
};


// ----------------------------------------------------------------------------

int register_android_media_SourceDefaultEffect(JNIEnv *env)
{
    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
}