diff options
| author | 2018-01-23 12:22:47 -0800 | |
|---|---|---|
| committer | 2018-01-26 17:53:43 -0800 | |
| commit | 589f6a299ed464cf70a953992b5013d8b275099c (patch) | |
| tree | c1d3435b052ac1c5532a5eda736e40c85512dc91 | |
| parent | 23675f6c79d0c76caa837402a1e5e49ca11e2a02 (diff) | |
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
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | media/java/android/media/MediaRecorder.java | 28 | ||||
| -rw-r--r-- | media/jni/android_media_MediaRecorder.cpp | 60 |
3 files changed, 88 insertions, 1 deletions
diff --git a/api/current.txt b/api/current.txt index fe0043c599ad..1cea3d6e20f9 100644 --- a/api/current.txt +++ b/api/current.txt @@ -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(); diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 78477f757e2a..62240cedf0be 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -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. diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index d2bc1743654f..b3a8b21147c1 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -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[] = { @@ -742,7 +798,9 @@ 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_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 |