Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a514c202 authored by Ján Sebechlebský's avatar Ján Sebechlebský Committed by Android (Google) Code Review
Browse files

Merge "Add support for audio session id based routing"

parents 04df6535 f28b1c66
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
  }
+5 −0
Original line number Diff line number Diff line
@@ -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);
+28 −4
Original line number Diff line number Diff line
@@ -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:
+8 −0
Original line number Diff line number Diff line
@@ -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!";
                }
+56 −1
Original line number Diff line number Diff line
@@ -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);
    }

}