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 //#define LOG_NDEBUG 0
18
19 #define LOG_TAG "AudioAttributes-JNI"
20
21 #include <inttypes.h>
22 #include <jni.h>
23 #include <nativehelper/JNIHelp.h>
24 #include "core_jni_helpers.h"
25
26 #include <utils/Log.h>
27 #include <vector>
28
29 #include <nativehelper/ScopedLocalRef.h>
30 #include <nativehelper/ScopedUtfChars.h>
31
32 #include "android_media_AudioAttributes.h"
33 #include "android_media_AudioErrors.h"
34
35 // ----------------------------------------------------------------------------
36
37 using namespace android;
38
39 // ----------------------------------------------------------------------------
40 static const char* const kClassPathName = "android/media/AudioAttributes";
41
42 static jclass gAudioAttributesClass;
43 static struct {
44 jfieldID mUsage; // AudioAttributes.mUsage
45 jfieldID mSource; // AudioAttributes.mSource
46 jfieldID mContentType; // AudioAttributes.mContentType
47 jfieldID mFlags; // AudioAttributes.mFlags
48 jfieldID mFormattedTags; // AudioAttributes.mFormattedTags
49 } gAudioAttributesFields;
50
51 static jclass gAudioAttributesBuilderClass;
52 static jmethodID gAudioAttributesBuilderCstor;
53 static struct {
54 jmethodID build;
55 jmethodID setUsage;
56 jmethodID setInternalCapturePreset;
57 jmethodID setContentType;
58 jmethodID setFlags;
59 jmethodID addTag;
60 } gAudioAttributesBuilderMethods;
61
62
nativeAudioAttributesFromJavaAudioAttributes(JNIEnv * env,jobject jAudioAttributes,audio_attributes_t * aa)63 static jint nativeAudioAttributesFromJavaAudioAttributes(
64 JNIEnv* env, jobject jAudioAttributes, audio_attributes_t *aa)
65 {
66 if (env == nullptr) {
67 return AUDIO_JAVA_DEAD_OBJECT;
68 }
69 if (jAudioAttributes == nullptr) {
70 ALOGE("Invalid AudioAttributes java object");
71 return (jint)AUDIO_JAVA_BAD_VALUE;
72 }
73 if (!env->IsInstanceOf(jAudioAttributes, gAudioAttributesClass)) {
74 return (jint)AUDIO_JAVA_BAD_VALUE;
75 }
76 const jstring jtags =
77 (jstring) env->GetObjectField(jAudioAttributes, gAudioAttributesFields.mFormattedTags);
78 if (jtags == nullptr) {
79 return AUDIO_JAVA_NO_INIT;
80 }
81 const char* tags = env->GetStringUTFChars(jtags, NULL);
82 // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
83 strncpy(aa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
84 env->ReleaseStringUTFChars(jtags, tags);
85
86 // Record ?
87 aa->source = (audio_source_t) env->GetIntField(jAudioAttributes,
88 gAudioAttributesFields.mSource);
89 // Track ?
90 aa->usage = (audio_usage_t) env->GetIntField(jAudioAttributes, gAudioAttributesFields.mUsage);
91
92 aa->content_type =
93 (audio_content_type_t) env->GetIntField(jAudioAttributes,
94 gAudioAttributesFields.mContentType);
95
96 aa->flags = (audio_flags_mask_t)env->GetIntField(jAudioAttributes,
97 gAudioAttributesFields.mFlags);
98
99 ALOGV("AudioAttributes for usage=%d content=%d source=%d tags=%s flags=%08x tags=%s",
100 aa->usage, aa->content_type, aa->source, aa->tags, aa->flags, aa->tags);
101 return (jint)AUDIO_JAVA_SUCCESS;
102 }
103
nativeAudioAttributesToJavaAudioAttributes(JNIEnv * env,jobject * jAudioAttributes,const audio_attributes_t & attributes)104 static jint nativeAudioAttributesToJavaAudioAttributes(
105 JNIEnv* env, jobject *jAudioAttributes, const audio_attributes_t &attributes)
106 {
107 ScopedLocalRef<jobject> jAttributeBuilder(env, env->NewObject(gAudioAttributesBuilderClass,
108 gAudioAttributesBuilderCstor));
109 if (jAttributeBuilder.get() == nullptr) {
110 return (jint)AUDIO_JAVA_ERROR;
111 }
112 env->CallObjectMethod(jAttributeBuilder.get(),
113 gAudioAttributesBuilderMethods.setUsage,
114 attributes.usage);
115 env->CallObjectMethod(jAttributeBuilder.get(),
116 gAudioAttributesBuilderMethods.setInternalCapturePreset,
117 attributes.source);
118 env->CallObjectMethod(jAttributeBuilder.get(),
119 gAudioAttributesBuilderMethods.setContentType,
120 attributes.content_type);
121 env->CallObjectMethod(jAttributeBuilder.get(),
122 gAudioAttributesBuilderMethods.setFlags,
123 attributes.flags);
124 env->CallObjectMethod(jAttributeBuilder.get(),
125 gAudioAttributesBuilderMethods.addTag,
126 env->NewStringUTF(attributes.tags));
127
128 *jAudioAttributes = env->CallObjectMethod(jAttributeBuilder.get(),
129 gAudioAttributesBuilderMethods.build);
130 return (jint)AUDIO_JAVA_SUCCESS;
131 }
132
133 // ----------------------------------------------------------------------------
makeUnique()134 JNIAudioAttributeHelper::UniqueAaPtr JNIAudioAttributeHelper::makeUnique()
135 {
136 audio_attributes_t *aa = new (calloc(1, sizeof(audio_attributes_t)))
137 audio_attributes_t{AUDIO_ATTRIBUTES_INITIALIZER};
138 return UniqueAaPtr{aa};
139 }
140
nativeFromJava(JNIEnv * env,jobject jAudioAttributes,audio_attributes_t * paa)141 jint JNIAudioAttributeHelper::nativeFromJava(JNIEnv* env, jobject jAudioAttributes,
142 audio_attributes_t *paa)
143 {
144 return nativeAudioAttributesFromJavaAudioAttributes(env, jAudioAttributes, paa);
145 }
146
nativeToJava(JNIEnv * env,jobject * jAudioAttributes,const audio_attributes_t & attributes)147 jint JNIAudioAttributeHelper::nativeToJava(
148 JNIEnv* env, jobject *jAudioAttributes, const audio_attributes_t &attributes)
149 {
150 return nativeAudioAttributesToJavaAudioAttributes(env, jAudioAttributes, attributes);
151 }
152
getJavaArray(JNIEnv * env,jobjectArray * jAudioAttributeArray,jint numAudioAttributes)153 jint JNIAudioAttributeHelper::getJavaArray(
154 JNIEnv* env, jobjectArray *jAudioAttributeArray, jint numAudioAttributes)
155 {
156 *jAudioAttributeArray = env->NewObjectArray(numAudioAttributes, gAudioAttributesClass, NULL);
157 return *jAudioAttributeArray == NULL? (jint)AUDIO_JAVA_ERROR : (jint)AUDIO_JAVA_SUCCESS;
158 }
159
160 /*
161 * JNI registration.
162 */
163 static const JNINativeMethod gMethods[] = {
164 // n/a
165 };
166
register_android_media_AudioAttributes(JNIEnv * env)167 int register_android_media_AudioAttributes(JNIEnv *env)
168 {
169 jclass audioAttributesClass = FindClassOrDie(env, kClassPathName);
170 gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
171 gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
172 gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
173 gAudioAttributesFields.mContentType =
174 GetFieldIDOrDie(env, audioAttributesClass, "mContentType", "I");
175 gAudioAttributesFields.mFlags = GetFieldIDOrDie(env, audioAttributesClass, "mFlags", "I");
176 gAudioAttributesFields.mFormattedTags =
177 GetFieldIDOrDie(env, audioAttributesClass, "mFormattedTags", "Ljava/lang/String;");
178
179 jclass audioAttributesBuilderClass = FindClassOrDie(
180 env, "android/media/AudioAttributes$Builder");
181 gAudioAttributesBuilderClass = MakeGlobalRefOrDie(env, audioAttributesBuilderClass);
182 gAudioAttributesBuilderCstor = GetMethodIDOrDie(
183 env, audioAttributesBuilderClass, "<init>", "()V");
184 gAudioAttributesBuilderMethods.build = GetMethodIDOrDie(
185 env, audioAttributesBuilderClass, "build", "()Landroid/media/AudioAttributes;");
186 gAudioAttributesBuilderMethods.setUsage = GetMethodIDOrDie(
187 env, audioAttributesBuilderClass, "setUsage",
188 "(I)Landroid/media/AudioAttributes$Builder;");
189 gAudioAttributesBuilderMethods.setInternalCapturePreset = GetMethodIDOrDie(
190 env, audioAttributesBuilderClass, "setInternalCapturePreset",
191 "(I)Landroid/media/AudioAttributes$Builder;");
192 gAudioAttributesBuilderMethods.setContentType = GetMethodIDOrDie(
193 env, audioAttributesBuilderClass, "setContentType",
194 "(I)Landroid/media/AudioAttributes$Builder;");
195 gAudioAttributesBuilderMethods.setFlags = GetMethodIDOrDie(
196 env, audioAttributesBuilderClass, "setFlags",
197 "(I)Landroid/media/AudioAttributes$Builder;");
198 gAudioAttributesBuilderMethods.addTag = GetMethodIDOrDie(
199 env, audioAttributesBuilderClass, "addTag",
200 "(Ljava/lang/String;)Landroid/media/AudioAttributes$Builder;");
201
202 env->DeleteLocalRef(audioAttributesClass);
203
204 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
205 }
206