From a40a71a534092e93bef18b79915fa8423cb2b8d5 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 --- .../java/com/google/android/exoplayer2/C.java | 14 ++++ .../exoplayer2/audio/AudioAttributes.java | 74 +++++++++++++++++-- .../exoplayer2/audio/AudioAttributesTest.java | 1 + 3 files changed, 84 insertions(+), 5 deletions(-) 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()))