summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author jiabin <jiabin@google.com> 2018-01-23 12:22:47 -0800
committer jiabin <jiabin@google.com> 2018-01-26 17:53:43 -0800
commit589f6a299ed464cf70a953992b5013d8b275099c (patch)
treec1d3435b052ac1c5532a5eda736e40c85512dc91
parent23675f6c79d0c76caa837402a1e5e49ca11e2a02 (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.txt1
-rw-r--r--media/java/android/media/MediaRecorder.java28
-rw-r--r--media/jni/android_media_MediaRecorder.cpp60
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