Merge "AudioSystem JNI: Add support for spatializer APIs" into sc-v2-dev am: 8c500d5882
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15557293 Change-Id: I32955fb8cdff488ed3cf1ec6a48f8f3173d05c91
This commit is contained in:
@@ -342,6 +342,8 @@ java_defaults {
|
|||||||
"modules-utils-preconditions",
|
"modules-utils-preconditions",
|
||||||
"modules-utils-os",
|
"modules-utils-os",
|
||||||
"framework-permission-aidl-java",
|
"framework-permission-aidl-java",
|
||||||
|
"spatializer-aidl-java",
|
||||||
|
"audiopolicy-types-aidl-java",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -243,6 +243,8 @@ cc_library_shared {
|
|||||||
shared_libs: [
|
shared_libs: [
|
||||||
"audioclient-types-aidl-cpp",
|
"audioclient-types-aidl-cpp",
|
||||||
"audioflinger-aidl-cpp",
|
"audioflinger-aidl-cpp",
|
||||||
|
"audiopolicy-types-aidl-cpp",
|
||||||
|
"spatializer-aidl-cpp",
|
||||||
"av-types-aidl-cpp",
|
"av-types-aidl-cpp",
|
||||||
"android.hardware.camera.device@3.2",
|
"android.hardware.camera.device@3.2",
|
||||||
"libandroidicu",
|
"libandroidicu",
|
||||||
|
|||||||
@@ -24,6 +24,11 @@ using namespace android;
|
|||||||
|
|
||||||
static jclass gAudioDeviceAttributesClass;
|
static jclass gAudioDeviceAttributesClass;
|
||||||
static jmethodID gAudioDeviceAttributesCstor;
|
static jmethodID gAudioDeviceAttributesCstor;
|
||||||
|
static struct {
|
||||||
|
jfieldID mAddress;
|
||||||
|
jfieldID mNativeType;
|
||||||
|
// other fields unused by JNI
|
||||||
|
} gAudioDeviceAttributesFields;
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
@@ -33,12 +38,25 @@ jint createAudioDeviceAttributesFromNative(JNIEnv *env, jobject *jAudioDeviceAtt
|
|||||||
jint jNativeType = (jint)devTypeAddr->mType;
|
jint jNativeType = (jint)devTypeAddr->mType;
|
||||||
ScopedLocalRef<jstring> jAddress(env, env->NewStringUTF(devTypeAddr->getAddress()));
|
ScopedLocalRef<jstring> jAddress(env, env->NewStringUTF(devTypeAddr->getAddress()));
|
||||||
|
|
||||||
*jAudioDeviceAttributes = env->NewObject(gAudioDeviceAttributesClass, gAudioDeviceAttributesCstor,
|
*jAudioDeviceAttributes =
|
||||||
|
env->NewObject(gAudioDeviceAttributesClass, gAudioDeviceAttributesCstor,
|
||||||
jNativeType, jAddress.get());
|
jNativeType, jAddress.get());
|
||||||
|
|
||||||
return jStatus;
|
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
|
} // namespace android
|
||||||
|
|
||||||
int register_android_media_AudioDeviceAttributes(JNIEnv *env) {
|
int register_android_media_AudioDeviceAttributes(JNIEnv *env) {
|
||||||
@@ -48,5 +66,10 @@ int register_android_media_AudioDeviceAttributes(JNIEnv *env) {
|
|||||||
gAudioDeviceAttributesCstor =
|
gAudioDeviceAttributesCstor =
|
||||||
GetMethodIDOrDie(env, audioDeviceTypeAddressClass, "<init>", "(ILjava/lang/String;)V");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ namespace android {
|
|||||||
|
|
||||||
extern jint createAudioDeviceAttributesFromNative(JNIEnv *env, jobject *jAudioDeviceAttributes,
|
extern jint createAudioDeviceAttributesFromNative(JNIEnv *env, jobject *jAudioDeviceAttributes,
|
||||||
const AudioDeviceTypeAddr *devTypeAddr);
|
const AudioDeviceTypeAddr *devTypeAddr);
|
||||||
|
|
||||||
|
extern jint createAudioDeviceTypeAddrFromJava(JNIEnv *env, AudioDeviceTypeAddr *devTypeAddr,
|
||||||
|
const jobject jAudioDeviceAttributes);
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -27,6 +27,8 @@
|
|||||||
#include "core_jni_helpers.h"
|
#include "core_jni_helpers.h"
|
||||||
|
|
||||||
#include <android/media/AudioVibratorInfo.h>
|
#include <android/media/AudioVibratorInfo.h>
|
||||||
|
#include <android/media/INativeSpatializerCallback.h>
|
||||||
|
#include <android/media/ISpatializer.h>
|
||||||
#include <audiomanager/AudioManager.h>
|
#include <audiomanager/AudioManager.h>
|
||||||
#include <media/AudioPolicy.h>
|
#include <media/AudioPolicy.h>
|
||||||
#include <media/AudioSystem.h>
|
#include <media/AudioSystem.h>
|
||||||
@@ -2023,6 +2025,18 @@ android_media_AudioSystem_registerRoutingCallback(JNIEnv *env, jobject thiz)
|
|||||||
AudioSystem::setRoutingCallback(android_media_AudioSystem_routing_callback);
|
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,
|
static jint convertAudioMixToNative(JNIEnv *env,
|
||||||
AudioMix *nAudioMix,
|
AudioMix *nAudioMix,
|
||||||
@@ -2043,13 +2057,7 @@ static jint convertAudioMixToNative(JNIEnv *env,
|
|||||||
nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
|
nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
|
||||||
|
|
||||||
jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
|
jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
|
||||||
nAudioMix->mFormat = AUDIO_CONFIG_INITIALIZER;
|
javaAudioFormatToNativeAudioConfig(env, &nAudioMix->mFormat, jFormat, false /*isInput*/);
|
||||||
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));
|
|
||||||
env->DeleteLocalRef(jFormat);
|
env->DeleteLocalRef(jFormat);
|
||||||
|
|
||||||
jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
|
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));
|
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[] =
|
static const JNINativeMethod gMethods[] =
|
||||||
@@ -2848,7 +2908,15 @@ static const JNINativeMethod gMethods[] =
|
|||||||
(void *)android_media_AudioSystem_removeUserIdDeviceAffinities},
|
(void *)android_media_AudioSystem_removeUserIdDeviceAffinities},
|
||||||
{"setCurrentImeUid", "(I)I", (void *)android_media_AudioSystem_setCurrentImeUid},
|
{"setCurrentImeUid", "(I)I", (void *)android_media_AudioSystem_setCurrentImeUid},
|
||||||
{"setVibratorInfos", "(Ljava/util/List;)I",
|
{"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[] = {
|
static const JNINativeMethod gEventHandlerMethods[] = {
|
||||||
{"native_setup",
|
{"native_setup",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package android.media;
|
|||||||
|
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.annotation.RequiresPermission;
|
import android.annotation.RequiresPermission;
|
||||||
import android.annotation.TestApi;
|
import android.annotation.TestApi;
|
||||||
import android.bluetooth.BluetoothCodecConfig;
|
import android.bluetooth.BluetoothCodecConfig;
|
||||||
@@ -2000,6 +2001,46 @@ public class AudioSystem
|
|||||||
*/
|
*/
|
||||||
public static native int setVibratorInfos(@NonNull List<Vibrator> vibrators);
|
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
|
// Items shared with audio service
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user