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
convertMicrophoneInfoFromNative(JNIEnv * env,jobject * jMicrophoneInfo,const media::MicrophoneInfo * microphoneInfo)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
register_android_media_MicrophoneInfo(JNIEnv * env)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