diff --git a/library/common/src/main/java/com/google/android/exoplayer2/C.java b/library/common/src/main/java/com/google/android/exoplayer2/C.java index 2c2548468b..b8d2def750 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/C.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/C.java @@ -272,6 +272,20 @@ public final class C { /** @see AudioFormat#ENCODING_DOLBY_TRUEHD */ 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/library/common/src/main/java/com/google/android/exoplayer2/audio/AudioAttributes.java b/library/common/src/main/java/com/google/android/exoplayer2/audio/AudioAttributes.java index f503ab53c4..0ae911cf08 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/audio/AudioAttributes.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/audio/AudioAttributes.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2.audio; import android.os.Bundle; +import androidx.annotation.DoNotInline; import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; @@ -25,6 +26,7 @@ import com.google.android.exoplayer2.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 @@ -48,6 +50,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}. @@ -60,6 +63,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) */ @@ -86,9 +90,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); } } @@ -96,6 +109,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; @@ -103,11 +117,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; } /** @@ -124,7 +140,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(); } @@ -143,7 +162,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 @@ -153,6 +173,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; } @@ -160,13 +181,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; @Override public Bundle toBundle() { @@ -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; } @@ -194,10 +223,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/library/common/src/test/java/com/google/android/exoplayer2/audio/AudioAttributesTest.java b/library/common/src/test/java/com/google/android/exoplayer2/audio/AudioAttributesTest.java index 9296f60dd7..241633eb1b 100644 --- a/library/common/src/test/java/com/google/android/exoplayer2/audio/AudioAttributesTest.java +++ b/library/common/src/test/java/com/google/android/exoplayer2/audio/AudioAttributesTest.java @@ -34,6 +34,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()))