1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "android_media_MicrophoneInfo.h" 18 #include "android_media_AudioErrors.h" 19 #include "core_jni_helpers.h" 20 21 using namespace android; 22 23 static jclass gArrayListClass; 24 static jmethodID gArrayListCstor; 25 static struct { 26 jmethodID add; 27 } gArrayListMethods; 28 29 static jclass gFloatClass; 30 static jmethodID gFloatCstor; 31 32 static jclass gFloatArrayClass; 33 34 static jclass gIntegerClass; 35 static jmethodID gIntegerCstor; 36 37 static jclass gMicrophoneInfoClass; 38 static jmethodID gMicrophoneInfoCstor; 39 40 static jclass gMicrophoneInfoCoordinateClass; 41 static jmethodID gMicrophoneInfoCoordinateCstor; 42 43 static jclass gPairClass; 44 static jmethodID gPairCstor; 45 46 namespace android { 47 48 jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo, 49 const media::MicrophoneInfo *microphoneInfo) 50 { 51 jint jStatus = (jint)AUDIO_JAVA_SUCCESS; 52 jstring jDeviceId = NULL; 53 jstring jAddress = NULL; 54 jobject jGeometricLocation = NULL; 55 jobject jOrientation = NULL; 56 jobject jFrequencyResponses = NULL; 57 jobject jChannelMappings = NULL; 58 59 jDeviceId = env->NewStringUTF(String8(microphoneInfo->getDeviceId()).string()); 60 jAddress = env->NewStringUTF(String8(microphoneInfo->getAddress()).string()); 61 if (microphoneInfo->getGeometricLocation().size() != 3 || 62 microphoneInfo->getOrientation().size() != 3) { 63 jStatus = nativeToJavaStatus(BAD_VALUE); 64 goto exit; 65 } 66 jGeometricLocation = env->NewObject(gMicrophoneInfoCoordinateClass, 67 gMicrophoneInfoCoordinateCstor, 68 microphoneInfo->getGeometricLocation()[0], 69 microphoneInfo->getGeometricLocation()[1], 70 microphoneInfo->getGeometricLocation()[2]); 71 jOrientation = env->NewObject(gMicrophoneInfoCoordinateClass, 72 gMicrophoneInfoCoordinateCstor, 73 microphoneInfo->getOrientation()[0], 74 microphoneInfo->getOrientation()[1], 75 microphoneInfo->getOrientation()[2]); 76 // Create a list of Pair for frequency response. 77 if (microphoneInfo->getFrequencyResponses().size() != 2 || 78 microphoneInfo->getFrequencyResponses()[0].size() != 79 microphoneInfo->getFrequencyResponses()[1].size()) { 80 jStatus = nativeToJavaStatus(BAD_VALUE); 81 goto exit; 82 } 83 jFrequencyResponses = env->NewObject(gArrayListClass, gArrayListCstor); 84 for (size_t i = 0; i < microphoneInfo->getFrequencyResponses()[0].size(); i++) { 85 jobject jFrequency = env->NewObject(gFloatClass, gFloatCstor, 86 microphoneInfo->getFrequencyResponses()[0][i]); 87 jobject jResponse = env->NewObject(gFloatClass, gFloatCstor, 88 microphoneInfo->getFrequencyResponses()[1][i]); 89 jobject jFrequencyResponse = env->NewObject(gPairClass, gPairCstor, jFrequency, jResponse); 90 env->CallBooleanMethod(jFrequencyResponses, gArrayListMethods.add, jFrequencyResponse); 91 env->DeleteLocalRef(jFrequency); 92 env->DeleteLocalRef(jResponse); 93 env->DeleteLocalRef(jFrequencyResponse); 94 } 95 // Create a list of Pair for channel mapping. 96 if (microphoneInfo->getChannelMapping().size() != AUDIO_CHANNEL_COUNT_MAX) { 97 jStatus = nativeToJavaStatus(BAD_VALUE); 98 goto exit; 99 } 100 jChannelMappings = env->NewObject(gArrayListClass, gArrayListCstor); 101 for (size_t i = 0; i < microphoneInfo->getChannelMapping().size(); i++) { 102 int channelMappingType = microphoneInfo->getChannelMapping()[i]; 103 if (channelMappingType != AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) { 104 jobject jChannelIndex = env->NewObject(gIntegerClass, gIntegerCstor, i); 105 jobject jChannelMappingType = env->NewObject(gIntegerClass, gIntegerCstor, 106 channelMappingType); 107 jobject jChannelMapping = env->NewObject(gPairClass, gPairCstor, 108 jChannelIndex, jChannelMappingType); 109 env->CallBooleanMethod(jChannelMappings, gArrayListMethods.add, jChannelMapping); 110 env->DeleteLocalRef(jChannelIndex); 111 env->DeleteLocalRef(jChannelMappingType); 112 env->DeleteLocalRef(jChannelMapping); 113 } 114 } 115 *jMicrophoneInfo = env->NewObject(gMicrophoneInfoClass, gMicrophoneInfoCstor, jDeviceId, 116 microphoneInfo->getType(), jAddress, 117 microphoneInfo->getDeviceLocation(), 118 microphoneInfo->getDeviceGroup(), 119 microphoneInfo->getIndexInTheGroup(), 120 jGeometricLocation, jOrientation, 121 jFrequencyResponses, jChannelMappings, 122 microphoneInfo->getSensitivity(), 123 microphoneInfo->getMaxSpl(), 124 microphoneInfo->getMinSpl(), 125 microphoneInfo->getDirectionality()); 126 127 exit: 128 if (jDeviceId != NULL) { 129 env->DeleteLocalRef(jDeviceId); 130 } 131 if (jAddress != NULL) { 132 env->DeleteLocalRef(jAddress); 133 } 134 if (jFrequencyResponses != NULL) { 135 env->DeleteLocalRef(jFrequencyResponses); 136 } 137 if (jChannelMappings != NULL) { 138 env->DeleteLocalRef(jChannelMappings); 139 } 140 if (jGeometricLocation != NULL) { 141 env->DeleteLocalRef(jGeometricLocation); 142 } 143 if (jOrientation != NULL) { 144 env->DeleteLocalRef(jOrientation); 145 } 146 return jStatus; 147 } 148 149 } 150 151 int register_android_media_MicrophoneInfo(JNIEnv *env) 152 { 153 jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList"); 154 gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass); 155 gArrayListCstor = GetMethodIDOrDie(env, arrayListClass, "<init>", "()V"); 156 gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z"); 157 158 jclass floatClass = FindClassOrDie(env, "java/lang/Float"); 159 gFloatClass = MakeGlobalRefOrDie(env, floatClass); 160 gFloatCstor = GetMethodIDOrDie(env, floatClass, "<init>", "(F)V"); 161 162 jclass floatArrayClass = FindClassOrDie(env, "[F"); 163 gFloatArrayClass = MakeGlobalRefOrDie(env, floatArrayClass); 164 165 jclass integerClass = FindClassOrDie(env, "java/lang/Integer"); 166 gIntegerClass = MakeGlobalRefOrDie(env, integerClass); 167 gIntegerCstor = GetMethodIDOrDie(env, integerClass, "<init>", "(I)V"); 168 169 jclass microphoneInfoClass = FindClassOrDie(env, "android/media/MicrophoneInfo"); 170 gMicrophoneInfoClass = MakeGlobalRefOrDie(env, microphoneInfoClass); 171 gMicrophoneInfoCstor = GetMethodIDOrDie(env, microphoneInfoClass, "<init>", 172 "(Ljava/lang/String;ILjava/lang/String;IIILandroid/media/MicrophoneInfo$Coordinate3F;Landroid/media/MicrophoneInfo$Coordinate3F;Ljava/util/List;Ljava/util/List;FFFI)V"); 173 174 jclass microphoneInfoCoordinateClass = FindClassOrDie( 175 env, "android/media/MicrophoneInfo$Coordinate3F"); 176 gMicrophoneInfoCoordinateClass = MakeGlobalRefOrDie(env, microphoneInfoCoordinateClass); 177 gMicrophoneInfoCoordinateCstor = GetMethodIDOrDie(env, microphoneInfoCoordinateClass, "<init>", 178 "(FFF)V"); 179 180 jclass pairClass = FindClassOrDie(env, "android/util/Pair"); 181 gPairClass = MakeGlobalRefOrDie(env, pairClass); 182 gPairCstor = GetMethodIDOrDie(env, pairClass, "<init>", "(Ljava/lang/Object;Ljava/lang/Object;)V"); 183 184 return 0; 185 } 186