diff --git a/api/current.txt b/api/current.txt index 70add6585cd09..7c590eb34bc8d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -21917,6 +21917,7 @@ package android.media { method public java.util.List getActivePlaybackConfigurations(); method public java.util.List getActiveRecordingConfigurations(); method public android.media.AudioDeviceInfo[] getDevices(int); + method public java.util.List getMicrophones() throws java.io.IOException; method public int getMode(); method public java.lang.String getParameters(java.lang.String); method public java.lang.String getProperty(java.lang.String); @@ -24411,6 +24412,41 @@ package android.media { method public float getMediaClockRate(); } + public final class MicrophoneInfo { + method public java.util.List> getChannelMapping(); + method public java.lang.String getDescription(); + method public int getDirectionality(); + method public java.util.List> getFrequencyResponse(); + method public int getGroup(); + method public int getId(); + method public int getIndexInTheGroup(); + method public int getLocation(); + method public float getMaxSpl(); + method public float getMinSpl(); + method public android.media.MicrophoneInfo.Coordinate3F getOrientation(); + method public android.media.MicrophoneInfo.Coordinate3F getPosition(); + method public float getSensitivity(); + method public int getType(); + field public static final int CHANNEL_MAPPING_DIRECT = 1; // 0x1 + field public static final int CHANNEL_MAPPING_PROCESSED = 2; // 0x2 + field public static final int DIRECTIONALITY_BI_DIRECTIONAL = 2; // 0x2 + field public static final int DIRECTIONALITY_CARDIOID = 3; // 0x3 + field public static final int DIRECTIONALITY_HYPER_CARDIOID = 4; // 0x4 + field public static final int DIRECTIONALITY_OMNI = 1; // 0x1 + field public static final int DIRECTIONALITY_SUPER_CARDIOID = 5; // 0x5 + field public static final int DIRECTIONALITY_UNKNOW = 0; // 0x0 + field public static final int LOCATION_MAINBODY = 1; // 0x1 + field public static final int LOCATION_MAINBODY_MOVABLE = 2; // 0x2 + field public static final int LOCATION_PERIPHERAL = 3; // 0x3 + field public static final int LOCATION_UNKNOWN = 0; // 0x0 + } + + public class MicrophoneInfo.Coordinate3F { + field public final float x; + field public final float y; + field public final float z; + } + public final class NotProvisionedException extends android.media.MediaDrmException { ctor public NotProvisionedException(java.lang.String); } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 5751fc99a4849..78a3e137ccb0f 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -164,6 +164,7 @@ cc_library_shared { "android_media_DeviceCallback.cpp", "android_media_JetPlayer.cpp", "android_media_MediaMetricsJNI.cpp", + "android_media_MicrophoneInfo.cpp", "android_media_RemoteDisplay.cpp", "android_media_ToneGenerator.cpp", "android_hardware_Camera.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index e3b5c8f3136ab..78be2fdb14391 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -104,6 +104,7 @@ extern int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv extern int register_android_media_AudioRecord(JNIEnv *env); extern int register_android_media_AudioSystem(JNIEnv *env); extern int register_android_media_AudioTrack(JNIEnv *env); +extern int register_android_media_MicrophoneInfo(JNIEnv *env); extern int register_android_media_JetPlayer(JNIEnv *env); extern int register_android_media_ToneGenerator(JNIEnv *env); @@ -1457,6 +1458,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_media_AudioSystem), REG_JNI(register_android_media_AudioTrack), REG_JNI(register_android_media_JetPlayer), + REG_JNI(register_android_media_MicrophoneInfo), REG_JNI(register_android_media_RemoteDisplay), REG_JNI(register_android_media_ToneGenerator), diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 376a797176779..adaff1fcfbcbd 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -21,17 +21,20 @@ #include #include +#include #include #include #include "core_jni_helpers.h" #include #include +#include #include #include #include #include "android_media_AudioFormat.h" #include "android_media_AudioErrors.h" +#include "android_media_MicrophoneInfo.h" // ---------------------------------------------------------------------------- @@ -143,7 +146,6 @@ static struct { jfieldID mSource; } gAudioAttributesFields; - static const char* const kEventHandlerClassPathName = "android/media/AudioPortEventHandler"; static struct { @@ -1158,7 +1160,6 @@ exit: return jStatus; } - static jint android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz, jobject jPorts, jintArray jGeneration) @@ -1789,6 +1790,45 @@ android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz, return AudioSystem::isOffloadSupported(format); } +static jint +android_media_AudioSystem_getMicrophones(JNIEnv *env, jobject thiz, jobject jMicrophonesInfo) +{ + ALOGV("getMicrophones"); + + if (jMicrophonesInfo == NULL) { + ALOGE("jMicrophonesInfo NULL MicrophoneInfo ArrayList"); + return (jint)AUDIO_JAVA_BAD_VALUE; + } + if (!env->IsInstanceOf(jMicrophonesInfo, gArrayListClass)) { + ALOGE("getMicrophones not an arraylist"); + return (jint)AUDIO_JAVA_BAD_VALUE; + } + + jint jStatus; + std::vector microphones; + status_t status = AudioSystem::getMicrophones(µphones); + if (status != NO_ERROR) { + ALOGE_IF(status != NO_ERROR, "AudioSystem::getMicrophones error %d", status); + jStatus = nativeToJavaStatus(status); + return jStatus; + } + if (microphones.size() == 0) { + jStatus = (jint)AUDIO_JAVA_SUCCESS; + return jStatus; + } + for (size_t i = 0; i < microphones.size(); i++) { + jobject jMicrophoneInfo; + jStatus = convertMicrophoneInfoFromNative(env, &jMicrophoneInfo, µphones[i]); + if (jStatus != AUDIO_JAVA_SUCCESS) { + return jStatus; + } + env->CallBooleanMethod(jMicrophonesInfo, gArrayListMethods.add, jMicrophoneInfo); + env->DeleteLocalRef(jMicrophoneInfo); + } + + return jStatus; +} + // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { @@ -1843,6 +1883,7 @@ static const JNINativeMethod gMethods[] = { {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady}, {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB}, {"native_is_offload_supported", "(IIII)Z", (void *)android_media_AudioSystem_isOffloadSupported}, + {"getMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioSystem_getMicrophones}, }; diff --git a/core/jni/android_media_MicrophoneInfo.cpp b/core/jni/android_media_MicrophoneInfo.cpp new file mode 100644 index 0000000000000..9198cbe648eb0 --- /dev/null +++ b/core/jni/android_media_MicrophoneInfo.cpp @@ -0,0 +1,187 @@ +/* + * 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 "android_media_MicrophoneInfo.h" +#include "android_media_AudioErrors.h" +#include "core_jni_helpers.h" + +using namespace android; + +static jclass gArrayListClass; +static jmethodID gArrayListCstor; +static struct { + jmethodID add; +} gArrayListMethods; + +static jclass gFloatClass; +static jmethodID gFloatCstor; + +static jclass gFloatArrayClass; + +static jclass gIntegerClass; +static jmethodID gIntegerCstor; + +static jclass gMicrophoneInfoClass; +static jmethodID gMicrophoneInfoCstor; + +static jclass gMicrophoneInfoCoordinateClass; +static jmethodID gMicrophoneInfoCoordinateCstor; + +static jclass gPairClass; +static jmethodID gPairCstor; + +namespace android { + +jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo, + const media::MicrophoneInfo *microphoneInfo) +{ + jint jStatus = (jint)AUDIO_JAVA_SUCCESS; + jstring jDeviceId = NULL; + jstring jAddress = NULL; + jobject jGeometricLocation = NULL; + jobject jOrientation = NULL; + jobject jFrequencyResponses = NULL; + jobject jChannelMappings = NULL; + + jDeviceId = env->NewStringUTF(String8(microphoneInfo->getDeviceId()).string()); + jAddress = env->NewStringUTF(String8(microphoneInfo->getAddress()).string()); + if (microphoneInfo->getGeometricLocation().size() != 3 || + microphoneInfo->getOrientation().size() != 3) { + jStatus = nativeToJavaStatus(BAD_VALUE); + goto exit; + } + jGeometricLocation = env->NewObject(gMicrophoneInfoCoordinateClass, + gMicrophoneInfoCoordinateCstor, + NULL, + microphoneInfo->getGeometricLocation()[0], + microphoneInfo->getGeometricLocation()[1], + microphoneInfo->getGeometricLocation()[2]); + jOrientation = env->NewObject(gMicrophoneInfoCoordinateClass, + gMicrophoneInfoCoordinateCstor, + NULL, + microphoneInfo->getOrientation()[0], + microphoneInfo->getOrientation()[1], + microphoneInfo->getOrientation()[2]); + // Create a list of Pair for frequency response. + if (microphoneInfo->getFrequencyResponses().size() != 2 || + microphoneInfo->getFrequencyResponses()[0].size() != + microphoneInfo->getFrequencyResponses()[1].size()) { + jStatus = nativeToJavaStatus(BAD_VALUE); + goto exit; + } + jFrequencyResponses = env->NewObject(gArrayListClass, gArrayListCstor); + for (size_t i = 0; i < microphoneInfo->getFrequencyResponses()[0].size(); i++) { + jobject jFrequency = env->NewObject(gFloatClass, gFloatCstor, + microphoneInfo->getFrequencyResponses()[0][i]); + jobject jResponse = env->NewObject(gFloatClass, gFloatCstor, + microphoneInfo->getFrequencyResponses()[1][i]); + jobject jFrequencyResponse = env->NewObject(gPairClass, gPairCstor, jFrequency, jResponse); + env->CallBooleanMethod(jFrequencyResponses, gArrayListMethods.add, jFrequencyResponse); + env->DeleteLocalRef(jFrequency); + env->DeleteLocalRef(jResponse); + env->DeleteLocalRef(jFrequencyResponse); + } + // Create a list of Pair for channel mapping. + if (microphoneInfo->getChannelMapping().size() != AUDIO_CHANNEL_COUNT_MAX) { + jStatus = nativeToJavaStatus(BAD_VALUE); + goto exit; + } + jChannelMappings = env->NewObject(gArrayListClass, gArrayListCstor); + for (size_t i = 0; i < microphoneInfo->getChannelMapping().size(); i++) { + int channelMappingType = microphoneInfo->getChannelMapping()[i]; + if (channelMappingType != AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) { + jobject jChannelIndex = env->NewObject(gIntegerClass, gIntegerCstor, i); + jobject jChannelMappingType = env->NewObject(gIntegerClass, gIntegerCstor, + channelMappingType); + jobject jChannelMapping = env->NewObject(gPairClass, gPairCstor, + jChannelIndex, jChannelMappingType); + env->CallBooleanMethod(jChannelMappings, gArrayListMethods.add, jChannelMapping); + env->DeleteLocalRef(jChannelIndex); + env->DeleteLocalRef(jChannelMappingType); + env->DeleteLocalRef(jChannelMapping); + } + } + *jMicrophoneInfo = env->NewObject(gMicrophoneInfoClass, gMicrophoneInfoCstor, jDeviceId, + microphoneInfo->getType(), jAddress, + microphoneInfo->getDeviceLocation(), + microphoneInfo->getDeviceGroup(), + microphoneInfo->getIndexInTheGroup(), + jGeometricLocation, jOrientation, + jFrequencyResponses, jChannelMappings, + microphoneInfo->getSensitivity(), + microphoneInfo->getMaxSpl(), + microphoneInfo->getMinSpl(), + microphoneInfo->getDirectionality()); + +exit: + if (jDeviceId != NULL) { + env->DeleteLocalRef(jDeviceId); + } + if (jAddress != NULL) { + env->DeleteLocalRef(jAddress); + } + if (jFrequencyResponses != NULL) { + env->DeleteLocalRef(jFrequencyResponses); + } + if (jChannelMappings != NULL) { + env->DeleteLocalRef(jChannelMappings); + } + if (jGeometricLocation != NULL) { + env->DeleteLocalRef(jGeometricLocation); + } + if (jOrientation != NULL) { + env->DeleteLocalRef(jOrientation); + } + return jStatus; +} + +} + +int register_android_media_MicrophoneInfo(JNIEnv *env) +{ + jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList"); + gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass); + gArrayListCstor = GetMethodIDOrDie(env, arrayListClass, "", "()V"); + gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z"); + + jclass floatClass = FindClassOrDie(env, "java/lang/Float"); + gFloatClass = MakeGlobalRefOrDie(env, floatClass); + gFloatCstor = GetMethodIDOrDie(env, floatClass, "", "(F)V"); + + jclass floatArrayClass = FindClassOrDie(env, "[F"); + gFloatArrayClass = MakeGlobalRefOrDie(env, floatArrayClass); + + jclass integerClass = FindClassOrDie(env, "java/lang/Integer"); + gIntegerClass = MakeGlobalRefOrDie(env, integerClass); + gIntegerCstor = GetMethodIDOrDie(env, integerClass, "", "(I)V"); + + jclass microphoneInfoClass = FindClassOrDie(env, "android/media/MicrophoneInfo"); + gMicrophoneInfoClass = MakeGlobalRefOrDie(env, microphoneInfoClass); + gMicrophoneInfoCstor = GetMethodIDOrDie(env, microphoneInfoClass, "", + "(Ljava/lang/String;ILjava/lang/String;IIILandroid/media/MicrophoneInfo$Coordinate3F;Landroid/media/MicrophoneInfo$Coordinate3F;Ljava/util/List;Ljava/util/List;FFFI)V"); + + jclass microphoneInfoCoordinateClass = FindClassOrDie( + env, "android/media/MicrophoneInfo$Coordinate3F"); + gMicrophoneInfoCoordinateClass = MakeGlobalRefOrDie(env, microphoneInfoCoordinateClass); + gMicrophoneInfoCoordinateCstor = GetMethodIDOrDie(env, microphoneInfoCoordinateClass, "", + "(Landroid/media/MicrophoneInfo;FFF)V"); + + jclass pairClass = FindClassOrDie(env, "android/util/Pair"); + gPairClass = MakeGlobalRefOrDie(env, pairClass); + gPairCstor = GetMethodIDOrDie(env, pairClass, "", "(Ljava/lang/Object;Ljava/lang/Object;)V"); + + return 0; +} diff --git a/core/jni/android_media_MicrophoneInfo.h b/core/jni/android_media_MicrophoneInfo.h new file mode 100644 index 0000000000000..241b6d05b724d --- /dev/null +++ b/core/jni/android_media_MicrophoneInfo.h @@ -0,0 +1,33 @@ +/* + * 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_MICROPHONEINFO_H +#define ANDROID_MEDIA_MICROPHONEINFO_H + +#include +#include + +#include "jni.h" + +namespace android { + +// Conversion from C++ MicrophoneInfo object to Java MicrophoneInfo object + +extern jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo, + const media::MicrophoneInfo *microphoneInfo); +} // namespace android + +#endif \ No newline at end of file diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 2ac4063d1b08b..a0a67b09964c0 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -48,11 +48,13 @@ import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.Slog; import android.view.KeyEvent; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -4566,6 +4568,51 @@ public class AudioManager { } } + /** + * Set port id for microphones by matching device type and address. + * @hide + */ + public static void setPortIdForMicrophones(ArrayList microphones) { + AudioDeviceInfo[] devices = getDevicesStatic(AudioManager.GET_DEVICES_INPUTS); + for (int i = microphones.size() - 1; i >= 0; i--) { + boolean foundPortId = false; + for (AudioDeviceInfo device : devices) { + if (device.getPort().type() == microphones.get(i).getInternalDeviceType() + && TextUtils.equals(device.getAddress(), microphones.get(i).getAddress())) { + microphones.get(i).setId(device.getId()); + foundPortId = true; + break; + } + } + if (!foundPortId) { + Log.i(TAG, "Failed to find port id for device with type:" + + microphones.get(i).getType() + " address:" + + microphones.get(i).getAddress()); + microphones.remove(i); + } + } + } + + /** + * Returns a list of {@link MicrophoneInfo} that corresponds to the characteristics + * of all available microphones. The list is empty when no microphones are available + * on the device. An error during the query will result in an IOException being thrown. + * + * @return a list that contains all microphones' characteristics + * @throws IOException if an error occurs. + */ + public List getMicrophones() throws IOException { + ArrayList microphones = new ArrayList(); + int status = AudioSystem.getMicrophones(microphones); + if (status != AudioManager.SUCCESS) { + // fail and bail! + Log.e(TAG, "getMicrophones failed:" + status); + return new ArrayList(); // Always return a list. + } + setPortIdForMicrophones(microphones); + return microphones; + } + // Since we need to calculate the changes since THE LAST NOTIFICATION, and not since the // (unpredictable) last time updateAudioPortCache() was called by someone, keep a list // of the ports that exist at the time of the last notification. diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index dcd37dafd4955..be9fcb8fae835 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -827,6 +827,8 @@ public class AudioSystem private static native boolean native_is_offload_supported(int encoding, int sampleRate, int channelMask, int channelIndexMask); + public static native int getMicrophones(ArrayList microphonesInfo); + // Items shared with audio service /** diff --git a/media/java/android/media/MicrophoneInfo.java b/media/java/android/media/MicrophoneInfo.java new file mode 100644 index 0000000000000..21f9171664982 --- /dev/null +++ b/media/java/android/media/MicrophoneInfo.java @@ -0,0 +1,342 @@ +/* + * 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; + +import android.annotation.IntDef; +import android.util.Pair; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; + +/** + * Class providing information on a microphone. It indicates the location and orientation of the + * microphone on the device as well as useful information like frequency response and sensitivity. + * It can be used by applications implementing special pre processing effects like noise suppression + * of beam forming that need to know about precise microphone characteristics in order to adapt + * their algorithms. + */ +public final class MicrophoneInfo { + + /** + * A microphone that the location is unknown. + */ + public static final int LOCATION_UNKNOWN = 0; + + /** + * A microphone that locate on main body of the device. + */ + public static final int LOCATION_MAINBODY = 1; + + /** + * A microphone that locate on a movable main body of the device. + */ + public static final int LOCATION_MAINBODY_MOVABLE = 2; + + /** + * A microphone that locate on a peripheral. + */ + public static final int LOCATION_PERIPHERAL = 3; + + /** + * Unknown microphone directionality. + */ + public static final int DIRECTIONALITY_UNKNOW = 0; + + /** + * Microphone directionality type: omni. + */ + public static final int DIRECTIONALITY_OMNI = 1; + + /** + * Microphone directionality type: bi-directional. + */ + public static final int DIRECTIONALITY_BI_DIRECTIONAL = 2; + + /** + * Microphone directionality type: cardioid. + */ + public static final int DIRECTIONALITY_CARDIOID = 3; + + /** + * Microphone directionality type: hyper cardioid. + */ + public static final int DIRECTIONALITY_HYPER_CARDIOID = 4; + + /** + * Microphone directionality type: super cardioid. + */ + public static final int DIRECTIONALITY_SUPER_CARDIOID = 5; + + /** + * The channel contains raw audio from this microphone. + */ + public static final int CHANNEL_MAPPING_DIRECT = 1; + + /** + * The channel contains processed audio from this microphone and possibly another microphone. + */ + public static final int CHANNEL_MAPPING_PROCESSED = 2; + + /** @hide */ + @IntDef(flag = true, prefix = { "LOCATION_" }, value = { + LOCATION_UNKNOWN, + LOCATION_MAINBODY, + LOCATION_MAINBODY_MOVABLE, + LOCATION_PERIPHERAL, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MicrophoneLocation {} + + /** @hide */ + @IntDef(flag = true, prefix = { "DIRECTIONALITY_" }, value = { + DIRECTIONALITY_UNKNOW, + DIRECTIONALITY_OMNI, + DIRECTIONALITY_BI_DIRECTIONAL, + DIRECTIONALITY_CARDIOID, + DIRECTIONALITY_HYPER_CARDIOID, + DIRECTIONALITY_SUPER_CARDIOID, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface MicrophoneDirectionality {} + + private Coordinate3F mPosition; + private Coordinate3F mOrientation; + private String mDeviceId; + private String mAddress; + private List> mFrequencyResponse; + private List> mChannelMapping; + private float mMaxSpl; + private float mMinSpl; + private float mSensitivity; + private int mLocation; + private int mGroup; /* Usually 0 will be used for main body. */ + private int mIndexInTheGroup; + private int mPortId; /* mPortId will correspond to the id in AudioPort */ + private int mType; + private int mDirectionality; + + MicrophoneInfo(String deviceId, int type, String address, int location, + int group, int indexInTheGroup, Coordinate3F position, + Coordinate3F orientation, List> frequencyResponse, + List> channelMapping, float sensitivity, float maxSpl, + float minSpl, int directionality) { + mDeviceId = deviceId; + mType = type; + mAddress = address; + mLocation = location; + mGroup = group; + mIndexInTheGroup = indexInTheGroup; + mPosition = position; + mOrientation = orientation; + mFrequencyResponse = frequencyResponse; + mChannelMapping = channelMapping; + mSensitivity = sensitivity; + mMaxSpl = maxSpl; + mMinSpl = minSpl; + mDirectionality = directionality; + } + + /** + * Returns alphanumeric code that uniquely identifies the device. + * + * @return the description of the microphone + */ + public String getDescription() { + return mDeviceId; + } + + /** + * Returns The system unique device ID that corresponds to the id + * returned by {@link AudioDeviceInfo#getId()}. + * + * @return the microphone's id + */ + public int getId() { + return mPortId; + } + + /** + * @hide + * Returns the internal device type (e.g AudioSystem.DEVICE_IN_BUILTIN_MIC). + * The internal device type could be used when getting microphone's port id + * by matching type and address. + * + * @return the internal device type + */ + public int getInternalDeviceType() { + return mType; + } + + /** + * Returns the device type identifier of the microphone (e.g AudioDeviceInfo.TYPE_BUILTIN_MIC). + * + * @return the device type of the microphone + */ + public int getType() { + return AudioDeviceInfo.convertInternalDeviceToDeviceType(mType); + } + + /** + * @hide + * Returns The "address" string of the microphone that corresponds to the + * address returned by {@link AudioDeviceInfo#getAddress()} + * @return the address of the microphone + */ + public String getAddress() { + return mAddress; + } + + /** + * Returns the location of the microphone. The return value is + * one of {@link #LOCATION_UNKNOWN}, {@link #LOCATION_MAINBODY}, + * {@link #LOCATION_MAINBODY_MOVABLE}, or {@link #LOCATION_PERIPHERAL}. + * + * @return the location of the microphone + */ + public @MicrophoneLocation int getLocation() { + return mLocation; + } + + /** + * Returns A device group id that can be used to group together microphones on the same + * peripheral, attachments or logical groups. Main body is usually group 0. + * + * @return the group of the microphone + */ + public int getGroup() { + return mGroup; + } + + /** + * Returns unique index for device within its group. + * + * @return the microphone's index in its group + */ + public int getIndexInTheGroup() { + return mIndexInTheGroup; + } + + /** + * Returns A {@link Coordinate3F} object that represents the geometric location of microphone + * in meters, from botton-left-back corner of appliance. X-axis, Y-axis and Z-axis show + * as the x, y, z values. + * + * @return the geometric location of the microphone + */ + public Coordinate3F getPosition() { + return mPosition; + } + + /** + * Returns A {@link Coordinate3F} object that represents the orientation of microphone. + * X-axis, Y-axis and Z-axis show as the x, y, z value. The orientation will be normalized + * such as sqrt(x^2 + y^2 + z^2) equals 1. + * + * @return the orientation of the microphone + */ + public Coordinate3F getOrientation() { + return mOrientation; + } + + /** + * Returns a {@link android.util.Pair} list of frequency responses. + * For every {@link android.util.Pair} in the list, the first value represents frequency in Hz, + * and the second value represents response in dB. + * + * @return the frequency response of the microphone + */ + public List> getFrequencyResponse() { + return mFrequencyResponse; + } + + /** + * Returns a {@link android.util.Pair} list for channel mapping, which indicating how this + * microphone is used by each channels or a capture stream. For each {@link android.util.Pair}, + * the first value is channel index, the second value is channel mapping type, which could be + * either {@link #CHANNEL_MAPPING_DIRECT} or {@link #CHANNEL_MAPPING_PROCESSED}. + * If a channel has contributions from more than one microphone, it is likely the HAL + * did some extra processing to combine the sources, but this is to be inferred by the user. + * Empty list when the MicrophoneInfo is returned by AudioManager.getMicrophones(). + * At least one entry when the MicrophoneInfo is returned by AudioRecord.getActiveMicrophones(). + * + * @return a {@link android.util.Pair} list for channel mapping + */ + public List> getChannelMapping() { + return mChannelMapping; + } + + /** + * Returns the level in dBFS produced by a 1000Hz tone at 94 dB SPL. + * + * @return the sensitivity of the microphone + */ + public float getSensitivity() { + return mSensitivity; + } + + /** + * Returns the level in dB of the maximum SPL supported by the device at 1000Hz. + * + * @return the maximum level in dB + */ + public float getMaxSpl() { + return mMaxSpl; + } + + /** + * Returns the level in dB of the minimum SPL that can be registered by the device at 1000Hz. + * + * @return the minimum level in dB + */ + public float getMinSpl() { + return mMinSpl; + } + + /** + * Returns the directionality of microphone. The return value is one of + * {@link #DIRECTIONALITY_UNKNOW}, {@link #DIRECTIONALITY_OMNI}, + * {@link #DIRECTIONALITY_BI_DIRECTIONAL}, {@link #DIRECTIONALITY_CARDIOID}, + * {@link #DIRECTIONALITY_HYPER_CARDIOID}, or {@link #DIRECTIONALITY_SUPER_CARDIOID}. + * + * @return the directionality of microphone + */ + public @MicrophoneDirectionality int getDirectionality() { + return mDirectionality; + } + + /** + * Set the port id for the device. + * @hide + */ + public void setId(int portId) { + mPortId = portId; + } + + /* A class containing three float value to represent a 3D coordinate */ + public class Coordinate3F { + public final float x; + public final float y; + public final float z; + + Coordinate3F(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + } + } +}