blob: b616ffc111a3b11af1ef1046b9f784e312e3a06e [file] [log] [blame]
François Gaffieb4691282018-07-09 13:07:32 +02001/*
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
37using namespace android;
38
39// ----------------------------------------------------------------------------
40static const char* const kClassPathName = "android/media/AudioAttributes";
41
42static jclass gAudioAttributesClass;
43static 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
Hayden Gomes62812aa2019-12-23 11:40:27 -080051static struct { jmethodID isSystemUsage; } gAudioAttributesClassMethods;
Hayden Gomesfe2c8772019-12-23 11:37:23 -080052
François Gaffieb4691282018-07-09 13:07:32 +020053static jclass gAudioAttributesBuilderClass;
54static jmethodID gAudioAttributesBuilderCstor;
55static struct {
56 jmethodID build;
57 jmethodID setUsage;
Hayden Gomesfe2c8772019-12-23 11:37:23 -080058 jmethodID setSystemUsage;
François Gaffieb4691282018-07-09 13:07:32 +020059 jmethodID setInternalCapturePreset;
60 jmethodID setContentType;
61 jmethodID setFlags;
62 jmethodID addTag;
63} gAudioAttributesBuilderMethods;
64
65
66static jint nativeAudioAttributesFromJavaAudioAttributes(
67 JNIEnv* env, jobject jAudioAttributes, audio_attributes_t *aa)
68{
69 if (env == nullptr) {
70 return AUDIO_JAVA_DEAD_OBJECT;
71 }
72 if (jAudioAttributes == nullptr) {
73 ALOGE("Invalid AudioAttributes java object");
74 return (jint)AUDIO_JAVA_BAD_VALUE;
75 }
76 if (!env->IsInstanceOf(jAudioAttributes, gAudioAttributesClass)) {
77 return (jint)AUDIO_JAVA_BAD_VALUE;
78 }
79 const jstring jtags =
80 (jstring) env->GetObjectField(jAudioAttributes, gAudioAttributesFields.mFormattedTags);
81 if (jtags == nullptr) {
82 return AUDIO_JAVA_NO_INIT;
83 }
84 const char* tags = env->GetStringUTFChars(jtags, NULL);
85 // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
86 strncpy(aa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
87 env->ReleaseStringUTFChars(jtags, tags);
88
89 // Record ?
90 aa->source = (audio_source_t) env->GetIntField(jAudioAttributes,
91 gAudioAttributesFields.mSource);
92 // Track ?
93 aa->usage = (audio_usage_t) env->GetIntField(jAudioAttributes, gAudioAttributesFields.mUsage);
94
95 aa->content_type =
96 (audio_content_type_t) env->GetIntField(jAudioAttributes,
97 gAudioAttributesFields.mContentType);
98
99 aa->flags = (audio_flags_mask_t)env->GetIntField(jAudioAttributes,
100 gAudioAttributesFields.mFlags);
101
102 ALOGV("AudioAttributes for usage=%d content=%d source=%d tags=%s flags=%08x tags=%s",
103 aa->usage, aa->content_type, aa->source, aa->tags, aa->flags, aa->tags);
104 return (jint)AUDIO_JAVA_SUCCESS;
105}
106
107static jint nativeAudioAttributesToJavaAudioAttributes(
108 JNIEnv* env, jobject *jAudioAttributes, const audio_attributes_t &attributes)
109{
110 ScopedLocalRef<jobject> jAttributeBuilder(env, env->NewObject(gAudioAttributesBuilderClass,
111 gAudioAttributesBuilderCstor));
112 if (jAttributeBuilder.get() == nullptr) {
113 return (jint)AUDIO_JAVA_ERROR;
114 }
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800115
116 const bool isSystemUsage = env->CallStaticBooleanMethod(gAudioAttributesClass,
117 gAudioAttributesClassMethods.isSystemUsage,
118 attributes.usage);
119 if (isSystemUsage) {
120 env->CallObjectMethod(jAttributeBuilder.get(),
Hayden Gomes62812aa2019-12-23 11:40:27 -0800121 gAudioAttributesBuilderMethods.setSystemUsage, attributes.usage);
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800122 } else {
Hayden Gomes62812aa2019-12-23 11:40:27 -0800123 env->CallObjectMethod(jAttributeBuilder.get(), gAudioAttributesBuilderMethods.setUsage,
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800124 attributes.usage);
125 }
François Gaffieb4691282018-07-09 13:07:32 +0200126 env->CallObjectMethod(jAttributeBuilder.get(),
127 gAudioAttributesBuilderMethods.setInternalCapturePreset,
128 attributes.source);
129 env->CallObjectMethod(jAttributeBuilder.get(),
130 gAudioAttributesBuilderMethods.setContentType,
131 attributes.content_type);
132 env->CallObjectMethod(jAttributeBuilder.get(),
133 gAudioAttributesBuilderMethods.setFlags,
134 attributes.flags);
135 env->CallObjectMethod(jAttributeBuilder.get(),
136 gAudioAttributesBuilderMethods.addTag,
137 env->NewStringUTF(attributes.tags));
138
139 *jAudioAttributes = env->CallObjectMethod(jAttributeBuilder.get(),
140 gAudioAttributesBuilderMethods.build);
141 return (jint)AUDIO_JAVA_SUCCESS;
142}
143
144// ----------------------------------------------------------------------------
145JNIAudioAttributeHelper::UniqueAaPtr JNIAudioAttributeHelper::makeUnique()
146{
147 audio_attributes_t *aa = new (calloc(1, sizeof(audio_attributes_t)))
148 audio_attributes_t{AUDIO_ATTRIBUTES_INITIALIZER};
George Burgess IV20d18962019-01-29 19:30:40 -0800149 return UniqueAaPtr{aa};
François Gaffieb4691282018-07-09 13:07:32 +0200150}
151
152jint JNIAudioAttributeHelper::nativeFromJava(JNIEnv* env, jobject jAudioAttributes,
153 audio_attributes_t *paa)
154{
155 return nativeAudioAttributesFromJavaAudioAttributes(env, jAudioAttributes, paa);
156}
157
158jint JNIAudioAttributeHelper::nativeToJava(
159 JNIEnv* env, jobject *jAudioAttributes, const audio_attributes_t &attributes)
160{
161 return nativeAudioAttributesToJavaAudioAttributes(env, jAudioAttributes, attributes);
162}
163
164jint JNIAudioAttributeHelper::getJavaArray(
165 JNIEnv* env, jobjectArray *jAudioAttributeArray, jint numAudioAttributes)
166{
167 *jAudioAttributeArray = env->NewObjectArray(numAudioAttributes, gAudioAttributesClass, NULL);
Greg Kaiser2df731cf2019-01-29 06:37:11 -0800168 return *jAudioAttributeArray == NULL? (jint)AUDIO_JAVA_ERROR : (jint)AUDIO_JAVA_SUCCESS;
François Gaffieb4691282018-07-09 13:07:32 +0200169}
170
171/*
172 * JNI registration.
173 */
174static const JNINativeMethod gMethods[] = {
175 // n/a
176};
177
178int register_android_media_AudioAttributes(JNIEnv *env)
179{
180 jclass audioAttributesClass = FindClassOrDie(env, kClassPathName);
181 gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
Hayden Gomes62812aa2019-12-23 11:40:27 -0800182 gAudioAttributesClassMethods.isSystemUsage =
183 GetStaticMethodIDOrDie(env, gAudioAttributesClass, "isSystemUsage", "(I)Z");
Hayden Gomesfe2c8772019-12-23 11:37:23 -0800184
François Gaffieb4691282018-07-09 13:07:32 +0200185 gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
186 gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
187 gAudioAttributesFields.mContentType =
188 GetFieldIDOrDie(env, audioAttributesClass, "mContentType", "I");
189 gAudioAttributesFields.mFlags = GetFieldIDOrDie(env, audioAttributesClass, "mFlags", "I");
190 gAudioAttributesFields.mFormattedTags =
191 GetFieldIDOrDie(env, audioAttributesClass, "mFormattedTags", "Ljava/lang/String;");
192
193 jclass audioAttributesBuilderClass = FindClassOrDie(
194 env, "android/media/AudioAttributes$Builder");
195 gAudioAttributesBuilderClass = MakeGlobalRefOrDie(env, audioAttributesBuilderClass);
196 gAudioAttributesBuilderCstor = GetMethodIDOrDie(
197 env, audioAttributesBuilderClass, "<init>", "()V");
198 gAudioAttributesBuilderMethods.build = GetMethodIDOrDie(
199 env, audioAttributesBuilderClass, "build", "()Landroid/media/AudioAttributes;");
200 gAudioAttributesBuilderMethods.setUsage = GetMethodIDOrDie(
201 env, audioAttributesBuilderClass, "setUsage",
202 "(I)Landroid/media/AudioAttributes$Builder;");
Hayden Gomes62812aa2019-12-23 11:40:27 -0800203 gAudioAttributesBuilderMethods.setSystemUsage =
204 GetMethodIDOrDie(env, audioAttributesBuilderClass, "setSystemUsage",
205 "(I)Landroid/media/AudioAttributes$Builder;");
François Gaffieb4691282018-07-09 13:07:32 +0200206 gAudioAttributesBuilderMethods.setInternalCapturePreset = GetMethodIDOrDie(
207 env, audioAttributesBuilderClass, "setInternalCapturePreset",
208 "(I)Landroid/media/AudioAttributes$Builder;");
209 gAudioAttributesBuilderMethods.setContentType = GetMethodIDOrDie(
210 env, audioAttributesBuilderClass, "setContentType",
211 "(I)Landroid/media/AudioAttributes$Builder;");
212 gAudioAttributesBuilderMethods.setFlags = GetMethodIDOrDie(
213 env, audioAttributesBuilderClass, "setFlags",
214 "(I)Landroid/media/AudioAttributes$Builder;");
215 gAudioAttributesBuilderMethods.addTag = GetMethodIDOrDie(
216 env, audioAttributesBuilderClass, "addTag",
217 "(Ljava/lang/String;)Landroid/media/AudioAttributes$Builder;");
218
219 env->DeleteLocalRef(audioAttributesClass);
220
221 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
222}