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

Commit 589f6a29 authored by jiabin's avatar jiabin
Browse files

Support query active microphones in MediaRecorder.

This is part of device enumeration. With the new add API, developer
could get the active microphones information for each channel.

Bug: 64038649
Test: Run cts and check the print log.
Change-Id: I6de3339add858cb1f6b7f948995bd013570d4260
parent 23675f6c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -24098,6 +24098,7 @@ package android.media {
    ctor public MediaRecorder();
    method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
    method protected void finalize();
    method public java.util.List<android.media.MicrophoneInfo> getActiveMicrophones() throws java.io.IOException;
    method public static final int getAudioSourceMax();
    method public int getMaxAmplitude() throws java.lang.IllegalStateException;
    method public android.os.PersistableBundle getMetrics();
+28 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.view.Surface;
@@ -34,6 +35,8 @@ import java.io.FileDescriptor;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

import com.android.internal.annotations.GuardedBy;

@@ -1406,6 +1409,31 @@ public class MediaRecorder implements AudioRouting
    private native final int native_getRoutedDeviceId();
    private native final void native_enableDeviceCallback(boolean enabled);

    //--------------------------------------------------------------------------
    // Microphone information
    //--------------------
    /**
     * Return A lists of {@link MicrophoneInfo} representing the active microphones.
     * By querying channel mapping for each active microphone, developer can know how
     * the microphone is used by each channels or a capture stream.
     *
     * @return a lists of {@link MicrophoneInfo} representing the active microphones
     * @throws IOException if an error occurs
     */
    public List<MicrophoneInfo> getActiveMicrophones() throws IOException {
        ArrayList<MicrophoneInfo> activeMicrophones = new ArrayList<>();
        int status = native_getActiveMicrophones(activeMicrophones);
        if (status != AudioManager.SUCCESS) {
            Log.e(TAG, "getActiveMicrophones failed:" + status);
            return new ArrayList<MicrophoneInfo>();
        }
        AudioManager.setPortIdForMicrophones(activeMicrophones);
        return activeMicrophones;
    }

    private native final int native_getActiveMicrophones(
            ArrayList<MicrophoneInfo> activeMicrophones);

    /**
     * Called from native code when an interesting event happens.  This method
     * just uses the EventHandler system to post the event back to the main app thread.
+59 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <limits.h>
#include <stdio.h>
#include <unistd.h>
#include <vector>

//#define LOG_NDEBUG 0
#define LOG_TAG "MediaRecorderJNI"
@@ -29,6 +30,7 @@
#include <camera/Camera.h>
#include <media/mediarecorder.h>
#include <media/MediaAnalyticsItem.h>
#include <media/MicrophoneInfo.h>
#include <media/stagefright/PersistentSurface.h>
#include <utils/threads.h>

@@ -36,7 +38,9 @@

#include "jni.h"
#include <nativehelper/JNIHelp.h>
#include "android_media_AudioErrors.h"
#include "android_media_MediaMetricsJNI.h"
#include "android_media_MicrophoneInfo.h"
#include "android_runtime/AndroidRuntime.h"

#include <system/audio.h>
@@ -61,6 +65,12 @@ struct fields_t {
};
static fields_t fields;

struct ArrayListFields {
    jmethodID add;
    jclass classId;
};
static ArrayListFields gArrayListFields;

static Mutex sLock;

// ----------------------------------------------------------------------------
@@ -565,6 +575,13 @@ android_media_MediaRecorder_native_init(JNIEnv *env)
    if (fields.post_event == NULL) {
        return;
    }

    clazz = env->FindClass("java/util/ArrayList");
    if (clazz == NULL) {
        return;
    }
    gArrayListFields.add = env->GetMethodID(clazz, "add", "(Ljava/lang/Object;)Z");
    gArrayListFields.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
}


@@ -707,6 +724,45 @@ android_media_MediaRecorder_enableDeviceCallback(JNIEnv *env, jobject thiz, jboo
    process_media_recorder_call(env, mr->enableAudioDeviceCallback(enabled),
            "java/lang/RuntimeException", "enableDeviceCallback failed.");
}

static jint
android_media_MediaRecord_getActiveMicrophones(JNIEnv *env,
        jobject thiz, jobject jActiveMicrophones) {
    if (jActiveMicrophones == NULL) {
        ALOGE("jActiveMicrophones is null");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }
    if (!env->IsInstanceOf(jActiveMicrophones, gArrayListFields.classId)) {
        ALOGE("getActiveMicrophones not an arraylist");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }

    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
    if (mr == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return (jint)AUDIO_JAVA_NO_INIT;
    }

    jint jStatus = AUDIO_JAVA_SUCCESS;
    std::vector<media::MicrophoneInfo> activeMicrophones;
    status_t status = mr->getActiveMicrophones(&activeMicrophones);
    if (status != NO_ERROR) {
        ALOGE_IF(status != NO_ERROR, "MediaRecorder::getActiveMicrophones error %d", status);
        jStatus = nativeToJavaStatus(status);
        return jStatus;
    }

    for (size_t i = 0; i < activeMicrophones.size(); i++) {
        jobject jMicrophoneInfo;
        jStatus = convertMicrophoneInfoFromNative(env, &jMicrophoneInfo, &activeMicrophones[i]);
        if (jStatus != AUDIO_JAVA_SUCCESS) {
            return jStatus;
        }
        env->CallBooleanMethod(jActiveMicrophones, gArrayListFields.add, jMicrophoneInfo);
        env->DeleteLocalRef(jMicrophoneInfo);
    }
    return jStatus;
}
// ----------------------------------------------------------------------------

static const JNINativeMethod gMethods[] = {
@@ -743,6 +799,8 @@ static const JNINativeMethod gMethods[] = {
    {"native_setInputDevice", "(I)Z",                           (void *)android_media_MediaRecorder_setInputDevice},
    {"native_getRoutedDeviceId", "()I",                         (void *)android_media_MediaRecorder_getRoutedDeviceId},
    {"native_enableDeviceCallback", "(Z)V",                     (void *)android_media_MediaRecorder_enableDeviceCallback},

    {"native_getActiveMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_MediaRecord_getActiveMicrophones},
};

// This function only registers the native methods, and is called from