From e4e0c7bce5437a1bb79b2a783ae5368830199cd7 Mon Sep 17 00:00:00 2001 From: christosts Date: Mon, 6 Dec 2021 12:37:06 +0000 Subject: [PATCH] Add AudioAttributes.spatializationBehavior The new field matches the platform's AudioAttributes.getSpatializationBehavior() API added in Sv2. At the moment, the platform API is called via reflection, until Sv2 is released and the compile SDK target can be increased to 32. PiperOrigin-RevId: 414406126 --- .../media3/common/AudioAttributes.java | 74 +++++++++++++++++-- .../main/java/androidx/media3/common/C.java | 14 ++++ .../media3/common/AudioAttributesTest.java | 1 + 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/AudioAttributes.java b/libraries/common/src/main/java/androidx/media3/common/AudioAttributes.java index 482fe14045..ac8049f1f4 100644 --- a/libraries/common/src/main/java/androidx/media3/common/AudioAttributes.java +++ b/libraries/common/src/main/java/androidx/media3/common/AudioAttributes.java @@ -16,6 +16,7 @@ package androidx.media3.common; import android.os.Bundle; +import androidx.annotation.DoNotInline; import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; @@ -24,6 +25,7 @@ import androidx.media3.common.util.Util; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Method; /** * Attributes for audio playback, which configure the underlying platform {@link @@ -47,6 +49,7 @@ public final class AudioAttributes implements Bundleable { private @C.AudioFlags int flags; private @C.AudioUsage int usage; private @C.AudioAllowedCapturePolicy int allowedCapturePolicy; + private @C.SpatializationBehavior int spatializationBehavior; /** * Creates a new builder for {@link AudioAttributes}. @@ -59,6 +62,7 @@ public final class AudioAttributes implements Bundleable { flags = 0; usage = C.USAGE_MEDIA; allowedCapturePolicy = C.ALLOW_CAPTURE_BY_ALL; + spatializationBehavior = C.SPATIALIZATION_BEHAVIOR_AUTO; } /** @see android.media.AudioAttributes.Builder#setContentType(int) */ @@ -85,9 +89,18 @@ public final class AudioAttributes implements Bundleable { return this; } + // TODO[b/190759307] Update javadoc to link to AudioAttributes.Builder#setSpatializationBehavior + // once compile SDK target is set to 32. + /** See AudioAttributes.Builder#setSpatializationBehavior(int). */ + public Builder setSpatializationBehavior(@C.SpatializationBehavior int spatializationBehavior) { + this.spatializationBehavior = spatializationBehavior; + return this; + } + /** Creates an {@link AudioAttributes} instance from this builder. */ public AudioAttributes build() { - return new AudioAttributes(contentType, flags, usage, allowedCapturePolicy); + return new AudioAttributes( + contentType, flags, usage, allowedCapturePolicy, spatializationBehavior); } } @@ -95,6 +108,7 @@ public final class AudioAttributes implements Bundleable { public final @C.AudioFlags int flags; public final @C.AudioUsage int usage; public final @C.AudioAllowedCapturePolicy int allowedCapturePolicy; + public final @C.SpatializationBehavior int spatializationBehavior; @Nullable private android.media.AudioAttributes audioAttributesV21; @@ -102,11 +116,13 @@ public final class AudioAttributes implements Bundleable { @C.AudioContentType int contentType, @C.AudioFlags int flags, @C.AudioUsage int usage, - @C.AudioAllowedCapturePolicy int allowedCapturePolicy) { + @C.AudioAllowedCapturePolicy int allowedCapturePolicy, + @C.SpatializationBehavior int spatializationBehavior) { this.contentType = contentType; this.flags = flags; this.usage = usage; this.allowedCapturePolicy = allowedCapturePolicy; + this.spatializationBehavior = spatializationBehavior; } /** @@ -123,7 +139,10 @@ public final class AudioAttributes implements Bundleable { .setFlags(flags) .setUsage(usage); if (Util.SDK_INT >= 29) { - builder.setAllowedCapturePolicy(allowedCapturePolicy); + Api29.setAllowedCapturePolicy(builder, allowedCapturePolicy); + } + if (Util.SDK_INT >= 32) { + Api32.setSpatializationBehavior(builder, spatializationBehavior); } audioAttributesV21 = builder.build(); } @@ -142,7 +161,8 @@ public final class AudioAttributes implements Bundleable { return this.contentType == other.contentType && this.flags == other.flags && this.usage == other.usage - && this.allowedCapturePolicy == other.allowedCapturePolicy; + && this.allowedCapturePolicy == other.allowedCapturePolicy + && this.spatializationBehavior == other.spatializationBehavior; } @Override @@ -152,6 +172,7 @@ public final class AudioAttributes implements Bundleable { result = 31 * result + flags; result = 31 * result + usage; result = 31 * result + allowedCapturePolicy; + result = 31 * result + spatializationBehavior; return result; } @@ -159,13 +180,20 @@ public final class AudioAttributes implements Bundleable { @Documented @Retention(RetentionPolicy.SOURCE) - @IntDef({FIELD_CONTENT_TYPE, FIELD_FLAGS, FIELD_USAGE, FIELD_ALLOWED_CAPTURE_POLICY}) + @IntDef({ + FIELD_CONTENT_TYPE, + FIELD_FLAGS, + FIELD_USAGE, + FIELD_ALLOWED_CAPTURE_POLICY, + FIELD_SPATIALIZATION_BEHAVIOR + }) private @interface FieldNumber {} private static final int FIELD_CONTENT_TYPE = 0; private static final int FIELD_FLAGS = 1; private static final int FIELD_USAGE = 2; private static final int FIELD_ALLOWED_CAPTURE_POLICY = 3; + private static final int FIELD_SPATIALIZATION_BEHAVIOR = 4; @UnstableApi @Override @@ -175,6 +203,7 @@ public final class AudioAttributes implements Bundleable { bundle.putInt(keyForField(FIELD_FLAGS), flags); bundle.putInt(keyForField(FIELD_USAGE), usage); bundle.putInt(keyForField(FIELD_ALLOWED_CAPTURE_POLICY), allowedCapturePolicy); + bundle.putInt(keyForField(FIELD_SPATIALIZATION_BEHAVIOR), spatializationBehavior); return bundle; } @@ -195,10 +224,45 @@ public final class AudioAttributes implements Bundleable { if (bundle.containsKey(keyForField(FIELD_ALLOWED_CAPTURE_POLICY))) { builder.setAllowedCapturePolicy(bundle.getInt(keyForField(FIELD_ALLOWED_CAPTURE_POLICY))); } + if (bundle.containsKey(keyForField(FIELD_SPATIALIZATION_BEHAVIOR))) { + builder.setSpatializationBehavior( + bundle.getInt(keyForField(FIELD_SPATIALIZATION_BEHAVIOR))); + } return builder.build(); }; private static String keyForField(@FieldNumber int field) { return Integer.toString(field, Character.MAX_RADIX); } + + @RequiresApi(29) + private static final class Api29 { + private Api29() {} + + @DoNotInline + public static void setAllowedCapturePolicy( + android.media.AudioAttributes.Builder builder, + @C.AudioAllowedCapturePolicy int allowedCapturePolicy) { + builder.setAllowedCapturePolicy(allowedCapturePolicy); + } + } + + @RequiresApi(32) + private static final class Api32 { + private Api32() {} + + @DoNotInline + public static void setSpatializationBehavior( + android.media.AudioAttributes.Builder builder, + @C.SpatializationBehavior int spatializationBehavior) { + try { + // TODO[b/190759307]: Remove reflection once compile SDK target is set to 32. + Method setSpatializationBehavior = + builder.getClass().getMethod("setSpatializationBehavior", Integer.TYPE); + setSpatializationBehavior.invoke(builder, spatializationBehavior); + } catch (Exception e) { + // Do nothing if reflection fails. + } + } + } } diff --git a/libraries/common/src/main/java/androidx/media3/common/C.java b/libraries/common/src/main/java/androidx/media3/common/C.java index e82f1bd6ca..75e5f66437 100644 --- a/libraries/common/src/main/java/androidx/media3/common/C.java +++ b/libraries/common/src/main/java/androidx/media3/common/C.java @@ -276,6 +276,20 @@ public final class C { /** @see AudioFormat#ENCODING_DOLBY_TRUEHD */ @UnstableApi public static final int ENCODING_DOLBY_TRUEHD = AudioFormat.ENCODING_DOLBY_TRUEHD; + /** Represents the behavior affecting whether spatialization will be used. */ + @Documented + @Retention(RetentionPolicy.SOURCE) + @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, TYPE_USE}) + @IntDef({SPATIALIZATION_BEHAVIOR_AUTO, SPATIALIZATION_BEHAVIOR_NEVER}) + public @interface SpatializationBehavior {} + + // TODO[b/190759307]: Update constant values and javadoc to use SDK once compile SDK target is set + // to 32. + /** See AudioAttributes#SPATIALIZATION_BEHAVIOR_AUTO */ + public static final int SPATIALIZATION_BEHAVIOR_AUTO = 0; + /** See AudioAttributes#SPATIALIZATION_BEHAVIOR_NEVER */ + public static final int SPATIALIZATION_BEHAVIOR_NEVER = 1; + /** * Stream types for an {@link android.media.AudioTrack}. One of {@link #STREAM_TYPE_ALARM}, {@link * #STREAM_TYPE_DTMF}, {@link #STREAM_TYPE_MUSIC}, {@link #STREAM_TYPE_NOTIFICATION}, {@link diff --git a/libraries/common/src/test/java/androidx/media3/common/AudioAttributesTest.java b/libraries/common/src/test/java/androidx/media3/common/AudioAttributesTest.java index 99bc900080..85378ed7a4 100644 --- a/libraries/common/src/test/java/androidx/media3/common/AudioAttributesTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/AudioAttributesTest.java @@ -33,6 +33,7 @@ public class AudioAttributesTest { .setFlags(C.FLAG_AUDIBILITY_ENFORCED) .setUsage(C.USAGE_ALARM) .setAllowedCapturePolicy(C.ALLOW_CAPTURE_BY_SYSTEM) + .setSpatializationBehavior(C.SPATIALIZATION_BEHAVIOR_NEVER) .build(); assertThat(AudioAttributes.CREATOR.fromBundle(audioAttributes.toBundle()))