Loading api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -23829,6 +23829,7 @@ package android.media.audiopolicy { public static class AudioMix.Builder { ctor public AudioMix.Builder(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.Builder setDevice(android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix.Builder setFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException; } media/java/android/media/audiopolicy/AudioMix.java +84 −9 Original line number Diff line number Diff line Loading @@ -17,7 +17,9 @@ package android.media.audiopolicy; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; import android.media.AudioDeviceInfo; import android.media.AudioFormat; import android.media.AudioSystem; Loading @@ -36,19 +38,28 @@ public class AudioMix { private int mRouteFlags; private String mRegistrationId; private int mMixType = MIX_TYPE_INVALID; // written by AudioPolicy int mMixState = MIX_STATE_DISABLED; int mCallbackFlags; // initialized in constructor, read by AudioPolicyConfig final int mDeviceId; final String mDeviceAddress; /** * All parameters are guaranteed valid through the Builder. */ private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags) { private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags, int deviceId, String deviceAddress) { mRule = rule; mFormat = format; mRouteFlags = routeFlags; mRegistrationId = null; mMixType = rule.getTargetMixType(); mCallbackFlags = callbackFlags; mDeviceId = deviceId; mDeviceAddress = deviceAddress; } // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined Loading @@ -74,6 +85,8 @@ public class AudioMix { @SystemApi public static final int ROUTE_FLAG_LOOP_BACK = 0x1 << 1; private static final int ROUTE_FLAG_SUPPORTED = ROUTE_FLAG_RENDER | ROUTE_FLAG_LOOP_BACK; // MIX_TYPE_* values to keep in sync with frameworks/av/include/media/AudioPolicy.h /** * @hide Loading Loading @@ -172,6 +185,8 @@ public class AudioMix { private AudioFormat mFormat = null; private int mRouteFlags = 0; private int mCallbackFlags = 0; private int mDeviceId = -1; private String mDeviceAddress = null; /** * @hide Loading Loading @@ -200,7 +215,7 @@ public class AudioMix { * @return the same Builder instance. * @throws IllegalArgumentException */ public Builder setMixingRule(AudioMixingRule rule) Builder setMixingRule(AudioMixingRule rule) throws IllegalArgumentException { if (rule == null) { throw new IllegalArgumentException("Illegal null AudioMixingRule argument"); Loading @@ -216,7 +231,7 @@ public class AudioMix { * @return the same Builder instance. * @throws IllegalArgumentException */ public Builder setCallbackFlags(int flags) throws IllegalArgumentException { Builder setCallbackFlags(int flags) throws IllegalArgumentException { if ((flags != 0) && ((flags & CALLBACK_FLAGS_ALL) == 0)) { throw new IllegalArgumentException("Illegal callback flags 0x" + Integer.toHexString(flags).toUpperCase()); Loading @@ -225,6 +240,19 @@ public class AudioMix { return this; } /** * @hide * Only used by AudioPolicyConfig, not a public API. * @param deviceId * @param address * @return the same Builder instance. */ Builder setDevice(int deviceId, String address) { mDeviceId = deviceId; mDeviceAddress = address; return this; } /** * Sets the {@link AudioFormat} for the mix. * @param format a non-null {@link AudioFormat} instance. Loading @@ -242,7 +270,8 @@ public class AudioMix { } /** * Sets the routing behavior for the mix. * Sets the routing behavior for the mix. If not set, routing behavior will default to * {@link AudioMix#ROUTE_FLAG_LOOP_BACK}. * @param routeFlags one of {@link AudioMix#ROUTE_FLAG_LOOP_BACK}, * {@link AudioMix#ROUTE_FLAG_RENDER} * @return the same Builder instance. Loading @@ -254,14 +283,40 @@ public class AudioMix { if (routeFlags == 0) { throw new IllegalArgumentException("Illegal empty route flags"); } if ((routeFlags & (ROUTE_FLAG_LOOP_BACK | ROUTE_FLAG_RENDER)) == 0) { if ((routeFlags & ROUTE_FLAG_SUPPORTED) == 0) { throw new IllegalArgumentException("Invalid route flags 0x" + Integer.toHexString(routeFlags) + "when creating an AudioMix"); + Integer.toHexString(routeFlags) + "when configuring an AudioMix"); } if ((routeFlags & ~ROUTE_FLAG_SUPPORTED) != 0) { throw new IllegalArgumentException("Unknown route flags 0x" + Integer.toHexString(routeFlags) + "when configuring an AudioMix"); } mRouteFlags = routeFlags; return this; } /** * Sets the audio device used for playback. Cannot be used in the context of an audio * policy used to inject audio to be recorded, or in a mix whose route flags doesn't * specify {@link AudioMix#ROUTE_FLAG_RENDER}. * @param device a non-null AudioDeviceInfo describing the audio device to play the output * of this mix. * @return the same Builder instance * @throws IllegalArgumentException */ @SystemApi public Builder setDevice(@NonNull AudioDeviceInfo device) throws IllegalArgumentException { if (device == null) { throw new IllegalArgumentException("Illegal null AudioDeviceInfo argument"); } if (!device.isSink()) { throw new IllegalArgumentException("Unsupported device type on mix, not a sink"); } mDeviceId = device.getId(); mDeviceAddress = device.getAddress(); return this; } /** * Combines all of the settings and return a new {@link AudioMix} object. * @return a new {@link AudioMix} object Loading @@ -273,8 +328,13 @@ public class AudioMix { throw new IllegalArgumentException("Illegal null AudioMixingRule"); } if (mRouteFlags == 0) { // no route flags set, use default mRouteFlags = ROUTE_FLAG_RENDER; // no route flags set, use default as described in Builder.setRouteFlags(int) mRouteFlags = ROUTE_FLAG_LOOP_BACK; } // can't do loop back AND render at same time in this implementation if (mRouteFlags == (ROUTE_FLAG_RENDER | ROUTE_FLAG_LOOP_BACK)) { throw new IllegalArgumentException("Unsupported route behavior combination 0x" + Integer.toHexString(mRouteFlags)); } if (mFormat == null) { // FIXME Can we eliminate this? Will AudioMix work with an unspecified sample rate? Loading @@ -284,7 +344,22 @@ public class AudioMix { } mFormat = new AudioFormat.Builder().setSampleRate(rate).build(); } return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags); if (mDeviceId != -1) { if ((mRouteFlags & ROUTE_FLAG_RENDER) == 0) { throw new IllegalArgumentException( "Can't have audio device without flag ROUTE_FLAG_RENDER"); } if (mRule.getTargetMixType() != AudioMix.MIX_TYPE_PLAYERS) { throw new IllegalArgumentException("Unsupported device on non-playback mix"); } } else { if ((mRouteFlags & ROUTE_FLAG_RENDER) == ROUTE_FLAG_RENDER) { throw new IllegalArgumentException( "Can't have flag ROUTE_FLAG_RENDER without an audio device"); } } return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceId, mDeviceAddress); } } } media/java/android/media/audiopolicy/AudioPolicyConfig.java +15 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package android.media.audiopolicy; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioPatch; import android.media.audiopolicy.AudioMixingRule.AudioMixMatchCriterion; import android.os.Parcel; import android.os.Parcelable; Loading Loading @@ -81,6 +83,9 @@ public class AudioPolicyConfig implements Parcelable { dest.writeInt(mix.getRouteFlags()); // write callback flags dest.writeInt(mix.mCallbackFlags); // write device information dest.writeInt(mix.mDeviceId); dest.writeString(mix.mDeviceAddress); // write mix format dest.writeInt(mix.getFormat().getSampleRate()); dest.writeInt(mix.getFormat().getEncoding()); Loading @@ -104,6 +109,8 @@ public class AudioPolicyConfig implements Parcelable { mixBuilder.setRouteFlags(routeFlags); // read callback flags mixBuilder.setCallbackFlags(in.readInt()); // read device information mixBuilder.setDevice(in.readInt(), in.readString()); // read mix format int sampleRate = in.readInt(); int encoding = in.readInt(); Loading Loading @@ -197,8 +204,14 @@ public class AudioPolicyConfig implements Parcelable { int mixIndex = 0; for (AudioMix mix : mMixes) { if (!mRegistrationId.isEmpty()) { if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) == AudioMix.ROUTE_FLAG_LOOP_BACK) { mix.setRegistration(mRegistrationId + "mix" + mixTypeId(mix.getMixType()) + ":" + mixIndex++); } else if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_RENDER) == AudioMix.ROUTE_FLAG_RENDER) { mix.setRegistration(mix.mDeviceAddress); } } else { mix.setRegistration(""); } Loading Loading
api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -23829,6 +23829,7 @@ package android.media.audiopolicy { public static class AudioMix.Builder { ctor public AudioMix.Builder(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.Builder setDevice(android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix.Builder setFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException; }
media/java/android/media/audiopolicy/AudioMix.java +84 −9 Original line number Diff line number Diff line Loading @@ -17,7 +17,9 @@ package android.media.audiopolicy; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; import android.media.AudioDeviceInfo; import android.media.AudioFormat; import android.media.AudioSystem; Loading @@ -36,19 +38,28 @@ public class AudioMix { private int mRouteFlags; private String mRegistrationId; private int mMixType = MIX_TYPE_INVALID; // written by AudioPolicy int mMixState = MIX_STATE_DISABLED; int mCallbackFlags; // initialized in constructor, read by AudioPolicyConfig final int mDeviceId; final String mDeviceAddress; /** * All parameters are guaranteed valid through the Builder. */ private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags) { private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags, int deviceId, String deviceAddress) { mRule = rule; mFormat = format; mRouteFlags = routeFlags; mRegistrationId = null; mMixType = rule.getTargetMixType(); mCallbackFlags = callbackFlags; mDeviceId = deviceId; mDeviceAddress = deviceAddress; } // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined Loading @@ -74,6 +85,8 @@ public class AudioMix { @SystemApi public static final int ROUTE_FLAG_LOOP_BACK = 0x1 << 1; private static final int ROUTE_FLAG_SUPPORTED = ROUTE_FLAG_RENDER | ROUTE_FLAG_LOOP_BACK; // MIX_TYPE_* values to keep in sync with frameworks/av/include/media/AudioPolicy.h /** * @hide Loading Loading @@ -172,6 +185,8 @@ public class AudioMix { private AudioFormat mFormat = null; private int mRouteFlags = 0; private int mCallbackFlags = 0; private int mDeviceId = -1; private String mDeviceAddress = null; /** * @hide Loading Loading @@ -200,7 +215,7 @@ public class AudioMix { * @return the same Builder instance. * @throws IllegalArgumentException */ public Builder setMixingRule(AudioMixingRule rule) Builder setMixingRule(AudioMixingRule rule) throws IllegalArgumentException { if (rule == null) { throw new IllegalArgumentException("Illegal null AudioMixingRule argument"); Loading @@ -216,7 +231,7 @@ public class AudioMix { * @return the same Builder instance. * @throws IllegalArgumentException */ public Builder setCallbackFlags(int flags) throws IllegalArgumentException { Builder setCallbackFlags(int flags) throws IllegalArgumentException { if ((flags != 0) && ((flags & CALLBACK_FLAGS_ALL) == 0)) { throw new IllegalArgumentException("Illegal callback flags 0x" + Integer.toHexString(flags).toUpperCase()); Loading @@ -225,6 +240,19 @@ public class AudioMix { return this; } /** * @hide * Only used by AudioPolicyConfig, not a public API. * @param deviceId * @param address * @return the same Builder instance. */ Builder setDevice(int deviceId, String address) { mDeviceId = deviceId; mDeviceAddress = address; return this; } /** * Sets the {@link AudioFormat} for the mix. * @param format a non-null {@link AudioFormat} instance. Loading @@ -242,7 +270,8 @@ public class AudioMix { } /** * Sets the routing behavior for the mix. * Sets the routing behavior for the mix. If not set, routing behavior will default to * {@link AudioMix#ROUTE_FLAG_LOOP_BACK}. * @param routeFlags one of {@link AudioMix#ROUTE_FLAG_LOOP_BACK}, * {@link AudioMix#ROUTE_FLAG_RENDER} * @return the same Builder instance. Loading @@ -254,14 +283,40 @@ public class AudioMix { if (routeFlags == 0) { throw new IllegalArgumentException("Illegal empty route flags"); } if ((routeFlags & (ROUTE_FLAG_LOOP_BACK | ROUTE_FLAG_RENDER)) == 0) { if ((routeFlags & ROUTE_FLAG_SUPPORTED) == 0) { throw new IllegalArgumentException("Invalid route flags 0x" + Integer.toHexString(routeFlags) + "when creating an AudioMix"); + Integer.toHexString(routeFlags) + "when configuring an AudioMix"); } if ((routeFlags & ~ROUTE_FLAG_SUPPORTED) != 0) { throw new IllegalArgumentException("Unknown route flags 0x" + Integer.toHexString(routeFlags) + "when configuring an AudioMix"); } mRouteFlags = routeFlags; return this; } /** * Sets the audio device used for playback. Cannot be used in the context of an audio * policy used to inject audio to be recorded, or in a mix whose route flags doesn't * specify {@link AudioMix#ROUTE_FLAG_RENDER}. * @param device a non-null AudioDeviceInfo describing the audio device to play the output * of this mix. * @return the same Builder instance * @throws IllegalArgumentException */ @SystemApi public Builder setDevice(@NonNull AudioDeviceInfo device) throws IllegalArgumentException { if (device == null) { throw new IllegalArgumentException("Illegal null AudioDeviceInfo argument"); } if (!device.isSink()) { throw new IllegalArgumentException("Unsupported device type on mix, not a sink"); } mDeviceId = device.getId(); mDeviceAddress = device.getAddress(); return this; } /** * Combines all of the settings and return a new {@link AudioMix} object. * @return a new {@link AudioMix} object Loading @@ -273,8 +328,13 @@ public class AudioMix { throw new IllegalArgumentException("Illegal null AudioMixingRule"); } if (mRouteFlags == 0) { // no route flags set, use default mRouteFlags = ROUTE_FLAG_RENDER; // no route flags set, use default as described in Builder.setRouteFlags(int) mRouteFlags = ROUTE_FLAG_LOOP_BACK; } // can't do loop back AND render at same time in this implementation if (mRouteFlags == (ROUTE_FLAG_RENDER | ROUTE_FLAG_LOOP_BACK)) { throw new IllegalArgumentException("Unsupported route behavior combination 0x" + Integer.toHexString(mRouteFlags)); } if (mFormat == null) { // FIXME Can we eliminate this? Will AudioMix work with an unspecified sample rate? Loading @@ -284,7 +344,22 @@ public class AudioMix { } mFormat = new AudioFormat.Builder().setSampleRate(rate).build(); } return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags); if (mDeviceId != -1) { if ((mRouteFlags & ROUTE_FLAG_RENDER) == 0) { throw new IllegalArgumentException( "Can't have audio device without flag ROUTE_FLAG_RENDER"); } if (mRule.getTargetMixType() != AudioMix.MIX_TYPE_PLAYERS) { throw new IllegalArgumentException("Unsupported device on non-playback mix"); } } else { if ((mRouteFlags & ROUTE_FLAG_RENDER) == ROUTE_FLAG_RENDER) { throw new IllegalArgumentException( "Can't have flag ROUTE_FLAG_RENDER without an audio device"); } } return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceId, mDeviceAddress); } } }
media/java/android/media/audiopolicy/AudioPolicyConfig.java +15 −2 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package android.media.audiopolicy; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioPatch; import android.media.audiopolicy.AudioMixingRule.AudioMixMatchCriterion; import android.os.Parcel; import android.os.Parcelable; Loading Loading @@ -81,6 +83,9 @@ public class AudioPolicyConfig implements Parcelable { dest.writeInt(mix.getRouteFlags()); // write callback flags dest.writeInt(mix.mCallbackFlags); // write device information dest.writeInt(mix.mDeviceId); dest.writeString(mix.mDeviceAddress); // write mix format dest.writeInt(mix.getFormat().getSampleRate()); dest.writeInt(mix.getFormat().getEncoding()); Loading @@ -104,6 +109,8 @@ public class AudioPolicyConfig implements Parcelable { mixBuilder.setRouteFlags(routeFlags); // read callback flags mixBuilder.setCallbackFlags(in.readInt()); // read device information mixBuilder.setDevice(in.readInt(), in.readString()); // read mix format int sampleRate = in.readInt(); int encoding = in.readInt(); Loading Loading @@ -197,8 +204,14 @@ public class AudioPolicyConfig implements Parcelable { int mixIndex = 0; for (AudioMix mix : mMixes) { if (!mRegistrationId.isEmpty()) { if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) == AudioMix.ROUTE_FLAG_LOOP_BACK) { mix.setRegistration(mRegistrationId + "mix" + mixTypeId(mix.getMixType()) + ":" + mixIndex++); } else if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_RENDER) == AudioMix.ROUTE_FLAG_RENDER) { mix.setRegistration(mix.mDeviceAddress); } } else { mix.setRegistration(""); } Loading