/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "AudioVolumeGroups-JNI" #include #include #include #include "core_jni_helpers.h" #include #include #include #include #include #include "android_media_AudioAttributes.h" #include "android_media_AudioErrors.h" // ---------------------------------------------------------------------------- using namespace android; // ---------------------------------------------------------------------------- static const char* const kClassPathName = "android/media/audiopolicy/AudioVolumeGroup"; static const char* const kAudioVolumeGroupClassPathName = "android/media/audiopolicy/AudioVolumeGroup"; static jclass gAudioVolumeGroupClass; static jmethodID gAudioVolumeGroupCstor; static struct { jfieldID mName; jfieldID mId; } gAudioVolumeGroupFields; static jclass gArrayListClass; static jmethodID gArrayListCstor; static struct { jmethodID add; jmethodID toArray; } gArrayListMethods; static jint convertAudioVolumeGroupsFromNative( JNIEnv *env, jobject *jGroup, const AudioVolumeGroup &group) { jint jStatus = (jint)AUDIO_JAVA_SUCCESS; jstring jName = NULL; jint Id = NULL; jintArray jLegacyStreamTypes = NULL; jobjectArray jAudioAttributes = NULL; jint numAttributes; jobject jAudioAttribute = NULL; jName = env->NewStringUTF(group.getName().c_str()); Id = static_cast(group.getId()); // Legacy stream types array jLegacyStreamTypes = env->NewIntArray(group.getStreamTypes().size()); if (jLegacyStreamTypes == NULL) { jStatus = (jint)AUDIO_JAVA_ERROR; goto exit; } for (size_t streamIndex = 0; streamIndex < group.getStreamTypes().size(); streamIndex++) { jint jStream = group.getStreamTypes()[streamIndex]; env->SetIntArrayRegion(jLegacyStreamTypes, streamIndex, 1, &jStream); } // Audio Attributes array numAttributes = group.getAudioAttributes().size(); jStatus = JNIAudioAttributeHelper::getJavaArray(env, &jAudioAttributes, numAttributes); if (jStatus != (jint)AUDIO_JAVA_SUCCESS) { goto exit; } for (size_t j = 0; j < static_cast(numAttributes); j++) { auto attributes = group.getAudioAttributes()[j]; jStatus = JNIAudioAttributeHelper::nativeToJava(env, &jAudioAttribute, attributes); if (jStatus != AUDIO_JAVA_SUCCESS) { goto exit; } env->SetObjectArrayElement(jAudioAttributes, j, jAudioAttribute); } *jGroup = env->NewObject(gAudioVolumeGroupClass, gAudioVolumeGroupCstor, jName, Id, jAudioAttributes, jLegacyStreamTypes); exit: if (jName != NULL) { env->DeleteLocalRef(jName); } return jStatus; } static jint android_media_AudioSystem_listAudioVolumeGroups(JNIEnv *env, jobject clazz, jobject jVolumeGroups) { if (env == NULL) { return AUDIO_JAVA_DEAD_OBJECT; } if (jVolumeGroups == NULL) { ALOGE("listAudioVolumeGroups NULL AudioVolumeGroups"); return (jint)AUDIO_JAVA_BAD_VALUE; } if (!env->IsInstanceOf(jVolumeGroups, gArrayListClass)) { ALOGE("listAudioVolumeGroups not an arraylist"); return (jint)AUDIO_JAVA_BAD_VALUE; } status_t status; AudioVolumeGroupVector groups; jint jStatus; jobject jGroup = NULL; status = AudioSystem::listAudioVolumeGroups(groups); if (status != NO_ERROR) { ALOGE("AudioSystem::listAudioVolumeGroups error %d", status); return nativeToJavaStatus(status); } for (const auto &group : groups) { jStatus = convertAudioVolumeGroupsFromNative(env, &jGroup, group); if (jStatus != AUDIO_JAVA_SUCCESS) { goto exit; } env->CallBooleanMethod(jVolumeGroups, gArrayListMethods.add, jGroup); } exit: if (jGroup != NULL) { env->DeleteLocalRef(jGroup); } return jStatus; } /* * JNI registration. */ static const JNINativeMethod gMethods[] = { {"native_list_audio_volume_groups", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioSystem_listAudioVolumeGroups}, }; int register_android_media_AudioVolumeGroups(JNIEnv *env) { jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList"); gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass); gArrayListCstor = GetMethodIDOrDie(env, arrayListClass, "", "()V"); gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z"); gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;"); jclass audioVolumeGroupClass = FindClassOrDie(env, kAudioVolumeGroupClassPathName); gAudioVolumeGroupClass = MakeGlobalRefOrDie(env, audioVolumeGroupClass); gAudioVolumeGroupCstor = GetMethodIDOrDie( env, audioVolumeGroupClass, "", "(Ljava/lang/String;I[Landroid/media/AudioAttributes;[I)V"); gAudioVolumeGroupFields.mName = GetFieldIDOrDie( env, audioVolumeGroupClass, "mName", "Ljava/lang/String;"); gAudioVolumeGroupFields.mId = GetFieldIDOrDie( env, audioVolumeGroupClass, "mId", "I"); env->DeleteLocalRef(audioVolumeGroupClass); return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); }