diff options
| author | Eric Laurent <elaurent@google.com> | 2021-08-24 16:00:38 +0000 |
|---|---|---|
| committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-08-24 16:00:38 +0000 |
| commit | af8b4f4dc2e2c2dcaff4a6e8dea5bfd27bf2dc5a (patch) | |
| tree | 904d4afcaf52cbf09958ff29488a07899e3ba289 | |
| parent | 7ec41085c0625e6e4d3ea4f3ffa8c8b2348f2a7e (diff) | |
| parent | 8c500d588286605b1617a81547a8951aef7c8e9f (diff) | |
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
| -rw-r--r-- | Android.bp | 2 | ||||
| -rw-r--r-- | core/jni/Android.bp | 2 | ||||
| -rw-r--r-- | core/jni/android_media_AudioDeviceAttributes.cpp | 27 | ||||
| -rw-r--r-- | core/jni/android_media_AudioDeviceAttributes.h | 3 | ||||
| -rw-r--r-- | core/jni/android_media_AudioSystem.cpp | 84 | ||||
| -rw-r--r-- | media/java/android/media/AudioSystem.java | 41 |
6 files changed, 149 insertions, 10 deletions
diff --git a/Android.bp b/Android.bp index be10428a19ce..956582b45929 100644 --- a/Android.bp +++ b/Android.bp @@ -342,6 +342,8 @@ java_defaults { "modules-utils-preconditions", "modules-utils-os", "framework-permission-aidl-java", + "spatializer-aidl-java", + "audiopolicy-types-aidl-java", ], } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index f46aadfa3c3f..49066e35f859 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -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", diff --git a/core/jni/android_media_AudioDeviceAttributes.cpp b/core/jni/android_media_AudioDeviceAttributes.cpp index 2a16dce99125..6879a6008f5a 100644 --- a/core/jni/android_media_AudioDeviceAttributes.cpp +++ b/core/jni/android_media_AudioDeviceAttributes.cpp @@ -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; } diff --git a/core/jni/android_media_AudioDeviceAttributes.h b/core/jni/android_media_AudioDeviceAttributes.h index b49d9ba515b8..4a1f40d9bb7c 100644 --- a/core/jni/android_media_AudioDeviceAttributes.h +++ b/core/jni/android_media_AudioDeviceAttributes.h @@ -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
\ No newline at end of file diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 47db3547f931..509b7ad74a29 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -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", diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 69d1889d5762..5d9f2909903b 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -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 /** |
