Loading core/api/system-current.txt +5 −3 Original line number Original line Diff line number Diff line Loading @@ -8146,6 +8146,7 @@ package android.media.audiopolicy { public class AudioMix implements android.os.Parcelable { public class AudioMix implements android.os.Parcelable { method public int describeContents(); method public int describeContents(); method public int getMixState(); method public int getMixState(); method @FlaggedApi("android.media.audio.dap_injection_starve_management") public boolean isInjectingSilenceOnStarvation(); method public void writeToParcel(@NonNull android.os.Parcel, int); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioMix> CREATOR; field @NonNull public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioMix> CREATOR; field public static final int MIX_STATE_DISABLED = -1; // 0xffffffff field public static final int MIX_STATE_DISABLED = -1; // 0xffffffff Loading @@ -8158,9 +8159,10 @@ package android.media.audiopolicy { public static class AudioMix.Builder { public static class AudioMix.Builder { ctor public AudioMix.Builder(@NonNull android.media.audiopolicy.AudioMixingRule) throws java.lang.IllegalArgumentException; ctor public AudioMix.Builder(@NonNull android.media.audiopolicy.AudioMixingRule) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix build() throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix build() throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix.Builder setDevice(@NonNull android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException; method @NonNull public android.media.audiopolicy.AudioMix.Builder setDevice(@NonNull android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix.Builder setFormat(@NonNull android.media.AudioFormat) throws java.lang.IllegalArgumentException; method @NonNull public android.media.audiopolicy.AudioMix.Builder setFormat(@NonNull android.media.AudioFormat) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException; method @FlaggedApi("android.media.audio.dap_injection_starve_management") @NonNull public android.media.audiopolicy.AudioMix.Builder setInjectSilenceOnStarvation(boolean); method @NonNull public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException; } } public class AudioMixingRule implements android.os.Parcelable { public class AudioMixingRule implements android.os.Parcelable { media/java/android/media/audiopolicy/AudioMix.java +81 −11 Original line number Original line Diff line number Diff line Loading @@ -16,9 +16,12 @@ package android.media.audiopolicy; package android.media.audiopolicy; import static android.media.audio.Flags.FLAG_DAP_INJECTION_STARVE_MANAGEMENT; import static android.media.audio.Flags.dapInjectionStarveManagement; import static android.media.AudioSystem.getDeviceName; import static android.media.AudioSystem.getDeviceName; import static android.media.AudioSystem.isRemoteSubmixDevice; import static android.media.AudioSystem.isRemoteSubmixDevice; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; Loading Loading @@ -74,6 +77,11 @@ public class AudioMix implements Parcelable { // audio routing for this device ID. // audio routing for this device ID. private int mVirtualDeviceId; private int mVirtualDeviceId; // When this mix is used for injecting audio into recordings, indicates whether silence // should be injected when the injection is failing to provide enough audio data in time // False by default or when not applicable private boolean mInjectSilenceOnStarve = false; /** /** * All parameters are guaranteed valid through the Builder. * All parameters are guaranteed valid through the Builder. */ */ Loading @@ -90,6 +98,23 @@ public class AudioMix implements Parcelable { mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress; mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress; mToken = token; mToken = token; mVirtualDeviceId = virtualDeviceId; mVirtualDeviceId = virtualDeviceId; mInjectSilenceOnStarve = false; } private AudioMix(@NonNull AudioMixingRule rule, @NonNull AudioFormat format, int routeFlags, int callbackFlags, int deviceType, @Nullable String deviceAddress, IBinder token, int virtualDeviceId, boolean injectSilenceOnStarve) { mRule = Objects.requireNonNull(rule); mFormat = Objects.requireNonNull(format); mRouteFlags = routeFlags; mMixType = rule.getTargetMixType(); mCallbackFlags = callbackFlags; mDeviceSystemType = deviceType; mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress; mToken = token; mVirtualDeviceId = virtualDeviceId; mInjectSilenceOnStarve = injectSilenceOnStarve; } } // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined Loading Loading @@ -272,6 +297,20 @@ public class AudioMix implements Parcelable { return null; return null; } } /** * Returns whether this mix was configured to inject silence audio into recordings * when the injection is failing to provide enough audio data in time. * @return <code>false</code> if the mix is not an injection mix, or how it was configured * {@link Builder#setInjectSilenceOnStarvation(boolean)}. */ @FlaggedApi(FLAG_DAP_INJECTION_STARVE_MANAGEMENT) public boolean isInjectingSilenceOnStarvation() { if (!dapInjectionStarveManagement()) { return false; } return mInjectSilenceOnStarve; } /** @hide */ /** @hide */ public boolean isForCallRedirection() { public boolean isForCallRedirection() { return mRule.isForCallRedirection(); return mRule.isForCallRedirection(); Loading Loading @@ -321,6 +360,9 @@ public class AudioMix implements Parcelable { mRule.writeToParcel(dest, flags); mRule.writeToParcel(dest, flags); dest.writeStrongBinder(mToken); dest.writeStrongBinder(mToken); dest.writeInt(mVirtualDeviceId); dest.writeInt(mVirtualDeviceId); if (dapInjectionStarveManagement()) { dest.writeBoolean(mInjectSilenceOnStarve); } } } public static final @NonNull Parcelable.Creator<AudioMix> CREATOR = new Parcelable.Creator<>() { public static final @NonNull Parcelable.Creator<AudioMix> CREATOR = new Parcelable.Creator<>() { Loading @@ -342,6 +384,9 @@ public class AudioMix implements Parcelable { mixBuilder.setMixingRule(AudioMixingRule.CREATOR.createFromParcel(p)); mixBuilder.setMixingRule(AudioMixingRule.CREATOR.createFromParcel(p)); mixBuilder.setToken(p.readStrongBinder()); mixBuilder.setToken(p.readStrongBinder()); mixBuilder.setVirtualDeviceId(p.readInt()); mixBuilder.setVirtualDeviceId(p.readInt()); if (dapInjectionStarveManagement()) { mixBuilder.setInjectSilenceOnStarvation(p.readBoolean()); } return mixBuilder.build(); return mixBuilder.build(); } } Loading Loading @@ -378,6 +423,7 @@ public class AudioMix implements Parcelable { // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_* // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_* private int mDeviceSystemType = AudioSystem.DEVICE_NONE; private int mDeviceSystemType = AudioSystem.DEVICE_NONE; private String mDeviceAddress = null; private String mDeviceAddress = null; private boolean mInjectSilenceOnStarve = false; /** /** * @hide * @hide Loading Loading @@ -405,7 +451,7 @@ public class AudioMix implements Parcelable { * @return the same Builder instance. * @return the same Builder instance. * @throws IllegalArgumentException * @throws IllegalArgumentException */ */ Builder setMixingRule(@NonNull AudioMixingRule rule) @NonNull Builder setMixingRule(@NonNull AudioMixingRule rule) throws IllegalArgumentException { throws IllegalArgumentException { if (rule == null) { if (rule == null) { throw new IllegalArgumentException("Illegal null AudioMixingRule argument"); throw new IllegalArgumentException("Illegal null AudioMixingRule argument"); Loading @@ -418,7 +464,7 @@ public class AudioMix implements Parcelable { * @hide * @hide * Only used by AudioMix internally. * Only used by AudioMix internally. */ */ Builder setToken(IBinder token) { @NonNull Builder setToken(IBinder token) { mToken = token; mToken = token; return this; return this; } } Loading @@ -427,7 +473,7 @@ public class AudioMix implements Parcelable { * @hide * @hide * Only used by AudioMix internally. * Only used by AudioMix internally. */ */ Builder setVirtualDeviceId(int virtualDeviceId) { @NonNull Builder setVirtualDeviceId(int virtualDeviceId) { mVirtualDeviceId = virtualDeviceId; mVirtualDeviceId = virtualDeviceId; return this; return this; } } Loading @@ -435,11 +481,11 @@ public class AudioMix implements Parcelable { /** /** * @hide * @hide * Only used by AudioPolicyConfig, not a public API. * Only used by AudioPolicyConfig, not a public API. * @param callbackFlags which callbacks are called from native * @param flags which callbacks are called from native * @return the same Builder instance. * @return the same Builder instance. * @throws IllegalArgumentException * @throws IllegalArgumentException */ */ Builder setCallbackFlags(int flags) throws IllegalArgumentException { @NonNull Builder setCallbackFlags(int flags) throws IllegalArgumentException { if ((flags != 0) && ((flags & CALLBACK_FLAGS_ALL) == 0)) { if ((flags != 0) && ((flags & CALLBACK_FLAGS_ALL) == 0)) { throw new IllegalArgumentException("Illegal callback flags 0x" throw new IllegalArgumentException("Illegal callback flags 0x" + Integer.toHexString(flags).toUpperCase()); + Integer.toHexString(flags).toUpperCase()); Loading @@ -456,7 +502,7 @@ public class AudioMix implements Parcelable { * @return the same Builder instance. * @return the same Builder instance. */ */ @VisibleForTesting @VisibleForTesting public Builder setDevice(int deviceType, String address) { public @NonNull Builder setDevice(int deviceType, String address) { mDeviceSystemType = deviceType; mDeviceSystemType = deviceType; mDeviceAddress = address; mDeviceAddress = address; return this; return this; Loading @@ -468,7 +514,7 @@ public class AudioMix implements Parcelable { * @return the same Builder instance. * @return the same Builder instance. * @throws IllegalArgumentException * @throws IllegalArgumentException */ */ public Builder setFormat(@NonNull AudioFormat format) public @NonNull Builder setFormat(@NonNull AudioFormat format) throws IllegalArgumentException { throws IllegalArgumentException { if (format == null) { if (format == null) { throw new IllegalArgumentException("Illegal null AudioFormat argument"); throw new IllegalArgumentException("Illegal null AudioFormat argument"); Loading @@ -485,7 +531,7 @@ public class AudioMix implements Parcelable { * @return the same Builder instance. * @return the same Builder instance. * @throws IllegalArgumentException * @throws IllegalArgumentException */ */ public Builder setRouteFlags(@RouteFlags int routeFlags) public @NonNull Builder setRouteFlags(@RouteFlags int routeFlags) throws IllegalArgumentException { throws IllegalArgumentException { if (routeFlags == 0) { if (routeFlags == 0) { throw new IllegalArgumentException("Illegal empty route flags"); throw new IllegalArgumentException("Illegal empty route flags"); Loading @@ -511,7 +557,8 @@ public class AudioMix implements Parcelable { * @return the same Builder instance * @return the same Builder instance * @throws IllegalArgumentException * @throws IllegalArgumentException */ */ public Builder setDevice(@NonNull AudioDeviceInfo device) throws IllegalArgumentException { public @NonNull Builder setDevice(@NonNull AudioDeviceInfo device) throws IllegalArgumentException { if (device == null) { if (device == null) { throw new IllegalArgumentException("Illegal null AudioDeviceInfo argument"); throw new IllegalArgumentException("Illegal null AudioDeviceInfo argument"); } } Loading @@ -523,10 +570,24 @@ public class AudioMix implements Parcelable { return this; return this; } } /** * When this mix is used for injecting audio into recordings, configure whether silence * should be injected when the injection is failing to provide enough audio data in time * @param injectSilence indicates if silence is injected into recordings when * @return the same Builder instance */ @FlaggedApi(FLAG_DAP_INJECTION_STARVE_MANAGEMENT) public @NonNull Builder setInjectSilenceOnStarvation(boolean injectSilence) { mInjectSilenceOnStarve = injectSilence; return this; } /** /** * Combines all of the settings and return a new {@link AudioMix} object. * Combines all of the settings and return a new {@link AudioMix} object. * @return a new {@link AudioMix} object * @return a new {@link AudioMix} object * @throws IllegalArgumentException if no {@link AudioMixingRule} has been set. * @throws IllegalArgumentException if no {@link AudioMixingRule} has been set * or if {@link #setInjectSilenceOnStarvation(boolean)} was set to <code>true</code> on * a mix not used for injection */ */ public AudioMix build() throws IllegalArgumentException { public AudioMix build() throws IllegalArgumentException { if (mRule == null) { if (mRule == null) { Loading Loading @@ -588,6 +649,15 @@ public class AudioMix implements Parcelable { } } } } if (dapInjectionStarveManagement() && ((mRouteFlags & ROUTE_FLAG_LOOP_BACK) == ROUTE_FLAG_LOOP_BACK) && (mRule.getTargetMixType() != MIX_TYPE_RECORDERS) && (mInjectSilenceOnStarve)) { throw new IllegalArgumentException( "AudioMix.Builder.setInjectSilenceOnStarvation(true) called " + "on a non-injection AudioMix"); } if (mRule.allowPrivilegedMediaPlaybackCapture()) { if (mRule.allowPrivilegedMediaPlaybackCapture()) { String error = AudioMix.canBeUsedForPrivilegedMediaCapture(mFormat); String error = AudioMix.canBeUsedForPrivilegedMediaCapture(mFormat); if (error != null) { if (error != null) { Loading @@ -600,7 +670,7 @@ public class AudioMix implements Parcelable { } } return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType, return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType, mDeviceAddress, mToken, mVirtualDeviceId); mDeviceAddress, mToken, mVirtualDeviceId, mInjectSilenceOnStarve); } } private int getLoopbackDeviceSystemTypeForAudioMixingRule(AudioMixingRule rule) { private int getLoopbackDeviceSystemTypeForAudioMixingRule(AudioMixingRule rule) { Loading services/core/java/com/android/server/audio/AudioService.java +3 −0 Original line number Original line Diff line number Diff line Loading @@ -53,6 +53,7 @@ import static android.media.audio.Flags.autoPublicVolumeApiHardening; import static android.media.audio.Flags.cacheGetStreamMinMaxVolume; import static android.media.audio.Flags.cacheGetStreamMinMaxVolume; import static android.media.audio.Flags.cacheGetStreamVolume; import static android.media.audio.Flags.cacheGetStreamVolume; import static android.media.audio.Flags.concurrentAudioRecordBypassPermission; import static android.media.audio.Flags.concurrentAudioRecordBypassPermission; import static android.media.audio.Flags.dapInjectionStarveManagement; import static android.media.audio.Flags.deviceVolumeApis; import static android.media.audio.Flags.deviceVolumeApis; import static android.media.audio.Flags.featureSpatialAudioHeadtrackingLowLatency; import static android.media.audio.Flags.featureSpatialAudioHeadtrackingLowLatency; import static android.media.audio.Flags.focusFreezeTestApi; import static android.media.audio.Flags.focusFreezeTestApi; Loading Loading @@ -5442,6 +5443,8 @@ public class AudioService extends IAudioService.Stub pw.println("\tandroid.media.audio.autoPublicVolumeApiHardening:" pw.println("\tandroid.media.audio.autoPublicVolumeApiHardening:" + autoPublicVolumeApiHardening()); + autoPublicVolumeApiHardening()); pw.println("\tandroid.media.audio.automaticBtDeviceType - EOL"); pw.println("\tandroid.media.audio.automaticBtDeviceType - EOL"); pw.println("\tandroid.media.audio.dapInjectionStarveManagement:" + dapInjectionStarveManagement()); pw.println("\tandroid.media.audio.featureSpatialAudioHeadtrackingLowLatency:" pw.println("\tandroid.media.audio.featureSpatialAudioHeadtrackingLowLatency:" + featureSpatialAudioHeadtrackingLowLatency()); + featureSpatialAudioHeadtrackingLowLatency()); pw.println("\tandroid.media.audio.focusFreezeTestApi:" pw.println("\tandroid.media.audio.focusFreezeTestApi:" Loading Loading
core/api/system-current.txt +5 −3 Original line number Original line Diff line number Diff line Loading @@ -8146,6 +8146,7 @@ package android.media.audiopolicy { public class AudioMix implements android.os.Parcelable { public class AudioMix implements android.os.Parcelable { method public int describeContents(); method public int describeContents(); method public int getMixState(); method public int getMixState(); method @FlaggedApi("android.media.audio.dap_injection_starve_management") public boolean isInjectingSilenceOnStarvation(); method public void writeToParcel(@NonNull android.os.Parcel, int); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioMix> CREATOR; field @NonNull public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioMix> CREATOR; field public static final int MIX_STATE_DISABLED = -1; // 0xffffffff field public static final int MIX_STATE_DISABLED = -1; // 0xffffffff Loading @@ -8158,9 +8159,10 @@ package android.media.audiopolicy { public static class AudioMix.Builder { public static class AudioMix.Builder { ctor public AudioMix.Builder(@NonNull android.media.audiopolicy.AudioMixingRule) throws java.lang.IllegalArgumentException; ctor public AudioMix.Builder(@NonNull android.media.audiopolicy.AudioMixingRule) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix build() throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix build() throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix.Builder setDevice(@NonNull android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException; method @NonNull public android.media.audiopolicy.AudioMix.Builder setDevice(@NonNull android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix.Builder setFormat(@NonNull android.media.AudioFormat) throws java.lang.IllegalArgumentException; method @NonNull public android.media.audiopolicy.AudioMix.Builder setFormat(@NonNull android.media.AudioFormat) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException; method @FlaggedApi("android.media.audio.dap_injection_starve_management") @NonNull public android.media.audiopolicy.AudioMix.Builder setInjectSilenceOnStarvation(boolean); method @NonNull public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException; } } public class AudioMixingRule implements android.os.Parcelable { public class AudioMixingRule implements android.os.Parcelable {
media/java/android/media/audiopolicy/AudioMix.java +81 −11 Original line number Original line Diff line number Diff line Loading @@ -16,9 +16,12 @@ package android.media.audiopolicy; package android.media.audiopolicy; import static android.media.audio.Flags.FLAG_DAP_INJECTION_STARVE_MANAGEMENT; import static android.media.audio.Flags.dapInjectionStarveManagement; import static android.media.AudioSystem.getDeviceName; import static android.media.AudioSystem.getDeviceName; import static android.media.AudioSystem.isRemoteSubmixDevice; import static android.media.AudioSystem.isRemoteSubmixDevice; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; Loading Loading @@ -74,6 +77,11 @@ public class AudioMix implements Parcelable { // audio routing for this device ID. // audio routing for this device ID. private int mVirtualDeviceId; private int mVirtualDeviceId; // When this mix is used for injecting audio into recordings, indicates whether silence // should be injected when the injection is failing to provide enough audio data in time // False by default or when not applicable private boolean mInjectSilenceOnStarve = false; /** /** * All parameters are guaranteed valid through the Builder. * All parameters are guaranteed valid through the Builder. */ */ Loading @@ -90,6 +98,23 @@ public class AudioMix implements Parcelable { mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress; mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress; mToken = token; mToken = token; mVirtualDeviceId = virtualDeviceId; mVirtualDeviceId = virtualDeviceId; mInjectSilenceOnStarve = false; } private AudioMix(@NonNull AudioMixingRule rule, @NonNull AudioFormat format, int routeFlags, int callbackFlags, int deviceType, @Nullable String deviceAddress, IBinder token, int virtualDeviceId, boolean injectSilenceOnStarve) { mRule = Objects.requireNonNull(rule); mFormat = Objects.requireNonNull(format); mRouteFlags = routeFlags; mMixType = rule.getTargetMixType(); mCallbackFlags = callbackFlags; mDeviceSystemType = deviceType; mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress; mToken = token; mVirtualDeviceId = virtualDeviceId; mInjectSilenceOnStarve = injectSilenceOnStarve; } } // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined Loading Loading @@ -272,6 +297,20 @@ public class AudioMix implements Parcelable { return null; return null; } } /** * Returns whether this mix was configured to inject silence audio into recordings * when the injection is failing to provide enough audio data in time. * @return <code>false</code> if the mix is not an injection mix, or how it was configured * {@link Builder#setInjectSilenceOnStarvation(boolean)}. */ @FlaggedApi(FLAG_DAP_INJECTION_STARVE_MANAGEMENT) public boolean isInjectingSilenceOnStarvation() { if (!dapInjectionStarveManagement()) { return false; } return mInjectSilenceOnStarve; } /** @hide */ /** @hide */ public boolean isForCallRedirection() { public boolean isForCallRedirection() { return mRule.isForCallRedirection(); return mRule.isForCallRedirection(); Loading Loading @@ -321,6 +360,9 @@ public class AudioMix implements Parcelable { mRule.writeToParcel(dest, flags); mRule.writeToParcel(dest, flags); dest.writeStrongBinder(mToken); dest.writeStrongBinder(mToken); dest.writeInt(mVirtualDeviceId); dest.writeInt(mVirtualDeviceId); if (dapInjectionStarveManagement()) { dest.writeBoolean(mInjectSilenceOnStarve); } } } public static final @NonNull Parcelable.Creator<AudioMix> CREATOR = new Parcelable.Creator<>() { public static final @NonNull Parcelable.Creator<AudioMix> CREATOR = new Parcelable.Creator<>() { Loading @@ -342,6 +384,9 @@ public class AudioMix implements Parcelable { mixBuilder.setMixingRule(AudioMixingRule.CREATOR.createFromParcel(p)); mixBuilder.setMixingRule(AudioMixingRule.CREATOR.createFromParcel(p)); mixBuilder.setToken(p.readStrongBinder()); mixBuilder.setToken(p.readStrongBinder()); mixBuilder.setVirtualDeviceId(p.readInt()); mixBuilder.setVirtualDeviceId(p.readInt()); if (dapInjectionStarveManagement()) { mixBuilder.setInjectSilenceOnStarvation(p.readBoolean()); } return mixBuilder.build(); return mixBuilder.build(); } } Loading Loading @@ -378,6 +423,7 @@ public class AudioMix implements Parcelable { // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_* // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_* private int mDeviceSystemType = AudioSystem.DEVICE_NONE; private int mDeviceSystemType = AudioSystem.DEVICE_NONE; private String mDeviceAddress = null; private String mDeviceAddress = null; private boolean mInjectSilenceOnStarve = false; /** /** * @hide * @hide Loading Loading @@ -405,7 +451,7 @@ public class AudioMix implements Parcelable { * @return the same Builder instance. * @return the same Builder instance. * @throws IllegalArgumentException * @throws IllegalArgumentException */ */ Builder setMixingRule(@NonNull AudioMixingRule rule) @NonNull Builder setMixingRule(@NonNull AudioMixingRule rule) throws IllegalArgumentException { throws IllegalArgumentException { if (rule == null) { if (rule == null) { throw new IllegalArgumentException("Illegal null AudioMixingRule argument"); throw new IllegalArgumentException("Illegal null AudioMixingRule argument"); Loading @@ -418,7 +464,7 @@ public class AudioMix implements Parcelable { * @hide * @hide * Only used by AudioMix internally. * Only used by AudioMix internally. */ */ Builder setToken(IBinder token) { @NonNull Builder setToken(IBinder token) { mToken = token; mToken = token; return this; return this; } } Loading @@ -427,7 +473,7 @@ public class AudioMix implements Parcelable { * @hide * @hide * Only used by AudioMix internally. * Only used by AudioMix internally. */ */ Builder setVirtualDeviceId(int virtualDeviceId) { @NonNull Builder setVirtualDeviceId(int virtualDeviceId) { mVirtualDeviceId = virtualDeviceId; mVirtualDeviceId = virtualDeviceId; return this; return this; } } Loading @@ -435,11 +481,11 @@ public class AudioMix implements Parcelable { /** /** * @hide * @hide * Only used by AudioPolicyConfig, not a public API. * Only used by AudioPolicyConfig, not a public API. * @param callbackFlags which callbacks are called from native * @param flags which callbacks are called from native * @return the same Builder instance. * @return the same Builder instance. * @throws IllegalArgumentException * @throws IllegalArgumentException */ */ Builder setCallbackFlags(int flags) throws IllegalArgumentException { @NonNull Builder setCallbackFlags(int flags) throws IllegalArgumentException { if ((flags != 0) && ((flags & CALLBACK_FLAGS_ALL) == 0)) { if ((flags != 0) && ((flags & CALLBACK_FLAGS_ALL) == 0)) { throw new IllegalArgumentException("Illegal callback flags 0x" throw new IllegalArgumentException("Illegal callback flags 0x" + Integer.toHexString(flags).toUpperCase()); + Integer.toHexString(flags).toUpperCase()); Loading @@ -456,7 +502,7 @@ public class AudioMix implements Parcelable { * @return the same Builder instance. * @return the same Builder instance. */ */ @VisibleForTesting @VisibleForTesting public Builder setDevice(int deviceType, String address) { public @NonNull Builder setDevice(int deviceType, String address) { mDeviceSystemType = deviceType; mDeviceSystemType = deviceType; mDeviceAddress = address; mDeviceAddress = address; return this; return this; Loading @@ -468,7 +514,7 @@ public class AudioMix implements Parcelable { * @return the same Builder instance. * @return the same Builder instance. * @throws IllegalArgumentException * @throws IllegalArgumentException */ */ public Builder setFormat(@NonNull AudioFormat format) public @NonNull Builder setFormat(@NonNull AudioFormat format) throws IllegalArgumentException { throws IllegalArgumentException { if (format == null) { if (format == null) { throw new IllegalArgumentException("Illegal null AudioFormat argument"); throw new IllegalArgumentException("Illegal null AudioFormat argument"); Loading @@ -485,7 +531,7 @@ public class AudioMix implements Parcelable { * @return the same Builder instance. * @return the same Builder instance. * @throws IllegalArgumentException * @throws IllegalArgumentException */ */ public Builder setRouteFlags(@RouteFlags int routeFlags) public @NonNull Builder setRouteFlags(@RouteFlags int routeFlags) throws IllegalArgumentException { throws IllegalArgumentException { if (routeFlags == 0) { if (routeFlags == 0) { throw new IllegalArgumentException("Illegal empty route flags"); throw new IllegalArgumentException("Illegal empty route flags"); Loading @@ -511,7 +557,8 @@ public class AudioMix implements Parcelable { * @return the same Builder instance * @return the same Builder instance * @throws IllegalArgumentException * @throws IllegalArgumentException */ */ public Builder setDevice(@NonNull AudioDeviceInfo device) throws IllegalArgumentException { public @NonNull Builder setDevice(@NonNull AudioDeviceInfo device) throws IllegalArgumentException { if (device == null) { if (device == null) { throw new IllegalArgumentException("Illegal null AudioDeviceInfo argument"); throw new IllegalArgumentException("Illegal null AudioDeviceInfo argument"); } } Loading @@ -523,10 +570,24 @@ public class AudioMix implements Parcelable { return this; return this; } } /** * When this mix is used for injecting audio into recordings, configure whether silence * should be injected when the injection is failing to provide enough audio data in time * @param injectSilence indicates if silence is injected into recordings when * @return the same Builder instance */ @FlaggedApi(FLAG_DAP_INJECTION_STARVE_MANAGEMENT) public @NonNull Builder setInjectSilenceOnStarvation(boolean injectSilence) { mInjectSilenceOnStarve = injectSilence; return this; } /** /** * Combines all of the settings and return a new {@link AudioMix} object. * Combines all of the settings and return a new {@link AudioMix} object. * @return a new {@link AudioMix} object * @return a new {@link AudioMix} object * @throws IllegalArgumentException if no {@link AudioMixingRule} has been set. * @throws IllegalArgumentException if no {@link AudioMixingRule} has been set * or if {@link #setInjectSilenceOnStarvation(boolean)} was set to <code>true</code> on * a mix not used for injection */ */ public AudioMix build() throws IllegalArgumentException { public AudioMix build() throws IllegalArgumentException { if (mRule == null) { if (mRule == null) { Loading Loading @@ -588,6 +649,15 @@ public class AudioMix implements Parcelable { } } } } if (dapInjectionStarveManagement() && ((mRouteFlags & ROUTE_FLAG_LOOP_BACK) == ROUTE_FLAG_LOOP_BACK) && (mRule.getTargetMixType() != MIX_TYPE_RECORDERS) && (mInjectSilenceOnStarve)) { throw new IllegalArgumentException( "AudioMix.Builder.setInjectSilenceOnStarvation(true) called " + "on a non-injection AudioMix"); } if (mRule.allowPrivilegedMediaPlaybackCapture()) { if (mRule.allowPrivilegedMediaPlaybackCapture()) { String error = AudioMix.canBeUsedForPrivilegedMediaCapture(mFormat); String error = AudioMix.canBeUsedForPrivilegedMediaCapture(mFormat); if (error != null) { if (error != null) { Loading @@ -600,7 +670,7 @@ public class AudioMix implements Parcelable { } } return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType, return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType, mDeviceAddress, mToken, mVirtualDeviceId); mDeviceAddress, mToken, mVirtualDeviceId, mInjectSilenceOnStarve); } } private int getLoopbackDeviceSystemTypeForAudioMixingRule(AudioMixingRule rule) { private int getLoopbackDeviceSystemTypeForAudioMixingRule(AudioMixingRule rule) { Loading
services/core/java/com/android/server/audio/AudioService.java +3 −0 Original line number Original line Diff line number Diff line Loading @@ -53,6 +53,7 @@ import static android.media.audio.Flags.autoPublicVolumeApiHardening; import static android.media.audio.Flags.cacheGetStreamMinMaxVolume; import static android.media.audio.Flags.cacheGetStreamMinMaxVolume; import static android.media.audio.Flags.cacheGetStreamVolume; import static android.media.audio.Flags.cacheGetStreamVolume; import static android.media.audio.Flags.concurrentAudioRecordBypassPermission; import static android.media.audio.Flags.concurrentAudioRecordBypassPermission; import static android.media.audio.Flags.dapInjectionStarveManagement; import static android.media.audio.Flags.deviceVolumeApis; import static android.media.audio.Flags.deviceVolumeApis; import static android.media.audio.Flags.featureSpatialAudioHeadtrackingLowLatency; import static android.media.audio.Flags.featureSpatialAudioHeadtrackingLowLatency; import static android.media.audio.Flags.focusFreezeTestApi; import static android.media.audio.Flags.focusFreezeTestApi; Loading Loading @@ -5442,6 +5443,8 @@ public class AudioService extends IAudioService.Stub pw.println("\tandroid.media.audio.autoPublicVolumeApiHardening:" pw.println("\tandroid.media.audio.autoPublicVolumeApiHardening:" + autoPublicVolumeApiHardening()); + autoPublicVolumeApiHardening()); pw.println("\tandroid.media.audio.automaticBtDeviceType - EOL"); pw.println("\tandroid.media.audio.automaticBtDeviceType - EOL"); pw.println("\tandroid.media.audio.dapInjectionStarveManagement:" + dapInjectionStarveManagement()); pw.println("\tandroid.media.audio.featureSpatialAudioHeadtrackingLowLatency:" pw.println("\tandroid.media.audio.featureSpatialAudioHeadtrackingLowLatency:" + featureSpatialAudioHeadtrackingLowLatency()); + featureSpatialAudioHeadtrackingLowLatency()); pw.println("\tandroid.media.audio.focusFreezeTestApi:" pw.println("\tandroid.media.audio.focusFreezeTestApi:" Loading