Merge "Add support for audio session id based routing"
This commit is contained in:
committed by
Android (Google) Code Review
commit
a514c20292
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
/**
|
||||
@@ -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)
|
||||
@@ -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:
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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:
|
||||
@@ -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:
|
||||
|
||||
@@ -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!";
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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,
|
||||
@@ -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
|
||||
@@ -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") {
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user