blob: 8d8d000f467d1333b91c0dd1487d7722bb907aca [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.media.audio.cts;
import static org.testng.Assert.assertThrows;
import static org.testng.Assert.expectThrows;
import android.audio.policy.configuration.V7_0.AudioUsage;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.cts.NonMediaMainlineTest;
import android.os.Parcel;
import com.android.compatibility.common.util.CtsAndroidTestCase;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@NonMediaMainlineTest
public class AudioAttributesTest extends CtsAndroidTestCase {
// -----------------------------------------------------------------
// AUDIOATTRIBUTES TESTS:
// ----------------------------------
// -----------------------------------------------------------------
// Parcelable tests
// ----------------------------------
// Test case 1: call describeContents(), not used yet, but needs to be exercised
public void testParcelableDescribeContents() throws Exception {
final AudioAttributes aa = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA).build();
assertNotNull("Failure to create the AudioAttributes", aa);
assertEquals(0, aa.describeContents());
}
// Test case 2: create an instance, marshall it and create a new instance,
// check for equality, both by comparing fields, and with the equals(Object) method
public void testParcelableWriteToParcelCreate() throws Exception {
final AudioAttributes srcAttr = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED).build();
final Parcel srcParcel = Parcel.obtain();
final Parcel dstParcel = Parcel.obtain();
final byte[] mbytes;
srcAttr.writeToParcel(srcParcel, 0 /*no public flags for marshalling*/);
mbytes = srcParcel.marshall();
dstParcel.unmarshall(mbytes, 0, mbytes.length);
dstParcel.setDataPosition(0);
final AudioAttributes targetAttr = AudioAttributes.CREATOR.createFromParcel(dstParcel);
assertEquals("Marshalled/restored usage doesn't match",
srcAttr.getUsage(), targetAttr.getUsage());
assertEquals("Marshalled/restored content type doesn't match",
srcAttr.getContentType(), targetAttr.getContentType());
assertEquals("Marshalled/restored flags don't match",
srcAttr.getFlags(), targetAttr.getFlags());
assertTrue("Source and target attributes are not considered equal",
srcAttr.equals(targetAttr));
}
// Test case 3: verify going from AudioAttributes to stream type, with attributes built from
// stream type.
public void testGetVolumeControlStreamVsLegacyStream() throws Exception {
for (int testType : new int[] { AudioManager.STREAM_ALARM, AudioManager.STREAM_MUSIC,
AudioManager.STREAM_NOTIFICATION, AudioManager.STREAM_RING,
AudioManager.STREAM_SYSTEM, AudioManager.STREAM_VOICE_CALL}) {
final AudioAttributes aa = new AudioAttributes.Builder().setLegacyStreamType(testType)
.build();
final int stream = aa.getVolumeControlStream();
assertEquals("Volume control from attributes, stream doesn't match", testType, stream);
}
}
// -----------------------------------------------------------------
// Builder tests
// ----------------------------------
public void testInvalidUsage() {
assertThrows(IllegalArgumentException.class,
() -> { new AudioAttributes.Builder()
.setUsage(Integer.MIN_VALUE / 2) // some invalid value
.build();
});
}
public void testInvalidContentType() {
assertThrows(IllegalArgumentException.class,
() -> {
new AudioAttributes.Builder()
.setContentType(Integer.MIN_VALUE / 2) // some invalid value
.build();
} );
}
public void testDefaultUnknown() {
final AudioAttributes aa = new AudioAttributes.Builder()
.setFlags(AudioAttributes.ALLOW_CAPTURE_BY_ALL)
.build();
assertEquals("Unexpected default usage", AudioAttributes.USAGE_UNKNOWN, aa.getUsage());
assertEquals("Unexpected default content type",
AudioAttributes.CONTENT_TYPE_UNKNOWN, aa.getContentType());
}
// -----------------------------------------------------------------
// System usage tests
// ----------------------------------
public void testSetUsage_throwsWhenPassedSystemUsage()
throws NoSuchFieldException, IllegalAccessException {
int emergencySystemUsage = getEmergencySystemUsage();
AudioAttributes.Builder builder = new AudioAttributes.Builder();
assertThrows(IllegalArgumentException.class, () -> builder.setUsage(emergencySystemUsage));
}
public void testSetSystemUsage_throwsWhenPassedSdkUsage() {
InvocationTargetException e = expectThrows(InvocationTargetException.class, () -> {
setSystemUsage(new AudioAttributes.Builder(), AudioAttributes.USAGE_MEDIA);
});
assertEquals(IllegalArgumentException.class, e.getTargetException().getClass());
}
public void testBuild_throwsWhenSettingBothSystemAndSdkUsages()
throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException,
InvocationTargetException {
AudioAttributes.Builder builder = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA);
builder = setEmergencySystemUsage(builder);
assertThrows(IllegalArgumentException.class, builder::build);
}
public void testGetUsage_returnsUnknownWhenSystemUsageSet()
throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException,
InvocationTargetException {
AudioAttributes attributes = getAudioAttributesWithEmergencySystemUsage();
assertEquals(AudioAttributes.USAGE_UNKNOWN, attributes.getUsage());
}
public void testGetSystemUsage_returnsSetUsage()
throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.build();
assertEquals(AudioAttributes.USAGE_MEDIA, getSystemUsage(attributes));
}
public void testSpatializationAttr() {
for (int virtBehavior : new int[] { AudioAttributes.SPATIALIZATION_BEHAVIOR_AUTO,
AudioAttributes.SPATIALIZATION_BEHAVIOR_NEVER}) {
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setSpatializationBehavior(virtBehavior)
.build();
assertEquals("Spatialization behavior doesn't match", virtBehavior,
attributes.getSpatializationBehavior());
}
for (boolean isVirtualized : new boolean[] { true, false }) {
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setIsContentSpatialized(isVirtualized)
.build();
assertEquals("Is content virtualized doesn't match", isVirtualized,
attributes.isContentSpatialized());
}
}
// -----------------------------------------------------------------
// Capture policy tests
// ----------------------------------
public void testAllowedCapturePolicy() throws Exception {
for (int setPolicy : new int[] { AudioAttributes.ALLOW_CAPTURE_BY_ALL,
AudioAttributes.ALLOW_CAPTURE_BY_SYSTEM,
AudioAttributes.ALLOW_CAPTURE_BY_NONE }) {
final AudioAttributes aa = new AudioAttributes.Builder()
.setAllowedCapturePolicy(setPolicy).build();
final int getPolicy = aa.getAllowedCapturePolicy();
assertEquals("Allowed capture policy doesn't match", setPolicy, getPolicy);
}
}
public void testDefaultAllowedCapturePolicy() throws Exception {
final AudioAttributes aa = new AudioAttributes.Builder().build();
final int policy = aa.getAllowedCapturePolicy();
assertEquals("Wrong default capture policy", AudioAttributes.ALLOW_CAPTURE_BY_ALL, policy);
}
// -----------------------------------------------------------------
// Regression tests
// ----------------------------------
// Test against regression where setLegacyStreamType() was creating a different Builder
public void testSetLegacyStreamOnBuilder() throws Exception {
final int stream = AudioManager.STREAM_MUSIC;
AudioAttributes.Builder builder1 = new AudioAttributes.Builder();
builder1.setLegacyStreamType(stream);
AudioAttributes attr1 = builder1.build();
AudioAttributes.Builder builder2 = new AudioAttributes.Builder().setLegacyStreamType(stream);
AudioAttributes attr2 = builder2.build();
assertEquals(attr1, attr2);
}
/**
* Test AudioAttributes Builder error handling.
*
* @throws Exception
*/
public void testAudioAttributesBuilderError() throws Exception {
final int BIGNUM = Integer.MAX_VALUE;
assertThrows(IllegalArgumentException.class, () -> {
new AudioAttributes.Builder()
.setContentType(BIGNUM)
.build();
});
// TODO(b/207021564): This should throw IAE in AudioAttributes.Builder.
//assertThrows(IllegalArgumentException.class, () -> {
new AudioAttributes.Builder()
.setFlags(BIGNUM)
.build();
//});
// TODO(b/207016008): This should throw IAE in AudioAttributes.Builder.
//assertThrows(IllegalArgumentException.class, () -> {
new AudioAttributes.Builder()
.setLegacyStreamType(BIGNUM)
.build();
//});
assertThrows(IllegalArgumentException.class, () -> {
new AudioAttributes.Builder()
.setSpatializationBehavior(BIGNUM)
.build();
});
assertThrows(IllegalArgumentException.class, () -> {
new AudioAttributes.Builder()
.setUsage(BIGNUM)
.build();
});
}
// -----------------------------------------------------------------
// audio_policy_configuration.xsd converter tests
// ----------------------------------
public void testXsdStringToUsage_returnsCorrectUsage() {
int usage = AudioAttributes.xsdStringToUsage(AudioUsage.AUDIO_USAGE_MEDIA.toString());
assertEquals(AudioAttributes.USAGE_MEDIA, usage);
}
public void testXsdStringToUsage_withUnsupportedString_returnsUnknownUsage() {
int usage = AudioAttributes.xsdStringToUsage("not a usage");
assertEquals(AudioAttributes.USAGE_UNKNOWN, usage);
}
public void testUsageToXsdString_returnsCorrectString() {
String xsdUsage = AudioAttributes.usageToXsdString(AudioAttributes.USAGE_MEDIA);
assertEquals(AudioUsage.AUDIO_USAGE_MEDIA.toString(), xsdUsage);
}
// -------------------------------------------------------------------
// Reflection helpers for accessing system usage methods and fields
// -------------------------------------------------------------------
private static AudioAttributes getAudioAttributesWithEmergencySystemUsage()
throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException,
InvocationTargetException {
AudioAttributes.Builder builder = new AudioAttributes.Builder();
builder = setEmergencySystemUsage(builder);
return builder.build();
}
private static AudioAttributes.Builder setEmergencySystemUsage(AudioAttributes.Builder builder)
throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException,
InvocationTargetException {
int emergencySystemUsage = getEmergencySystemUsage();
return setSystemUsage(builder, emergencySystemUsage);
}
private static AudioAttributes.Builder setSystemUsage(AudioAttributes.Builder builder,
int systemUsage)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method setSystemUsageMethod = AudioAttributes.Builder.class
.getMethod("setSystemUsage", int.class);
return (AudioAttributes.Builder) setSystemUsageMethod.invoke(builder, systemUsage);
}
private static int getEmergencySystemUsage()
throws IllegalAccessException, NoSuchFieldException {
Field emergencyField = AudioAttributes.class.getDeclaredField("USAGE_EMERGENCY");
return emergencyField.getInt(null);
}
private static int getSystemUsage(AudioAttributes attributes)
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method getSystemUsageMethod = AudioAttributes.class.getMethod("getSystemUsage");
return (int) getSystemUsageMethod.invoke(attributes);
}
}