AudioSystem JNI: Add support for spatializer APIs
Add support for the following APIs in AudioSystem JNI: - getSpatializer - canBeSpatialized Bug: 188502620 Test: make Change-Id: I1942edc6c9fec3babfe870586f7a014d55b1ce70
This commit is contained in:
parent
03adaa2230
commit
8500f6c136
@ -341,6 +341,8 @@ java_defaults {
|
||||
"modules-utils-preconditions",
|
||||
"modules-utils-os",
|
||||
"framework-permission-aidl-java",
|
||||
"spatializer-aidl-java",
|
||||
"audiopolicy-types-aidl-java",
|
||||
],
|
||||
}
|
||||
|
||||
|
@ -243,6 +243,8 @@ cc_library_shared {
|
||||
shared_libs: [
|
||||
"audioclient-types-aidl-cpp",
|
||||
"audioflinger-aidl-cpp",
|
||||
"audiopolicy-types-aidl-cpp",
|
||||
"spatializer-aidl-cpp",
|
||||
"av-types-aidl-cpp",
|
||||
"android.hardware.camera.device@3.2",
|
||||
"libandroidicu",
|
||||
|
@ -24,6 +24,11 @@ using namespace android;
|
||||
|
||||
static jclass gAudioDeviceAttributesClass;
|
||||
static jmethodID gAudioDeviceAttributesCstor;
|
||||
static struct {
|
||||
jfieldID mAddress;
|
||||
jfieldID mNativeType;
|
||||
// other fields unused by JNI
|
||||
} gAudioDeviceAttributesFields;
|
||||
|
||||
namespace android {
|
||||
|
||||
@ -33,12 +38,25 @@ jint createAudioDeviceAttributesFromNative(JNIEnv *env, jobject *jAudioDeviceAtt
|
||||
jint jNativeType = (jint)devTypeAddr->mType;
|
||||
ScopedLocalRef<jstring> jAddress(env, env->NewStringUTF(devTypeAddr->getAddress()));
|
||||
|
||||
*jAudioDeviceAttributes = env->NewObject(gAudioDeviceAttributesClass, gAudioDeviceAttributesCstor,
|
||||
jNativeType, jAddress.get());
|
||||
*jAudioDeviceAttributes =
|
||||
env->NewObject(gAudioDeviceAttributesClass, gAudioDeviceAttributesCstor,
|
||||
jNativeType, jAddress.get());
|
||||
|
||||
return jStatus;
|
||||
}
|
||||
|
||||
jint createAudioDeviceTypeAddrFromJava(JNIEnv *env, AudioDeviceTypeAddr *devTypeAddr,
|
||||
const jobject jAudioDeviceAttributes) {
|
||||
devTypeAddr->mType = (audio_devices_t)env->GetIntField(jAudioDeviceAttributes,
|
||||
gAudioDeviceAttributesFields.mNativeType);
|
||||
|
||||
jstring jAddress = (jstring)env->GetObjectField(jAudioDeviceAttributes,
|
||||
gAudioDeviceAttributesFields.mAddress);
|
||||
devTypeAddr->setAddress(ScopedUtfChars(env, jAddress).c_str());
|
||||
|
||||
return AUDIO_JAVA_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
int register_android_media_AudioDeviceAttributes(JNIEnv *env) {
|
||||
@ -48,5 +66,10 @@ int register_android_media_AudioDeviceAttributes(JNIEnv *env) {
|
||||
gAudioDeviceAttributesCstor =
|
||||
GetMethodIDOrDie(env, audioDeviceTypeAddressClass, "<init>", "(ILjava/lang/String;)V");
|
||||
|
||||
gAudioDeviceAttributesFields.mNativeType =
|
||||
GetFieldIDOrDie(env, gAudioDeviceAttributesClass, "mNativeType", "I");
|
||||
gAudioDeviceAttributesFields.mAddress =
|
||||
GetFieldIDOrDie(env, gAudioDeviceAttributesClass, "mAddress", "Ljava/lang/String;");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -28,6 +28,9 @@ namespace android {
|
||||
|
||||
extern jint createAudioDeviceAttributesFromNative(JNIEnv *env, jobject *jAudioDeviceAttributes,
|
||||
const AudioDeviceTypeAddr *devTypeAddr);
|
||||
|
||||
extern jint createAudioDeviceTypeAddrFromJava(JNIEnv *env, AudioDeviceTypeAddr *devTypeAddr,
|
||||
const jobject jAudioDeviceAttributes);
|
||||
} // namespace android
|
||||
|
||||
#endif
|
@ -27,6 +27,8 @@
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
#include <android/media/AudioVibratorInfo.h>
|
||||
#include <android/media/INativeSpatializerCallback.h>
|
||||
#include <android/media/ISpatializer.h>
|
||||
#include <audiomanager/AudioManager.h>
|
||||
#include <media/AudioPolicy.h>
|
||||
#include <media/AudioSystem.h>
|
||||
@ -2023,6 +2025,18 @@ android_media_AudioSystem_registerRoutingCallback(JNIEnv *env, jobject thiz)
|
||||
AudioSystem::setRoutingCallback(android_media_AudioSystem_routing_callback);
|
||||
}
|
||||
|
||||
void javaAudioFormatToNativeAudioConfig(JNIEnv *env, audio_config_t *nConfig,
|
||||
const jobject jFormat, bool isInput) {
|
||||
*nConfig = AUDIO_CONFIG_INITIALIZER;
|
||||
nConfig->format = audioFormatToNative(env->GetIntField(jFormat, gAudioFormatFields.mEncoding));
|
||||
nConfig->sample_rate = env->GetIntField(jFormat, gAudioFormatFields.mSampleRate);
|
||||
jint jChannelMask = env->GetIntField(jFormat, gAudioFormatFields.mChannelMask);
|
||||
if (isInput) {
|
||||
nConfig->channel_mask = inChannelMaskToNative(jChannelMask);
|
||||
} else {
|
||||
nConfig->channel_mask = outChannelMaskToNative(jChannelMask);
|
||||
}
|
||||
}
|
||||
|
||||
static jint convertAudioMixToNative(JNIEnv *env,
|
||||
AudioMix *nAudioMix,
|
||||
@ -2043,13 +2057,7 @@ static jint convertAudioMixToNative(JNIEnv *env,
|
||||
nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
|
||||
|
||||
jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
|
||||
nAudioMix->mFormat = AUDIO_CONFIG_INITIALIZER;
|
||||
nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat,
|
||||
gAudioFormatFields.mSampleRate);
|
||||
nAudioMix->mFormat.channel_mask = outChannelMaskToNative(env->GetIntField(jFormat,
|
||||
gAudioFormatFields.mChannelMask));
|
||||
nAudioMix->mFormat.format = audioFormatToNative(env->GetIntField(jFormat,
|
||||
gAudioFormatFields.mEncoding));
|
||||
javaAudioFormatToNativeAudioConfig(env, &nAudioMix->mFormat, jFormat, false /*isInput*/);
|
||||
env->DeleteLocalRef(jFormat);
|
||||
|
||||
jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
|
||||
@ -2712,6 +2720,58 @@ static jint android_media_AudioSystem_setVibratorInfos(JNIEnv *env, jobject thiz
|
||||
return (jint)check_AudioSystem_Command(AudioSystem::setVibratorInfos(vibratorInfos));
|
||||
}
|
||||
|
||||
static jobject android_media_AudioSystem_getSpatializer(JNIEnv *env, jobject thiz,
|
||||
jobject jISpatializerCallback) {
|
||||
sp<media::INativeSpatializerCallback> nISpatializerCallback
|
||||
= interface_cast<media::INativeSpatializerCallback>(
|
||||
ibinderForJavaObject(env, jISpatializerCallback));
|
||||
sp<media::ISpatializer> nSpatializer;
|
||||
status_t status = AudioSystem::getSpatializer(nISpatializerCallback,
|
||||
&nSpatializer);
|
||||
if (status != NO_ERROR) {
|
||||
return nullptr;
|
||||
}
|
||||
return javaObjectForIBinder(env, IInterface::asBinder(nSpatializer));
|
||||
}
|
||||
|
||||
static jboolean android_media_AudioSystem_canBeSpatialized(JNIEnv *env, jobject thiz,
|
||||
jobject jaa, jobject jFormat,
|
||||
jobjectArray jDeviceArray) {
|
||||
JNIAudioAttributeHelper::UniqueAaPtr paa = JNIAudioAttributeHelper::makeUnique();
|
||||
jint jStatus = JNIAudioAttributeHelper::nativeFromJava(env, jaa, paa.get());
|
||||
if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioDeviceTypeAddrVector nDevices;
|
||||
|
||||
const size_t numDevices = env->GetArrayLength(jDeviceArray);
|
||||
for (size_t i = 0; i < numDevices; ++i) {
|
||||
AudioDeviceTypeAddr device;
|
||||
jobject jDevice = env->GetObjectArrayElement(jDeviceArray, i);
|
||||
if (jDevice == nullptr) {
|
||||
return false;
|
||||
}
|
||||
jStatus = createAudioDeviceTypeAddrFromJava(env, &device, jDevice);
|
||||
if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
nDevices.push_back(device);
|
||||
}
|
||||
|
||||
audio_config_t nConfig;
|
||||
javaAudioFormatToNativeAudioConfig(env, &nConfig, jFormat, false /*isInput*/);
|
||||
|
||||
bool canBeSpatialized;
|
||||
status_t status =
|
||||
AudioSystem::canBeSpatialized(paa.get(), &nConfig, nDevices, &canBeSpatialized);
|
||||
if (status != NO_ERROR) {
|
||||
ALOGW("%s native returned error %d", __func__, status);
|
||||
return false;
|
||||
}
|
||||
return canBeSpatialized;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static const JNINativeMethod gMethods[] =
|
||||
@ -2848,7 +2908,15 @@ static const JNINativeMethod gMethods[] =
|
||||
(void *)android_media_AudioSystem_removeUserIdDeviceAffinities},
|
||||
{"setCurrentImeUid", "(I)I", (void *)android_media_AudioSystem_setCurrentImeUid},
|
||||
{"setVibratorInfos", "(Ljava/util/List;)I",
|
||||
(void *)android_media_AudioSystem_setVibratorInfos}};
|
||||
(void *)android_media_AudioSystem_setVibratorInfos},
|
||||
{"nativeGetSpatializer",
|
||||
"(Landroid/media/INativeSpatializerCallback;)Landroid/os/IBinder;",
|
||||
(void *)android_media_AudioSystem_getSpatializer},
|
||||
{"canBeSpatialized",
|
||||
"(Landroid/media/AudioAttributes;Landroid/media/AudioFormat;"
|
||||
"[Landroid/media/AudioDeviceAttributes;)Z",
|
||||
(void *)android_media_AudioSystem_canBeSpatialized}};
|
||||
|
||||
|
||||
static const JNINativeMethod gEventHandlerMethods[] = {
|
||||
{"native_setup",
|
||||
|
@ -18,6 +18,7 @@ package android.media;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.TestApi;
|
||||
import android.bluetooth.BluetoothCodecConfig;
|
||||
@ -2000,6 +2001,46 @@ public class AudioSystem
|
||||
*/
|
||||
public static native int setVibratorInfos(@NonNull List<Vibrator> vibrators);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* If a spatializer effect is present on the platform, this will return an
|
||||
* ISpatializer interface to control this feature.
|
||||
* If no spatializer is present, a null interface is returned.
|
||||
* The INativeSpatializerCallback passed must not be null.
|
||||
* Only one ISpatializer interface can exist at a given time. The native audio policy
|
||||
* service will reject the request if an interface was already acquired and previous owner
|
||||
* did not die or call ISpatializer.release().
|
||||
* @param callback the callback to receive state updates if the ISpatializer
|
||||
* interface is acquired.
|
||||
* @return the ISpatializer interface made available to control the
|
||||
* platform spatializer
|
||||
*/
|
||||
@Nullable
|
||||
public static ISpatializer getSpatializer(INativeSpatializerCallback callback) {
|
||||
return ISpatializer.Stub.asInterface(nativeGetSpatializer(callback));
|
||||
}
|
||||
private static native IBinder nativeGetSpatializer(INativeSpatializerCallback callback);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Queries if some kind of spatialization will be performed if the audio playback context
|
||||
* described by the provided arguments is present.
|
||||
* The context is made of:
|
||||
* - The audio attributes describing the playback use case.
|
||||
* - The audio configuration describing the audio format, channels, sampling rate ...
|
||||
* - The devices describing the sink audio device selected for playback.
|
||||
* All arguments are optional and only the specified arguments are used to match against
|
||||
* supported criteria. For instance, supplying no argument will tell if spatialization is
|
||||
* supported or not in general.
|
||||
* @param attributes audio attributes describing the playback use case
|
||||
* @param format audio configuration describing the audio format, channels, sampling rate...
|
||||
* @param devices the sink audio device selected for playback
|
||||
* @return true if spatialization is enabled for this context, false otherwise.
|
||||
*/
|
||||
public static native boolean canBeSpatialized(AudioAttributes attributes,
|
||||
AudioFormat format,
|
||||
AudioDeviceAttributes[] devices);
|
||||
|
||||
// Items shared with audio service
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user