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
19 #include <media/AidlConversion.h>
20
21 #include "android_media_AudioErrors.h"
22 #include "core_jni_helpers.h"
23
24 using namespace android;
25
26 static jclass gArrayListClass;
27 static jmethodID gArrayListCstor;
28 static struct {
29 jmethodID add;
30 } gArrayListMethods;
31
32 static jclass gFloatClass;
33 static jmethodID gFloatCstor;
34
35 static jclass gFloatArrayClass;
36
37 static jclass gIntegerClass;
38 static jmethodID gIntegerCstor;
39
40 static jclass gMicrophoneInfoClass;
41 static jmethodID gMicrophoneInfoCstor;
42
43 static jclass gMicrophoneInfoCoordinateClass;
44 static jmethodID gMicrophoneInfoCoordinateCstor;
45
46 static jclass gPairClass;
47 static jmethodID gPairCstor;
48
49 namespace android {
50
convertMicrophoneInfoFromNative(JNIEnv * env,jobject * jMicrophoneInfo,const media::MicrophoneInfoFw * microphoneInfo)51 jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo,
52 const media::MicrophoneInfoFw *microphoneInfo) {
53 // The Java object uses the same enum values as the C enum values, which are
54 // generated from HIDL. Thus, we can use the legacy structure as the source for
55 // creating the Java object. Once we start removing legacy types, we can add
56 // direct converters between Java and AIDL, this will eliminate the need
57 // to have JNI code like this one.
58 auto conv = aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(*microphoneInfo);
59 if (!conv.ok()) {
60 return nativeToJavaStatus(conv.error());
61 }
62
63 jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
64 jstring jDeviceId = NULL;
65 jstring jAddress = NULL;
66 jobject jGeometricLocation = NULL;
67 jobject jOrientation = NULL;
68 jobject jFrequencyResponses = NULL;
69 jobject jChannelMappings = NULL;
70
71 const auto &micInfo = conv.value();
72 jDeviceId = env->NewStringUTF(micInfo.device_id);
73 jAddress = env->NewStringUTF(micInfo.address);
74 jGeometricLocation =
75 env->NewObject(gMicrophoneInfoCoordinateClass, gMicrophoneInfoCoordinateCstor,
76 micInfo.geometric_location.x, micInfo.geometric_location.y,
77 micInfo.geometric_location.z);
78 jOrientation =
79 env->NewObject(gMicrophoneInfoCoordinateClass, gMicrophoneInfoCoordinateCstor,
80 micInfo.orientation.x, micInfo.orientation.y, micInfo.orientation.z);
81 // Create a list of Pair for frequency response.
82 jFrequencyResponses = env->NewObject(gArrayListClass, gArrayListCstor);
83 for (size_t i = 0; i < micInfo.num_frequency_responses; i++) {
84 jobject jFrequency =
85 env->NewObject(gFloatClass, gFloatCstor, micInfo.frequency_responses[0][i]);
86 jobject jResponse =
87 env->NewObject(gFloatClass, gFloatCstor, micInfo.frequency_responses[1][i]);
88 jobject jFrequencyResponse = env->NewObject(gPairClass, gPairCstor, jFrequency, jResponse);
89 env->CallBooleanMethod(jFrequencyResponses, gArrayListMethods.add, jFrequencyResponse);
90 env->DeleteLocalRef(jFrequency);
91 env->DeleteLocalRef(jResponse);
92 env->DeleteLocalRef(jFrequencyResponse);
93 }
94 // Create a list of Pair for channel mapping.
95 jChannelMappings = env->NewObject(gArrayListClass, gArrayListCstor);
96 const auto &channelMapping = micInfo.channel_mapping;
97 for (size_t i = 0; i < std::size(channelMapping); i++) {
98 int channelMappingType = channelMapping[i];
99 if (channelMappingType != AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {
100 jobject jChannelIndex = env->NewObject(gIntegerClass, gIntegerCstor, i);
101 jobject jChannelMappingType = env->NewObject(gIntegerClass, gIntegerCstor,
102 channelMappingType);
103 jobject jChannelMapping = env->NewObject(gPairClass, gPairCstor,
104 jChannelIndex, jChannelMappingType);
105 env->CallBooleanMethod(jChannelMappings, gArrayListMethods.add, jChannelMapping);
106 env->DeleteLocalRef(jChannelIndex);
107 env->DeleteLocalRef(jChannelMappingType);
108 env->DeleteLocalRef(jChannelMapping);
109 }
110 }
111 *jMicrophoneInfo = env->NewObject(gMicrophoneInfoClass, gMicrophoneInfoCstor, jDeviceId,
112 micInfo.device, jAddress, micInfo.location, micInfo.group,
113 micInfo.index_in_the_group, jGeometricLocation, jOrientation,
114 jFrequencyResponses, jChannelMappings, micInfo.sensitivity,
115 micInfo.max_spl, micInfo.min_spl, micInfo.directionality);
116
117 if (jDeviceId != NULL) {
118 env->DeleteLocalRef(jDeviceId);
119 }
120 if (jAddress != NULL) {
121 env->DeleteLocalRef(jAddress);
122 }
123 if (jFrequencyResponses != NULL) {
124 env->DeleteLocalRef(jFrequencyResponses);
125 }
126 if (jChannelMappings != NULL) {
127 env->DeleteLocalRef(jChannelMappings);
128 }
129 if (jGeometricLocation != NULL) {
130 env->DeleteLocalRef(jGeometricLocation);
131 }
132 if (jOrientation != NULL) {
133 env->DeleteLocalRef(jOrientation);
134 }
135 return jStatus;
136 }
137 }
138
register_android_media_MicrophoneInfo(JNIEnv * env)139 int register_android_media_MicrophoneInfo(JNIEnv *env)
140 {
141 jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
142 gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
143 gArrayListCstor = GetMethodIDOrDie(env, arrayListClass, "<init>", "()V");
144 gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
145
146 jclass floatClass = FindClassOrDie(env, "java/lang/Float");
147 gFloatClass = MakeGlobalRefOrDie(env, floatClass);
148 gFloatCstor = GetMethodIDOrDie(env, floatClass, "<init>", "(F)V");
149
150 jclass floatArrayClass = FindClassOrDie(env, "[F");
151 gFloatArrayClass = MakeGlobalRefOrDie(env, floatArrayClass);
152
153 jclass integerClass = FindClassOrDie(env, "java/lang/Integer");
154 gIntegerClass = MakeGlobalRefOrDie(env, integerClass);
155 gIntegerCstor = GetMethodIDOrDie(env, integerClass, "<init>", "(I)V");
156
157 jclass microphoneInfoClass = FindClassOrDie(env, "android/media/MicrophoneInfo");
158 gMicrophoneInfoClass = MakeGlobalRefOrDie(env, microphoneInfoClass);
159 gMicrophoneInfoCstor = GetMethodIDOrDie(env, microphoneInfoClass, "<init>",
160 "(Ljava/lang/String;ILjava/lang/String;IIILandroid/media/MicrophoneInfo$Coordinate3F;Landroid/media/MicrophoneInfo$Coordinate3F;Ljava/util/List;Ljava/util/List;FFFI)V");
161
162 jclass microphoneInfoCoordinateClass = FindClassOrDie(
163 env, "android/media/MicrophoneInfo$Coordinate3F");
164 gMicrophoneInfoCoordinateClass = MakeGlobalRefOrDie(env, microphoneInfoCoordinateClass);
165 gMicrophoneInfoCoordinateCstor = GetMethodIDOrDie(env, microphoneInfoCoordinateClass, "<init>",
166 "(FFF)V");
167
168 jclass pairClass = FindClassOrDie(env, "android/util/Pair");
169 gPairClass = MakeGlobalRefOrDie(env, pairClass);
170 gPairCstor = GetMethodIDOrDie(env, pairClass, "<init>", "(Ljava/lang/Object;Ljava/lang/Object;)V");
171
172 return 0;
173 }
174