blob: 7098451901c42fd13e1a3d0d2f6994c63c056d3e [file] [log] [blame]
François Gaffieadcd00a2018-09-18 17:06:26 +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 "AudioVolumeGroups-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 <media/AudioSystem.h>
30#include <media/AudioPolicy.h>
31
32#include <nativehelper/ScopedUtfChars.h>
33
34#include "android_media_AudioAttributes.h"
35#include "android_media_AudioErrors.h"
36
37// ----------------------------------------------------------------------------
38
39using namespace android;
40
41// ----------------------------------------------------------------------------
Hayden Gomesebd6aaa2019-04-04 13:14:21 -070042static const char* const kClassPathName = "android/media/audiopolicy/AudioVolumeGroup";
François Gaffieadcd00a2018-09-18 17:06:26 +020043static const char* const kAudioVolumeGroupClassPathName =
44 "android/media/audiopolicy/AudioVolumeGroup";
45
46static jclass gAudioVolumeGroupClass;
47static jmethodID gAudioVolumeGroupCstor;
48static struct {
49 jfieldID mName;
50 jfieldID mId;
51} gAudioVolumeGroupFields;
52
53static jclass gArrayListClass;
54static jmethodID gArrayListCstor;
55static struct {
56 jmethodID add;
57 jmethodID toArray;
58} gArrayListMethods;
59
60
61static jint convertAudioVolumeGroupsFromNative(
62 JNIEnv *env, jobject *jGroup, const AudioVolumeGroup &group)
63{
64 jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
65 jstring jName = NULL;
66 jint Id = NULL;
67
68 jintArray jLegacyStreamTypes = NULL;
69 jobjectArray jAudioAttributes = NULL;
70 jint numAttributes;
71 jobject jAudioAttribute = NULL;
72
73 jName = env->NewStringUTF(group.getName().c_str());
74 Id = static_cast<jint>(group.getId());
75
76 // Legacy stream types array
77 jLegacyStreamTypes = env->NewIntArray(group.getStreamTypes().size());
78 if (jLegacyStreamTypes == NULL) {
79 jStatus = (jint)AUDIO_JAVA_ERROR;
80 goto exit;
81 }
82 for (size_t streamIndex = 0; streamIndex < group.getStreamTypes().size(); streamIndex++) {
83 jint jStream = group.getStreamTypes()[streamIndex];
84 env->SetIntArrayRegion(jLegacyStreamTypes, streamIndex, 1, &jStream);
85 }
86
87 // Audio Attributes array
88 numAttributes = group.getAudioAttributes().size();
89 jStatus = JNIAudioAttributeHelper::getJavaArray(env, &jAudioAttributes, numAttributes);
90 if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
91 goto exit;
92 }
93
94 for (size_t j = 0; j < static_cast<size_t>(numAttributes); j++) {
95 auto attributes = group.getAudioAttributes()[j];
96
97 jStatus = JNIAudioAttributeHelper::nativeToJava(env, &jAudioAttribute, attributes);
98 if (jStatus != AUDIO_JAVA_SUCCESS) {
99 goto exit;
100 }
101 env->SetObjectArrayElement(jAudioAttributes, j, jAudioAttribute);
102 }
103
104 *jGroup = env->NewObject(gAudioVolumeGroupClass, gAudioVolumeGroupCstor,
105 jName, Id, jAudioAttributes, jLegacyStreamTypes);
106exit:
107 if (jName != NULL) {
108 env->DeleteLocalRef(jName);
109 }
110 return jStatus;
111}
112
113static jint
114android_media_AudioSystem_listAudioVolumeGroups(JNIEnv *env, jobject clazz, jobject jVolumeGroups)
115{
116 if (env == NULL) {
117 return AUDIO_JAVA_DEAD_OBJECT;
118 }
119 if (jVolumeGroups == NULL) {
120 ALOGE("listAudioVolumeGroups NULL AudioVolumeGroups");
121 return (jint)AUDIO_JAVA_BAD_VALUE;
122 }
123 if (!env->IsInstanceOf(jVolumeGroups, gArrayListClass)) {
124 ALOGE("listAudioVolumeGroups not an arraylist");
125 return (jint)AUDIO_JAVA_BAD_VALUE;
126 }
127
128 status_t status;
129 AudioVolumeGroupVector groups;
130 jint jStatus;
131 jobject jGroup = NULL;
132
133 status = AudioSystem::listAudioVolumeGroups(groups);
134 if (status != NO_ERROR) {
135 ALOGE("AudioSystem::listAudioVolumeGroups error %d", status);
136 return nativeToJavaStatus(status);
137 }
138 for (const auto &group : groups) {
139 jStatus = convertAudioVolumeGroupsFromNative(env, &jGroup, group);
140 if (jStatus != AUDIO_JAVA_SUCCESS) {
141 goto exit;
142 }
143 env->CallBooleanMethod(jVolumeGroups, gArrayListMethods.add, jGroup);
144 }
145exit:
146 if (jGroup != NULL) {
147 env->DeleteLocalRef(jGroup);
148 }
149 return jStatus;
150}
151
152/*
153 * JNI registration.
154 */
155static const JNINativeMethod gMethods[] = {
156 {"native_list_audio_volume_groups", "(Ljava/util/ArrayList;)I",
157 (void *)android_media_AudioSystem_listAudioVolumeGroups},
158};
159
160int register_android_media_AudioVolumeGroups(JNIEnv *env)
161{
162 jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
163 gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
164 gArrayListCstor = GetMethodIDOrDie(env, arrayListClass, "<init>", "()V");
165 gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
166 gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass,
167 "toArray", "()[Ljava/lang/Object;");
168
169 jclass audioVolumeGroupClass = FindClassOrDie(env, kAudioVolumeGroupClassPathName);
170 gAudioVolumeGroupClass = MakeGlobalRefOrDie(env, audioVolumeGroupClass);
171 gAudioVolumeGroupCstor = GetMethodIDOrDie(
172 env, audioVolumeGroupClass, "<init>",
173 "(Ljava/lang/String;I[Landroid/media/AudioAttributes;[I)V");
174
175 gAudioVolumeGroupFields.mName = GetFieldIDOrDie(
176 env, audioVolumeGroupClass, "mName", "Ljava/lang/String;");
177 gAudioVolumeGroupFields.mId = GetFieldIDOrDie(
178 env, audioVolumeGroupClass, "mId", "I");
179
180 env->DeleteLocalRef(audioVolumeGroupClass);
181
182 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
183}