diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 9c01bcada1ee7..dd9031a8af8e8 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -5379,12 +5379,14 @@ package android.media { method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void clearOnHeadToSoundstagePoseUpdatedListener(); method @NonNull @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public java.util.List getCompatibleAudioDevices(); method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public int getDesiredHeadTrackingMode(); + method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void getEffectParameter(int, @NonNull byte[]); method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public int getHeadTrackingMode(); method @NonNull @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public java.util.List getSupportedHeadTrackingModes(); method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void recenterHeadTracker(); method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void removeCompatibleAudioDevice(@NonNull android.media.AudioDeviceAttributes); method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void removeOnHeadTrackingModeChangedListener(@NonNull android.media.Spatializer.OnHeadTrackingModeChangedListener); method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void setDesiredHeadTrackingMode(int); + method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void setEffectParameter(int, @NonNull byte[]); method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void setEnabled(boolean); method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void setGlobalTransform(@NonNull float[]); method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public void setOnHeadToSoundstagePoseUpdatedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.Spatializer.OnHeadToSoundstagePoseUpdatedListener); diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index bc1040115417a..6d52b664cee90 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -436,4 +436,8 @@ interface IAudioService { oneway void setSpatializerGlobalTransform(in float[] transform); oneway void recenterHeadTracker(); + + void setSpatializerParameter(int key, in byte[] value); + + void getSpatializerParameter(int key, inout byte[] value); } diff --git a/media/java/android/media/Spatializer.java b/media/java/android/media/Spatializer.java index b062eea5017c5..3b835f7443055 100644 --- a/media/java/android/media/Spatializer.java +++ b/media/java/android/media/Spatializer.java @@ -792,6 +792,45 @@ public class Spatializer { } } + /** + * @hide + * Sets a parameter on the platform spatializer effect implementation. + * This is to be used for vendor-specific configurations of their effect, keys and values are + * not reuseable across implementations. + * @param key the parameter to change + * @param value an array for the value of the parameter to change + */ + @SystemApi(client = SystemApi.Client.PRIVILEGED_APPS) + @RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS) + public void setEffectParameter(int key, @NonNull byte[] value) { + Objects.requireNonNull(value); + try { + mAm.getService().setSpatializerParameter(key, value); + } catch (RemoteException e) { + Log.e(TAG, "Error calling setEffectParameter", e); + } + } + + /** + * @hide + * Retrieves a parameter value from the platform spatializer effect implementation. + * This is to be used for vendor-specific configurations of their effect, keys and values are + * not reuseable across implementations. + * @param key the parameter for which the value is queried + * @param value a non-empty array to contain the return value. The caller is responsible for + * passing an array of size matching the parameter. + */ + @SystemApi(client = SystemApi.Client.PRIVILEGED_APPS) + @RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS) + public void getEffectParameter(int key, @NonNull byte[] value) { + Objects.requireNonNull(value); + try { + mAm.getService().getSpatializerParameter(key, value); + } catch (RemoteException e) { + Log.e(TAG, "Error calling getEffectParameter", e); + } + } + //----------------------------------------------------------------------------- // callback helper definitions diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 5d0bad23f0243..e383c560823b8 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -8433,6 +8433,20 @@ public class AudioService extends IAudioService.Stub mSpatializerHelper.setDesiredHeadTrackingMode(mode); } + /** @see Spatializer#setEffectParameter */ + public void setSpatializerParameter(int key, @NonNull byte[] value) { + enforceModifyDefaultAudioEffectsPermission(); + Objects.requireNonNull(value); + mSpatializerHelper.setEffectParameter(key, value); + } + + /** @see Spatializer#getEffectParameter */ + public void getSpatializerParameter(int key, @NonNull byte[] value) { + enforceModifyDefaultAudioEffectsPermission(); + Objects.requireNonNull(value); + mSpatializerHelper.getEffectParameter(key, value); + } + //========================================================================================== private boolean readCameraSoundForced() { return SystemProperties.getBoolean("audio.camerasound.force", false) || diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java index 1d8597497a2c0..dd8e0081b50f2 100644 --- a/services/core/java/com/android/server/audio/SpatializerHelper.java +++ b/services/core/java/com/android/server/audio/SpatializerHelper.java @@ -728,4 +728,54 @@ public class SpatializerHelper { } mHeadPoseCallbacks.finishBroadcast(); } + + //------------------------------------------------------ + // vendor parameters + synchronized void setEffectParameter(int key, @NonNull byte[] value) { + switch (mState) { + case STATE_UNINITIALIZED: + case STATE_NOT_SUPPORTED: + throw (new IllegalStateException( + "Can't set parameter key:" + key + " without a spatializer")); + case STATE_ENABLED_UNAVAILABLE: + case STATE_DISABLED_UNAVAILABLE: + case STATE_DISABLED_AVAILABLE: + case STATE_ENABLED_AVAILABLE: + if (mSpat == null) { + throw (new IllegalStateException( + "null Spatializer for setParameter for key:" + key)); + } + break; + } + // mSpat != null + try { + mSpat.setParameter(key, value); + } catch (RemoteException e) { + Log.e(TAG, "Error in setParameter for key:" + key, e); + } + } + + synchronized void getEffectParameter(int key, @NonNull byte[] value) { + switch (mState) { + case STATE_UNINITIALIZED: + case STATE_NOT_SUPPORTED: + throw (new IllegalStateException( + "Can't get parameter key:" + key + " without a spatializer")); + case STATE_ENABLED_UNAVAILABLE: + case STATE_DISABLED_UNAVAILABLE: + case STATE_DISABLED_AVAILABLE: + case STATE_ENABLED_AVAILABLE: + if (mSpat == null) { + throw (new IllegalStateException( + "null Spatializer for getParameter for key:" + key)); + } + break; + } + // mSpat != null + try { + mSpat.getParameter(key, value); + } catch (RemoteException e) { + Log.e(TAG, "Error in getParameter for key:" + key, e); + } + } }