Loading core/api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -6511,6 +6511,7 @@ package android.media.audiopolicy { field public static final int MIX_ROLE_PLAYERS = 0; // 0x0 field public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 2; // 0x2 field public static final int RULE_MATCH_ATTRIBUTE_USAGE = 1; // 0x1 field public static final int RULE_MATCH_AUDIO_SESSION_ID = 16; // 0x10 field public static final int RULE_MATCH_UID = 4; // 0x4 field public static final int RULE_MATCH_USERID = 8; // 0x8 } core/jni/android_media_AudioSystem.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -2160,6 +2160,11 @@ static jint convertAudioMixToNative(JNIEnv *env, nCriterion.mValue.mUserId = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mIntProp); break; case RULE_MATCH_AUDIO_SESSION_ID: { jint jAudioSessionId = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mIntProp); nCriterion.mValue.mAudioSessionId = static_cast<audio_session_t>(jAudioSessionId); } break; case RULE_MATCH_ATTRIBUTE_USAGE: case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: { jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr); Loading media/java/android/media/audiopolicy/AudioMixingRule.java +28 −4 Original line number Diff line number Diff line Loading @@ -87,6 +87,13 @@ public class AudioMixingRule { * parameter is an instance of {@link java.lang.Integer}. */ public static final int RULE_MATCH_USERID = 0x1 << 3; /** * A rule requiring the audio session id of the audio stream to match that specified. * This mixing rule can be added with {@link Builder#addMixRule(int, Object)} where Object * parameter is an instance of {@link java.lang.Integer}. * @see android.media.AudioTrack.Builder#setSessionId */ public static final int RULE_MATCH_AUDIO_SESSION_ID = 0x1 << 4; private final static int RULE_EXCLUSION_MASK = 0x8000; /** Loading Loading @@ -115,6 +122,13 @@ public class AudioMixingRule { public static final int RULE_EXCLUDE_USERID = RULE_EXCLUSION_MASK | RULE_MATCH_USERID; /** * @hide * A rule requiring the audio session id information to differ. */ public static final int RULE_EXCLUDE_AUDIO_SESSION_ID = RULE_EXCLUSION_MASK | RULE_MATCH_AUDIO_SESSION_ID; /** @hide */ public static final class AudioMixMatchCriterion { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Loading Loading @@ -166,6 +180,7 @@ public class AudioMixingRule { break; case RULE_MATCH_UID: case RULE_MATCH_USERID: case RULE_MATCH_AUDIO_SESSION_ID: dest.writeInt(mIntProp); break; default: Loading Loading @@ -315,6 +330,7 @@ public class AudioMixingRule { case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: case RULE_MATCH_UID: case RULE_MATCH_USERID: case RULE_MATCH_AUDIO_SESSION_ID: return true; default: return false; Loading @@ -338,6 +354,7 @@ public class AudioMixingRule { case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: case RULE_MATCH_UID: case RULE_MATCH_USERID: case RULE_MATCH_AUDIO_SESSION_ID: return true; default: return false; Loading Loading @@ -445,7 +462,8 @@ public class AudioMixingRule { * @param rule one of {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or * {@link AudioMixingRule#RULE_MATCH_UID} or * {@link AudioMixingRule#RULE_MATCH_USERID}. * {@link AudioMixingRule#RULE_MATCH_USERID} or * {@link AudioMixingRule#RULE_MATCH_AUDIO_SESSION_ID}. * @param property see the definition of each rule for the type to use (either an * {@link AudioAttributes} or an {@link java.lang.Integer}). * @return the same Builder instance. Loading Loading @@ -476,7 +494,8 @@ public class AudioMixingRule { * @param rule one of {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or * {@link AudioMixingRule#RULE_MATCH_UID} or * {@link AudioMixingRule#RULE_MATCH_USERID}. * {@link AudioMixingRule#RULE_MATCH_USERID} or * {@link AudioMixingRule#RULE_MATCH_AUDIO_SESSION_ID}. * @param property see the definition of each rule for the type to use (either an * {@link AudioAttributes} or an {@link java.lang.Integer}). * @return the same Builder instance. Loading Loading @@ -606,9 +625,12 @@ public class AudioMixingRule { * @param intProp an integer property to match or exclude, null if not used. * @param rule one of {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}, * {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET}, * {@link AudioMixingRule#RULE_MATCH_UID}, {@link AudioMixingRule#RULE_EXCLUDE_UID}. * {@link AudioMixingRule#RULE_MATCH_UID}, * {@link AudioMixingRule#RULE_EXCLUDE_UID}, * {@link AudioMixingRule#RULE_MATCH_AUDIO_SESSION_ID}, * {@link AudioMixingRule#RULE_EXCLUDE_AUDIO_SESSION_ID} * {@link AudioMixingRule#RULE_MATCH_USERID}, * {@link AudioMixingRule#RULE_EXCLUDE_USERID}. * @return the same Builder instance. Loading Loading @@ -645,6 +667,7 @@ public class AudioMixingRule { break; case RULE_MATCH_UID: case RULE_MATCH_USERID: case RULE_MATCH_AUDIO_SESSION_ID: mCriteria.add(new AudioMixMatchCriterion(intProp, rule)); break; default: Loading @@ -666,6 +689,7 @@ public class AudioMixingRule { break; case RULE_MATCH_UID: case RULE_MATCH_USERID: case RULE_MATCH_AUDIO_SESSION_ID: intProp = new Integer(in.readInt()); break; default: Loading media/java/android/media/audiopolicy/AudioPolicyConfig.java +8 −0 Original line number Diff line number Diff line Loading @@ -217,6 +217,14 @@ public class AudioPolicyConfig implements Parcelable { textDump += " exclude userId "; textDump += criterion.mIntProp; break; case AudioMixingRule.RULE_MATCH_AUDIO_SESSION_ID: textDump += " match audio session id"; textDump += criterion.mIntProp; break; case AudioMixingRule.RULE_EXCLUDE_AUDIO_SESSION_ID: textDump += " exclude audio session id "; textDump += criterion.mIntProp; break; default: textDump += "invalid rule!"; } Loading media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixingRuleUnitTests.java +56 −1 Original line number Diff line number Diff line Loading @@ -22,9 +22,11 @@ import static android.media.audiopolicy.AudioMixingRule.MIX_ROLE_INJECTOR; import static android.media.audiopolicy.AudioMixingRule.MIX_ROLE_PLAYERS; import static android.media.audiopolicy.AudioMixingRule.RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET; import static android.media.audiopolicy.AudioMixingRule.RULE_EXCLUDE_ATTRIBUTE_USAGE; import static android.media.audiopolicy.AudioMixingRule.RULE_EXCLUDE_AUDIO_SESSION_ID; import static android.media.audiopolicy.AudioMixingRule.RULE_EXCLUDE_UID; import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET; import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE; import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_AUDIO_SESSION_ID; import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_UID; import static org.hamcrest.MatcherAssert.assertThat; Loading Loading @@ -61,12 +63,14 @@ public class AudioMixingRuleUnitTests { new AudioAttributes.Builder().setCapturePreset(VOICE_RECOGNITION).build(); private static final int TEST_UID = 42; private static final int OTHER_UID = 77; private static final int TEST_SESSION_ID = 1234; @Test public void testConstructValidRule() { AudioMixingRule rule = new AudioMixingRule.Builder() .addMixRule(RULE_MATCH_ATTRIBUTE_USAGE, USAGE_MEDIA_AUDIO_ATTRIBUTES) .addMixRule(RULE_MATCH_UID, TEST_UID) .excludeMixRule(RULE_MATCH_AUDIO_SESSION_ID, TEST_SESSION_ID) .build(); // Based on the rules, the mix type should fall back to MIX_ROLE_PLAYERS, Loading @@ -74,7 +78,8 @@ public class AudioMixingRuleUnitTests { assertEquals(rule.getTargetMixRole(), MIX_ROLE_PLAYERS); assertThat(rule.getCriteria(), containsInAnyOrder( isAudioMixMatchUsageCriterion(USAGE_MEDIA), isAudioMixMatchUidCriterion(TEST_UID))); isAudioMixMatchUidCriterion(TEST_UID), isAudioMixExcludeSessionCriterion(TEST_SESSION_ID))); } @Test Loading Loading @@ -183,6 +188,30 @@ public class AudioMixingRuleUnitTests { .build()); } @Test public void sessionIdRuleCompatibleWithPlayersMix() { int sessionId = 42; AudioMixingRule rule = new AudioMixingRule.Builder() .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, sessionId) .setTargetMixRole(MIX_ROLE_PLAYERS) .build(); assertEquals(rule.getTargetMixRole(), MIX_ROLE_PLAYERS); assertThat(rule.getCriteria(), containsInAnyOrder(isAudioMixSessionCriterion(sessionId))); } @Test public void sessionIdRuleCompatibleWithInjectorMix() { AudioMixingRule rule = new AudioMixingRule.Builder() .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, TEST_SESSION_ID) .setTargetMixRole(MIX_ROLE_INJECTOR) .build(); assertEquals(rule.getTargetMixRole(), MIX_ROLE_INJECTOR); assertThat(rule.getCriteria(), containsInAnyOrder(isAudioMixSessionCriterion(TEST_SESSION_ID))); } private static Matcher isAudioMixUidCriterion(int uid, boolean exclude) { return new CustomTypeSafeMatcher<AudioMixMatchCriterion>("uid mix criterion") { Loading Loading @@ -257,5 +286,31 @@ public class AudioMixingRuleUnitTests { return isAudioMixUsageCriterion(usage, /*exclude=*/ false); } private static Matcher isAudioMixSessionCriterion(int sessionId, boolean exclude) { return new CustomTypeSafeMatcher<AudioMixMatchCriterion>("sessionId mix criterion") { @Override public boolean matchesSafely(AudioMixMatchCriterion item) { int excludeRule = exclude ? RULE_EXCLUDE_AUDIO_SESSION_ID : RULE_MATCH_AUDIO_SESSION_ID; return item.getRule() == excludeRule && item.getIntProp() == sessionId; } @Override public void describeMismatchSafely( AudioMixMatchCriterion item, Description mismatchDescription) { mismatchDescription.appendText( String.format("is not %s criterion with session id %d", exclude ? "exclude" : "match", sessionId)); } }; } private static Matcher isAudioMixSessionCriterion(int sessionId) { return isAudioMixSessionCriterion(sessionId, /*exclude=*/ false); } private static Matcher isAudioMixExcludeSessionCriterion(int sessionId) { return isAudioMixSessionCriterion(sessionId, /*exclude=*/ true); } } Loading
core/api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -6511,6 +6511,7 @@ package android.media.audiopolicy { field public static final int MIX_ROLE_PLAYERS = 0; // 0x0 field public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 2; // 0x2 field public static final int RULE_MATCH_ATTRIBUTE_USAGE = 1; // 0x1 field public static final int RULE_MATCH_AUDIO_SESSION_ID = 16; // 0x10 field public static final int RULE_MATCH_UID = 4; // 0x4 field public static final int RULE_MATCH_USERID = 8; // 0x8 }
core/jni/android_media_AudioSystem.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -2160,6 +2160,11 @@ static jint convertAudioMixToNative(JNIEnv *env, nCriterion.mValue.mUserId = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mIntProp); break; case RULE_MATCH_AUDIO_SESSION_ID: { jint jAudioSessionId = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mIntProp); nCriterion.mValue.mAudioSessionId = static_cast<audio_session_t>(jAudioSessionId); } break; case RULE_MATCH_ATTRIBUTE_USAGE: case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: { jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr); Loading
media/java/android/media/audiopolicy/AudioMixingRule.java +28 −4 Original line number Diff line number Diff line Loading @@ -87,6 +87,13 @@ public class AudioMixingRule { * parameter is an instance of {@link java.lang.Integer}. */ public static final int RULE_MATCH_USERID = 0x1 << 3; /** * A rule requiring the audio session id of the audio stream to match that specified. * This mixing rule can be added with {@link Builder#addMixRule(int, Object)} where Object * parameter is an instance of {@link java.lang.Integer}. * @see android.media.AudioTrack.Builder#setSessionId */ public static final int RULE_MATCH_AUDIO_SESSION_ID = 0x1 << 4; private final static int RULE_EXCLUSION_MASK = 0x8000; /** Loading Loading @@ -115,6 +122,13 @@ public class AudioMixingRule { public static final int RULE_EXCLUDE_USERID = RULE_EXCLUSION_MASK | RULE_MATCH_USERID; /** * @hide * A rule requiring the audio session id information to differ. */ public static final int RULE_EXCLUDE_AUDIO_SESSION_ID = RULE_EXCLUSION_MASK | RULE_MATCH_AUDIO_SESSION_ID; /** @hide */ public static final class AudioMixMatchCriterion { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) Loading Loading @@ -166,6 +180,7 @@ public class AudioMixingRule { break; case RULE_MATCH_UID: case RULE_MATCH_USERID: case RULE_MATCH_AUDIO_SESSION_ID: dest.writeInt(mIntProp); break; default: Loading Loading @@ -315,6 +330,7 @@ public class AudioMixingRule { case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: case RULE_MATCH_UID: case RULE_MATCH_USERID: case RULE_MATCH_AUDIO_SESSION_ID: return true; default: return false; Loading @@ -338,6 +354,7 @@ public class AudioMixingRule { case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: case RULE_MATCH_UID: case RULE_MATCH_USERID: case RULE_MATCH_AUDIO_SESSION_ID: return true; default: return false; Loading Loading @@ -445,7 +462,8 @@ public class AudioMixingRule { * @param rule one of {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or * {@link AudioMixingRule#RULE_MATCH_UID} or * {@link AudioMixingRule#RULE_MATCH_USERID}. * {@link AudioMixingRule#RULE_MATCH_USERID} or * {@link AudioMixingRule#RULE_MATCH_AUDIO_SESSION_ID}. * @param property see the definition of each rule for the type to use (either an * {@link AudioAttributes} or an {@link java.lang.Integer}). * @return the same Builder instance. Loading Loading @@ -476,7 +494,8 @@ public class AudioMixingRule { * @param rule one of {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or * {@link AudioMixingRule#RULE_MATCH_UID} or * {@link AudioMixingRule#RULE_MATCH_USERID}. * {@link AudioMixingRule#RULE_MATCH_USERID} or * {@link AudioMixingRule#RULE_MATCH_AUDIO_SESSION_ID}. * @param property see the definition of each rule for the type to use (either an * {@link AudioAttributes} or an {@link java.lang.Integer}). * @return the same Builder instance. Loading Loading @@ -606,9 +625,12 @@ public class AudioMixingRule { * @param intProp an integer property to match or exclude, null if not used. * @param rule one of {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}, * {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET}, * {@link AudioMixingRule#RULE_MATCH_UID}, {@link AudioMixingRule#RULE_EXCLUDE_UID}. * {@link AudioMixingRule#RULE_MATCH_UID}, * {@link AudioMixingRule#RULE_EXCLUDE_UID}, * {@link AudioMixingRule#RULE_MATCH_AUDIO_SESSION_ID}, * {@link AudioMixingRule#RULE_EXCLUDE_AUDIO_SESSION_ID} * {@link AudioMixingRule#RULE_MATCH_USERID}, * {@link AudioMixingRule#RULE_EXCLUDE_USERID}. * @return the same Builder instance. Loading Loading @@ -645,6 +667,7 @@ public class AudioMixingRule { break; case RULE_MATCH_UID: case RULE_MATCH_USERID: case RULE_MATCH_AUDIO_SESSION_ID: mCriteria.add(new AudioMixMatchCriterion(intProp, rule)); break; default: Loading @@ -666,6 +689,7 @@ public class AudioMixingRule { break; case RULE_MATCH_UID: case RULE_MATCH_USERID: case RULE_MATCH_AUDIO_SESSION_ID: intProp = new Integer(in.readInt()); break; default: Loading
media/java/android/media/audiopolicy/AudioPolicyConfig.java +8 −0 Original line number Diff line number Diff line Loading @@ -217,6 +217,14 @@ public class AudioPolicyConfig implements Parcelable { textDump += " exclude userId "; textDump += criterion.mIntProp; break; case AudioMixingRule.RULE_MATCH_AUDIO_SESSION_ID: textDump += " match audio session id"; textDump += criterion.mIntProp; break; case AudioMixingRule.RULE_EXCLUDE_AUDIO_SESSION_ID: textDump += " exclude audio session id "; textDump += criterion.mIntProp; break; default: textDump += "invalid rule!"; } Loading
media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixingRuleUnitTests.java +56 −1 Original line number Diff line number Diff line Loading @@ -22,9 +22,11 @@ import static android.media.audiopolicy.AudioMixingRule.MIX_ROLE_INJECTOR; import static android.media.audiopolicy.AudioMixingRule.MIX_ROLE_PLAYERS; import static android.media.audiopolicy.AudioMixingRule.RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET; import static android.media.audiopolicy.AudioMixingRule.RULE_EXCLUDE_ATTRIBUTE_USAGE; import static android.media.audiopolicy.AudioMixingRule.RULE_EXCLUDE_AUDIO_SESSION_ID; import static android.media.audiopolicy.AudioMixingRule.RULE_EXCLUDE_UID; import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET; import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE; import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_AUDIO_SESSION_ID; import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_UID; import static org.hamcrest.MatcherAssert.assertThat; Loading Loading @@ -61,12 +63,14 @@ public class AudioMixingRuleUnitTests { new AudioAttributes.Builder().setCapturePreset(VOICE_RECOGNITION).build(); private static final int TEST_UID = 42; private static final int OTHER_UID = 77; private static final int TEST_SESSION_ID = 1234; @Test public void testConstructValidRule() { AudioMixingRule rule = new AudioMixingRule.Builder() .addMixRule(RULE_MATCH_ATTRIBUTE_USAGE, USAGE_MEDIA_AUDIO_ATTRIBUTES) .addMixRule(RULE_MATCH_UID, TEST_UID) .excludeMixRule(RULE_MATCH_AUDIO_SESSION_ID, TEST_SESSION_ID) .build(); // Based on the rules, the mix type should fall back to MIX_ROLE_PLAYERS, Loading @@ -74,7 +78,8 @@ public class AudioMixingRuleUnitTests { assertEquals(rule.getTargetMixRole(), MIX_ROLE_PLAYERS); assertThat(rule.getCriteria(), containsInAnyOrder( isAudioMixMatchUsageCriterion(USAGE_MEDIA), isAudioMixMatchUidCriterion(TEST_UID))); isAudioMixMatchUidCriterion(TEST_UID), isAudioMixExcludeSessionCriterion(TEST_SESSION_ID))); } @Test Loading Loading @@ -183,6 +188,30 @@ public class AudioMixingRuleUnitTests { .build()); } @Test public void sessionIdRuleCompatibleWithPlayersMix() { int sessionId = 42; AudioMixingRule rule = new AudioMixingRule.Builder() .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, sessionId) .setTargetMixRole(MIX_ROLE_PLAYERS) .build(); assertEquals(rule.getTargetMixRole(), MIX_ROLE_PLAYERS); assertThat(rule.getCriteria(), containsInAnyOrder(isAudioMixSessionCriterion(sessionId))); } @Test public void sessionIdRuleCompatibleWithInjectorMix() { AudioMixingRule rule = new AudioMixingRule.Builder() .addMixRule(RULE_MATCH_AUDIO_SESSION_ID, TEST_SESSION_ID) .setTargetMixRole(MIX_ROLE_INJECTOR) .build(); assertEquals(rule.getTargetMixRole(), MIX_ROLE_INJECTOR); assertThat(rule.getCriteria(), containsInAnyOrder(isAudioMixSessionCriterion(TEST_SESSION_ID))); } private static Matcher isAudioMixUidCriterion(int uid, boolean exclude) { return new CustomTypeSafeMatcher<AudioMixMatchCriterion>("uid mix criterion") { Loading Loading @@ -257,5 +286,31 @@ public class AudioMixingRuleUnitTests { return isAudioMixUsageCriterion(usage, /*exclude=*/ false); } private static Matcher isAudioMixSessionCriterion(int sessionId, boolean exclude) { return new CustomTypeSafeMatcher<AudioMixMatchCriterion>("sessionId mix criterion") { @Override public boolean matchesSafely(AudioMixMatchCriterion item) { int excludeRule = exclude ? RULE_EXCLUDE_AUDIO_SESSION_ID : RULE_MATCH_AUDIO_SESSION_ID; return item.getRule() == excludeRule && item.getIntProp() == sessionId; } @Override public void describeMismatchSafely( AudioMixMatchCriterion item, Description mismatchDescription) { mismatchDescription.appendText( String.format("is not %s criterion with session id %d", exclude ? "exclude" : "match", sessionId)); } }; } private static Matcher isAudioMixSessionCriterion(int sessionId) { return isAudioMixSessionCriterion(sessionId, /*exclude=*/ false); } private static Matcher isAudioMixExcludeSessionCriterion(int sessionId) { return isAudioMixSessionCriterion(sessionId, /*exclude=*/ true); } }