Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6e13284 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add Introspection API to retrieve AudioProductStrategies"

parents 4e7129df c01fa3a7
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -3629,6 +3629,28 @@ package android.media.audiopolicy {
    method public android.media.audiopolicy.AudioPolicy.Builder setLooper(@NonNull android.os.Looper) throws java.lang.IllegalArgumentException;
  }
  public final class AudioProductStrategies implements java.lang.Iterable<android.media.audiopolicy.AudioProductStrategy> android.os.Parcelable {
    ctor public AudioProductStrategies();
    method public int describeContents();
    method @NonNull public android.media.AudioAttributes getAudioAttributesForLegacyStreamType(int);
    method @NonNull public android.media.AudioAttributes getAudioAttributesForProductStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
    method @Nullable public android.media.audiopolicy.AudioProductStrategy getById(int);
    method public int getLegacyStreamTypeForAudioAttributes(@NonNull android.media.AudioAttributes);
    method public java.util.Iterator<android.media.audiopolicy.AudioProductStrategy> iterator();
    method public int size();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioProductStrategies> CREATOR;
  }
  public final class AudioProductStrategy implements android.os.Parcelable {
    method public int describeContents();
    method @NonNull public android.media.AudioAttributes getAudioAttributes();
    method public int getId();
    method @NonNull public String name();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioProductStrategy> CREATOR;
  }
}
package android.media.session {
+1 −0
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@ cc_library_shared {
        "android_media_AudioSystem.cpp",
        "android_media_AudioTrack.cpp",
        "android_media_AudioAttributes.cpp",
        "android_media_AudioProductStrategies.cpp",
        "android_media_DeviceCallback.cpp",
        "android_media_JetPlayer.cpp",
        "android_media_MediaMetricsJNI.cpp",
+2 −0
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ extern int register_android_media_AudioRecord(JNIEnv *env);
extern int register_android_media_AudioSystem(JNIEnv *env);
extern int register_android_media_AudioTrack(JNIEnv *env);
extern int register_android_media_AudioAttributes(JNIEnv *env);
extern int register_android_media_AudioProductStrategies(JNIEnv *env);
extern int register_android_media_MicrophoneInfo(JNIEnv *env);
extern int register_android_media_JetPlayer(JNIEnv *env);
extern int register_android_media_ToneGenerator(JNIEnv *env);
@@ -1495,6 +1496,7 @@ static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_android_media_AudioRecord),
    REG_JNI(register_android_media_AudioTrack),
    REG_JNI(register_android_media_AudioAttributes),
    REG_JNI(register_android_media_AudioProductStrategies),
    REG_JNI(register_android_media_JetPlayer),
    REG_JNI(register_android_media_MicrophoneInfo),
    REG_JNI(register_android_media_RemoteDisplay),
+242 −0
Original line number Diff line number Diff line
/*
 * 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 "AudioProductStrategies-JNI"

#include <inttypes.h>
#include <jni.h>
#include <nativehelper/JNIHelp.h>
#include "core_jni_helpers.h"

#include <utils/Log.h>
#include <vector>

#include <media/AudioSystem.h>
#include <media/AudioPolicy.h>

#include <nativehelper/ScopedUtfChars.h>

#include "android_media_AudioAttributes.h"
#include "android_media_AudioErrors.h"

// ----------------------------------------------------------------------------

using namespace android;

// ----------------------------------------------------------------------------
static const char* const kClassPathName = "android/media/audiopolicy/AudioProductStrategies";
static const char* const kAudioProductStrategyClassPathName =
        "android/media/audiopolicy/AudioProductStrategy";

static const char* const kAudioAttributesGroupsClassPathName =
        "android/media/audiopolicy/AudioProductStrategy$AudioAttributesGroup";

static jclass gAudioProductStrategyClass;
static jmethodID gAudioProductStrategyCstor;
static struct {
    jfieldID    mAudioAttributesGroups;
    jfieldID    mName;
    jfieldID    mId;
} gAudioProductStrategyFields;

static jclass gAudioAttributesGroupClass;
static jmethodID gAudioAttributesGroupCstor;
static struct {
    jfieldID    mGroupId;
    jfieldID    mLegacyStreamType;
    jfieldID    mAudioAttributes;
} gAudioAttributesGroupsFields;

static jclass gArrayListClass;
static struct {
    jmethodID    add;
    jmethodID    toArray;
} gArrayListMethods;


static jint convertAudioProductStrategiesFromNative(
        JNIEnv *env, jobject *jAudioStrategy, const AudioProductStrategy &strategy)
{
    jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
    jobjectArray jAudioAttributesGroups = NULL;
    jobjectArray jAudioAttributes = NULL;
    jobject jAudioAttribute = NULL;
    jstring jName = NULL;
    jint jStrategyId = NULL;
    jint numAttributesGroups;
    size_t indexGroup = 0;

    jName = env->NewStringUTF(strategy.getName().c_str());
    jStrategyId = static_cast<jint>(strategy.getId());

    // Audio Attributes Group array
    std::map<int, std::vector<AudioAttributes> > groups;
    for (const auto &attr : strategy.getAudioAttributes()) {
        int attrGroupId = attr.getGroupId();
        groups[attrGroupId].push_back(attr);
    }
    numAttributesGroups = groups.size();

    jAudioAttributesGroups = env->NewObjectArray(numAttributesGroups, gAudioAttributesGroupClass, NULL);

    for (const auto &iter : groups) {
        std::vector<AudioAttributes> audioAttributesGroups = iter.second;
        jint numAttributes = audioAttributesGroups.size();
        jint jGroupId = iter.first;
        jint jLegacyStreamType = audioAttributesGroups.front().getStreamType();

        jStatus = JNIAudioAttributeHelper::getJavaArray(env, &jAudioAttributes, numAttributes);
        if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
            goto exit;
        }
        for (size_t j = 0; j < static_cast<size_t>(numAttributes); j++) {
            auto attributes = audioAttributesGroups[j].getAttributes();

            jStatus = JNIAudioAttributeHelper::nativeToJava(env, &jAudioAttribute, attributes);
            if (jStatus != AUDIO_JAVA_SUCCESS) {
                goto exit;
            }
            env->SetObjectArrayElement(jAudioAttributes, j, jAudioAttribute);
        }
        jobject jAudioAttributesGroup = env->NewObject(gAudioAttributesGroupClass,
                                                       gAudioAttributesGroupCstor,
                                                       jGroupId,
                                                       jLegacyStreamType,
                                                       jAudioAttributes);
        env->SetObjectArrayElement(jAudioAttributesGroups, indexGroup++, jAudioAttributesGroup);

        if (jAudioAttributes != NULL) {
            env->DeleteLocalRef(jAudioAttributes);
            jAudioAttributes = NULL;
        }
        if (jAudioAttribute != NULL) {
            env->DeleteLocalRef(jAudioAttribute);
            jAudioAttribute = NULL;
        }
        if (jAudioAttributesGroup != NULL) {
            env->DeleteLocalRef(jAudioAttributesGroup);
            jAudioAttributesGroup = NULL;
        }
    }
    *jAudioStrategy = env->NewObject(gAudioProductStrategyClass, gAudioProductStrategyCstor,
                                     jName,
                                     jStrategyId,
                                     jAudioAttributesGroups);
exit:
    if (jAudioAttributes != NULL) {
        env->DeleteLocalRef(jAudioAttributes);
    }
    if (jAudioAttribute != NULL) {
        env->DeleteLocalRef(jAudioAttribute);
        jAudioAttribute = NULL;
    }
    if (jAudioAttributesGroups != NULL) {
        env->DeleteLocalRef(jAudioAttributesGroups);
    }
    if (jName != NULL) {
        env->DeleteLocalRef(jName);
    }
    return jStatus;
}

static jint
android_media_AudioSystem_listAudioProductStrategies(JNIEnv *env, jobject clazz,
                                                     jobject jStrategies)
{
    if (env == NULL) {
        return AUDIO_JAVA_DEAD_OBJECT;
    }
    if (jStrategies == NULL) {
        ALOGE("listAudioProductStrategies NULL AudioProductStrategies");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }
    if (!env->IsInstanceOf(jStrategies, gArrayListClass)) {
        ALOGE("listAudioProductStrategies not an arraylist");
        return (jint)AUDIO_JAVA_BAD_VALUE;
    }

    status_t status;
    AudioProductStrategyVector strategies;
    jint jStatus;
    jobject jStrategy = NULL;

    status = AudioSystem::listAudioProductStrategies(strategies);
    if (status != NO_ERROR) {
        ALOGE("AudioSystem::listAudioProductStrategies error %d", status);
        return nativeToJavaStatus(status);
    }
    for (const auto &strategy : strategies) {
        jStatus = convertAudioProductStrategiesFromNative(env, &jStrategy, strategy);
        if (jStatus != AUDIO_JAVA_SUCCESS) {
            goto exit;
        }
        env->CallBooleanMethod(jStrategies, gArrayListMethods.add, jStrategy);
    }
exit:
    if (jStrategy != NULL) {
        env->DeleteLocalRef(jStrategy);
    }
    return jStatus;
}

/*
 * JNI registration.
 */
static const JNINativeMethod gMethods[] = {
    {"native_list_audio_product_strategies", "(Ljava/util/ArrayList;)I",
                        (void *)android_media_AudioSystem_listAudioProductStrategies},
};

int register_android_media_AudioProductStrategies(JNIEnv *env)
{
    jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
    gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
    gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
    gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass,
                                                 "toArray", "()[Ljava/lang/Object;");

    jclass audioProductStrategyClass = FindClassOrDie(env, kAudioProductStrategyClassPathName);
    gAudioProductStrategyClass = MakeGlobalRefOrDie(env, audioProductStrategyClass);
    gAudioProductStrategyCstor = GetMethodIDOrDie(
                env, audioProductStrategyClass, "<init>",
                "(Ljava/lang/String;I[Landroid/media/audiopolicy/AudioProductStrategy$AudioAttributesGroup;)V");
    gAudioProductStrategyFields.mAudioAttributesGroups = GetFieldIDOrDie(
                env, audioProductStrategyClass, "mAudioAttributesGroups",
                "[Landroid/media/audiopolicy/AudioProductStrategy$AudioAttributesGroup;");
    gAudioProductStrategyFields.mName = GetFieldIDOrDie(
                env, audioProductStrategyClass, "mName", "Ljava/lang/String;");
    gAudioProductStrategyFields.mId = GetFieldIDOrDie(
                env, audioProductStrategyClass, "mId", "I");

    jclass audioAttributesGroupClass = FindClassOrDie(env, kAudioAttributesGroupsClassPathName);
    gAudioAttributesGroupClass = MakeGlobalRefOrDie(env, audioAttributesGroupClass);
    gAudioAttributesGroupCstor = GetMethodIDOrDie(env, audioAttributesGroupClass, "<init>",
                                                  "(II[Landroid/media/AudioAttributes;)V");
    gAudioAttributesGroupsFields.mGroupId = GetFieldIDOrDie(
                env, audioAttributesGroupClass, "mGroupId", "I");
    gAudioAttributesGroupsFields.mLegacyStreamType = GetFieldIDOrDie(
                env, audioAttributesGroupClass, "mLegacyStreamType", "I");
    gAudioAttributesGroupsFields.mAudioAttributes = GetFieldIDOrDie(
                env, audioAttributesGroupClass, "mAudioAttributes",
                "[Landroid/media/AudioAttributes;");

    env->DeleteLocalRef(audioProductStrategyClass);
    env->DeleteLocalRef(audioAttributesGroupClass);

    return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
+18 −0
Original line number Diff line number Diff line
/* Copyright 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.
*/

package android.media.audiopolicy;

parcelable AudioProductStrategies;
Loading