Loading api/system-current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -23250,12 +23250,15 @@ package android.media.audiopolicy { public class AudioMixingRule { 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_UID = 4; // 0x4 } public static class AudioMixingRule.Builder { ctor public AudioMixingRule.Builder(); method public android.media.audiopolicy.AudioMixingRule.Builder addMixRule(int, java.lang.Object) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMixingRule.Builder addRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMixingRule build(); method public android.media.audiopolicy.AudioMixingRule.Builder excludeMixRule(int, java.lang.Object) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMixingRule.Builder excludeRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException; } media/java/android/media/audiopolicy/AudioMixingRule.java +237 −61 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.media.audiopolicy; import android.annotation.SystemApi; import android.media.AudioAttributes; import android.os.Parcel; import android.util.Log; import java.util.ArrayList; import java.util.Iterator; Loading Loading @@ -48,14 +49,27 @@ public class AudioMixingRule { /** * A rule requiring the usage information of the {@link AudioAttributes} to match. * This mixing rule can be added with {@link Builder#addRule(AudioAttributes, int)} or * {@link Builder#addMixRule(int, Object)} where the Object parameter is an instance of * {@link AudioAttributes}. */ @SystemApi public static final int RULE_MATCH_ATTRIBUTE_USAGE = 0x1; /** * A rule requiring the capture preset information of the {@link AudioAttributes} to match. * This mixing rule can be added with {@link Builder#addRule(AudioAttributes, int)} or * {@link Builder#addMixRule(int, Object)} where the Object parameter is an instance of * {@link AudioAttributes}. */ @SystemApi public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 0x1 << 1; /** * A rule requiring the UID of the audio stream to match that specified. * This mixing rule can be added with {@link Builder#addMixRule(int, Object)} where the Object * parameter is an instance of {@link java.lang.Integer}. */ @SystemApi public static final int RULE_MATCH_UID = 0x1 << 2; private final static int RULE_EXCLUSION_MASK = 0x8000; /** Loading @@ -70,29 +84,53 @@ public class AudioMixingRule { */ public static final int RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET = RULE_EXCLUSION_MASK | RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET; /** * @hide * A rule requiring the UID information to differ. */ public static final int RULE_EXCLUDE_UID = RULE_EXCLUSION_MASK | RULE_MATCH_UID; static final class AttributeMatchCriterion { AudioAttributes mAttr; int mRule; final AudioAttributes mAttr; final Integer mIntProp; final int mRule; /** input parameters must be valid */ AttributeMatchCriterion(AudioAttributes attributes, int rule) { mAttr = attributes; mIntProp = null; mRule = rule; } /** input parameters must be valid */ AttributeMatchCriterion(Integer intProp, int rule) { mAttr = null; mIntProp = intProp; mRule = rule; } @Override public int hashCode() { return Objects.hash(mAttr, mRule); return Objects.hash(mAttr, mIntProp, mRule); } void writeToParcel(Parcel dest) { dest.writeInt(mRule); if ((mRule == RULE_MATCH_ATTRIBUTE_USAGE) || (mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE)) { final int match_rule = mRule & ~RULE_EXCLUSION_MASK; switch (match_rule) { case RULE_MATCH_ATTRIBUTE_USAGE: dest.writeInt(mAttr.getUsage()); } else { // capture preset rule break; case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: dest.writeInt(mAttr.getCapturePreset()); break; case RULE_MATCH_UID: dest.writeInt(mIntProp.intValue()); break; default: Log.e("AttributeMatchCriterion", "Unknown match rule" + match_rule + " when writing to Parcel"); dest.writeInt(-1); } } } Loading @@ -111,18 +149,31 @@ public class AudioMixingRule { switch(rule) { case RULE_MATCH_ATTRIBUTE_USAGE: case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: case RULE_MATCH_UID: return true; default: return false; } } private static boolean isValidIntRule(int rule) { private static boolean isValidAttributesSystemApiRule(int rule) { switch(rule) { case RULE_MATCH_ATTRIBUTE_USAGE: case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: return true; default: return false; } } private static boolean isValidRule(int rule) { switch(rule) { case RULE_MATCH_ATTRIBUTE_USAGE: case RULE_EXCLUDE_ATTRIBUTE_USAGE: case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: case RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET: case RULE_MATCH_UID: case RULE_EXCLUDE_UID: return true; default: return false; Loading @@ -130,8 +181,24 @@ public class AudioMixingRule { } private static boolean isPlayerRule(int rule) { return ((rule == RULE_MATCH_ATTRIBUTE_USAGE) || (rule == RULE_EXCLUDE_ATTRIBUTE_USAGE)); final int match_rule = rule & ~RULE_EXCLUSION_MASK; switch (match_rule) { case RULE_MATCH_ATTRIBUTE_USAGE: case RULE_MATCH_UID: return true; default: return false; } } private static boolean isAudioAttributeRule(int match_rule) { switch(match_rule) { case RULE_MATCH_ATTRIBUTE_USAGE: case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: return true; default: return false; } } /** Loading @@ -158,14 +225,15 @@ public class AudioMixingRule { * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}. * @return the same Builder instance. * @throws IllegalArgumentException * @see {@link #excludeRule(AudioAttributes, int)} */ @SystemApi public Builder addRule(AudioAttributes attrToMatch, int rule) throws IllegalArgumentException { if (!isValidSystemApiRule(rule)) { if (!isValidAttributesSystemApiRule(rule)) { throw new IllegalArgumentException("Illegal rule value " + rule); } return addRuleInt(attrToMatch, rule); return checkAddRuleObjInternal(rule, attrToMatch); } /** Loading @@ -186,33 +254,82 @@ public class AudioMixingRule { * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}. * @return the same Builder instance. * @throws IllegalArgumentException * @see {@link #addRule(AudioAttributes, int)} */ @SystemApi public Builder excludeRule(AudioAttributes attrToMatch, int rule) throws IllegalArgumentException { if (!isValidAttributesSystemApiRule(rule)) { throw new IllegalArgumentException("Illegal rule value " + rule); } return checkAddRuleObjInternal(rule | RULE_EXCLUSION_MASK, attrToMatch); } /** * Add a rule for the selection of which streams are mixed together. * The rule defines what the matching will be made on. It also determines the type of the * property to match against. * @param rule one of {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or * {@link AudioMixingRule#RULE_MATCH_UID}. * @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. * @throws IllegalArgumentException * @see {@link #excludeMixRule(int, Object)} */ @SystemApi public Builder addMixRule(int rule, Object property) throws IllegalArgumentException { if (!isValidSystemApiRule(rule)) { throw new IllegalArgumentException("Illegal rule value " + rule); } return addRuleInt(attrToMatch, rule | RULE_EXCLUSION_MASK); return checkAddRuleObjInternal(rule, property); } /** * Add or exclude a rule for the selection of which streams are mixed together. * @param attrToMatch a non-null AudioAttributes instance for which a contradictory * rule hasn't been set yet. * @param rule one of {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, * Add a rule by exclusion for the selection of which streams are mixed together. * <br>For instance the following code * <br><pre> * AudioAttributes mediaAttr = new AudioAttributes.Builder() * .setUsage(AudioAttributes.USAGE_MEDIA) * .build(); * AudioMixingRule noMediaRule = new AudioMixingRule.Builder() * .addMixRule(AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE, mediaAttr) * .excludeMixRule(AudioMixingRule.RULE_MATCH_UID, new Integer(uidToExclude) * .build(); * </pre> * <br>will create a rule which maps to usage USAGE_MEDIA, but excludes any stream * coming from the specified UID. * @param rule one of {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or * {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET}. * {@link AudioMixingRule#RULE_MATCH_UID}. * @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. * @throws IllegalArgumentException */ Builder addRuleInt(AudioAttributes attrToMatch, int rule) @SystemApi public Builder excludeMixRule(int rule, Object property) throws IllegalArgumentException { if (!isValidSystemApiRule(rule)) { throw new IllegalArgumentException("Illegal rule value " + rule); } return checkAddRuleObjInternal(rule | RULE_EXCLUSION_MASK, property); } /** * Add or exclude a rule for the selection of which streams are mixed together. * Does error checking on the parameters. * @param rule * @param property * @return the same Builder instance. * @throws IllegalArgumentException */ private Builder checkAddRuleObjInternal(int rule, Object property) throws IllegalArgumentException { if (attrToMatch == null) { throw new IllegalArgumentException("Illegal null AudioAttributes argument"); if (property == null) { throw new IllegalArgumentException("Illegal null Object argument"); } if (!isValidIntRule(rule)) { if (!isValidRule(rule)) { throw new IllegalArgumentException("Illegal rule value " + rule); } else { // as rules are added to the Builder, we verify they are consistent with the type Loading @@ -229,36 +346,87 @@ public class AudioMixingRule { throw new IllegalArgumentException("Incompatible rule for mix"); } } final int match_rule = rule & ~RULE_EXCLUSION_MASK; if (isAudioAttributeRule(match_rule)) { if (!(property instanceof AudioAttributes)) { throw new IllegalArgumentException("Invalid AudioAttributes argument"); } return addRuleInternal((AudioAttributes) property, null, rule); } else { // implies integer match rule if (!(property instanceof Integer)) { throw new IllegalArgumentException("Invalid Integer argument"); } return addRuleInternal(null, (Integer) property, rule); } } /** * Add or exclude a rule on AudioAttributes or integer property for the selection of which * streams are mixed together. * No rule-to-parameter type check, all done in {@link #checkAddRuleObjInternal(int, Object)}. * Exceptions are thrown only when incompatible rules are added. * @param attrToMatch a non-null AudioAttributes instance for which a contradictory * rule hasn't been set yet, null if not used. * @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_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET}, * {@link AudioMixingRule#RULE_MATCH_UID}, {@link AudioMixingRule#RULE_EXCLUDE_UID}. * @return the same Builder instance. * @throws IllegalArgumentException */ private Builder addRuleInternal(AudioAttributes attrToMatch, Integer intProp, int rule) throws IllegalArgumentException { synchronized (mCriteria) { Iterator<AttributeMatchCriterion> crIterator = mCriteria.iterator(); final int match_rule = rule & ~RULE_EXCLUSION_MASK; while (crIterator.hasNext()) { final AttributeMatchCriterion criterion = crIterator.next(); if ((rule == RULE_MATCH_ATTRIBUTE_USAGE) || (rule == RULE_EXCLUDE_ATTRIBUTE_USAGE)) { switch (match_rule) { case RULE_MATCH_ATTRIBUTE_USAGE: // "usage"-based rule if (criterion.mAttr.getUsage() == attrToMatch.getUsage()) { if (criterion.mRule == rule) { // rule already exists, we're done return this; } else { // criterion already exists with a another rule, it is incompatible throw new IllegalArgumentException("Contradictory rule exists for " + attrToMatch); // criterion already exists with a another rule, // it is incompatible throw new IllegalArgumentException("Contradictory rule exists" + " for " + attrToMatch); } } } else if ((rule == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET) || (rule == RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET)) { break; case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: // "capture preset"-base rule if (criterion.mAttr.getCapturePreset() == attrToMatch.getCapturePreset()) { if (criterion.mRule == rule) { // rule already exists, we're done return this; } else { // criterion already exists with a another rule, it is incompatible throw new IllegalArgumentException("Contradictory rule exists for " + attrToMatch); // criterion already exists with a another rule, // it is incompatible throw new IllegalArgumentException("Contradictory rule exists" + " for " + attrToMatch); } } break; case RULE_MATCH_UID: // "usage"-based rule if (criterion.mIntProp.intValue() == intProp.intValue()) { if (criterion.mRule == rule) { // rule already exists, we're done return this; } else { // criterion already exists with a another rule, // it is incompatible throw new IllegalArgumentException("Contradictory rule exists" + " for UID " + intProp); } } break; } } // rule didn't exist, add it Loading @@ -268,22 +436,30 @@ public class AudioMixingRule { } Builder addRuleFromParcel(Parcel in) throws IllegalArgumentException { int rule = in.readInt(); AudioAttributes attr; if ((rule == RULE_MATCH_ATTRIBUTE_USAGE) || (rule == RULE_EXCLUDE_ATTRIBUTE_USAGE)) { final int rule = in.readInt(); final int match_rule = rule & ~RULE_EXCLUSION_MASK; AudioAttributes attr = null; Integer intProp = null; switch (match_rule) { case RULE_MATCH_ATTRIBUTE_USAGE: int usage = in.readInt(); attr = new AudioAttributes.Builder() .setUsage(usage).build(); } else if ((rule == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET) || (rule == RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET)) { break; case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: int preset = in.readInt(); attr = new AudioAttributes.Builder() .setInternalCapturePreset(preset).build(); } else { in.readInt(); // assume there was in int value to read as for now they come in pair break; case RULE_MATCH_UID: intProp = new Integer(in.readInt()); break; default: // assume there was in int value to read as for now they come in pair in.readInt(); throw new IllegalArgumentException("Illegal rule value " + rule + " in parcel"); } return addRuleInt(attr, rule); return addRuleInternal(attr, intProp, rule); } /** Loading media/java/android/media/audiopolicy/AudioPolicyConfig.java +8 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,14 @@ public class AudioPolicyConfig implements Parcelable { textDump += " match capture preset "; textDump += criterion.mAttr.getCapturePreset(); break; case AudioMixingRule.RULE_MATCH_UID: textDump += " match UID "; textDump += criterion.mIntProp.toString(); break; case AudioMixingRule.RULE_EXCLUDE_UID: textDump += " exclude UID "; textDump += criterion.mIntProp.toString(); break; default: textDump += "invalid rule!"; } Loading Loading
api/system-current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -23250,12 +23250,15 @@ package android.media.audiopolicy { public class AudioMixingRule { 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_UID = 4; // 0x4 } public static class AudioMixingRule.Builder { ctor public AudioMixingRule.Builder(); method public android.media.audiopolicy.AudioMixingRule.Builder addMixRule(int, java.lang.Object) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMixingRule.Builder addRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMixingRule build(); method public android.media.audiopolicy.AudioMixingRule.Builder excludeMixRule(int, java.lang.Object) throws java.lang.IllegalArgumentException; method public android.media.audiopolicy.AudioMixingRule.Builder excludeRule(android.media.AudioAttributes, int) throws java.lang.IllegalArgumentException; }
media/java/android/media/audiopolicy/AudioMixingRule.java +237 −61 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.media.audiopolicy; import android.annotation.SystemApi; import android.media.AudioAttributes; import android.os.Parcel; import android.util.Log; import java.util.ArrayList; import java.util.Iterator; Loading Loading @@ -48,14 +49,27 @@ public class AudioMixingRule { /** * A rule requiring the usage information of the {@link AudioAttributes} to match. * This mixing rule can be added with {@link Builder#addRule(AudioAttributes, int)} or * {@link Builder#addMixRule(int, Object)} where the Object parameter is an instance of * {@link AudioAttributes}. */ @SystemApi public static final int RULE_MATCH_ATTRIBUTE_USAGE = 0x1; /** * A rule requiring the capture preset information of the {@link AudioAttributes} to match. * This mixing rule can be added with {@link Builder#addRule(AudioAttributes, int)} or * {@link Builder#addMixRule(int, Object)} where the Object parameter is an instance of * {@link AudioAttributes}. */ @SystemApi public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 0x1 << 1; /** * A rule requiring the UID of the audio stream to match that specified. * This mixing rule can be added with {@link Builder#addMixRule(int, Object)} where the Object * parameter is an instance of {@link java.lang.Integer}. */ @SystemApi public static final int RULE_MATCH_UID = 0x1 << 2; private final static int RULE_EXCLUSION_MASK = 0x8000; /** Loading @@ -70,29 +84,53 @@ public class AudioMixingRule { */ public static final int RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET = RULE_EXCLUSION_MASK | RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET; /** * @hide * A rule requiring the UID information to differ. */ public static final int RULE_EXCLUDE_UID = RULE_EXCLUSION_MASK | RULE_MATCH_UID; static final class AttributeMatchCriterion { AudioAttributes mAttr; int mRule; final AudioAttributes mAttr; final Integer mIntProp; final int mRule; /** input parameters must be valid */ AttributeMatchCriterion(AudioAttributes attributes, int rule) { mAttr = attributes; mIntProp = null; mRule = rule; } /** input parameters must be valid */ AttributeMatchCriterion(Integer intProp, int rule) { mAttr = null; mIntProp = intProp; mRule = rule; } @Override public int hashCode() { return Objects.hash(mAttr, mRule); return Objects.hash(mAttr, mIntProp, mRule); } void writeToParcel(Parcel dest) { dest.writeInt(mRule); if ((mRule == RULE_MATCH_ATTRIBUTE_USAGE) || (mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE)) { final int match_rule = mRule & ~RULE_EXCLUSION_MASK; switch (match_rule) { case RULE_MATCH_ATTRIBUTE_USAGE: dest.writeInt(mAttr.getUsage()); } else { // capture preset rule break; case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: dest.writeInt(mAttr.getCapturePreset()); break; case RULE_MATCH_UID: dest.writeInt(mIntProp.intValue()); break; default: Log.e("AttributeMatchCriterion", "Unknown match rule" + match_rule + " when writing to Parcel"); dest.writeInt(-1); } } } Loading @@ -111,18 +149,31 @@ public class AudioMixingRule { switch(rule) { case RULE_MATCH_ATTRIBUTE_USAGE: case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: case RULE_MATCH_UID: return true; default: return false; } } private static boolean isValidIntRule(int rule) { private static boolean isValidAttributesSystemApiRule(int rule) { switch(rule) { case RULE_MATCH_ATTRIBUTE_USAGE: case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: return true; default: return false; } } private static boolean isValidRule(int rule) { switch(rule) { case RULE_MATCH_ATTRIBUTE_USAGE: case RULE_EXCLUDE_ATTRIBUTE_USAGE: case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: case RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET: case RULE_MATCH_UID: case RULE_EXCLUDE_UID: return true; default: return false; Loading @@ -130,8 +181,24 @@ public class AudioMixingRule { } private static boolean isPlayerRule(int rule) { return ((rule == RULE_MATCH_ATTRIBUTE_USAGE) || (rule == RULE_EXCLUDE_ATTRIBUTE_USAGE)); final int match_rule = rule & ~RULE_EXCLUSION_MASK; switch (match_rule) { case RULE_MATCH_ATTRIBUTE_USAGE: case RULE_MATCH_UID: return true; default: return false; } } private static boolean isAudioAttributeRule(int match_rule) { switch(match_rule) { case RULE_MATCH_ATTRIBUTE_USAGE: case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: return true; default: return false; } } /** Loading @@ -158,14 +225,15 @@ public class AudioMixingRule { * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}. * @return the same Builder instance. * @throws IllegalArgumentException * @see {@link #excludeRule(AudioAttributes, int)} */ @SystemApi public Builder addRule(AudioAttributes attrToMatch, int rule) throws IllegalArgumentException { if (!isValidSystemApiRule(rule)) { if (!isValidAttributesSystemApiRule(rule)) { throw new IllegalArgumentException("Illegal rule value " + rule); } return addRuleInt(attrToMatch, rule); return checkAddRuleObjInternal(rule, attrToMatch); } /** Loading @@ -186,33 +254,82 @@ public class AudioMixingRule { * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}. * @return the same Builder instance. * @throws IllegalArgumentException * @see {@link #addRule(AudioAttributes, int)} */ @SystemApi public Builder excludeRule(AudioAttributes attrToMatch, int rule) throws IllegalArgumentException { if (!isValidAttributesSystemApiRule(rule)) { throw new IllegalArgumentException("Illegal rule value " + rule); } return checkAddRuleObjInternal(rule | RULE_EXCLUSION_MASK, attrToMatch); } /** * Add a rule for the selection of which streams are mixed together. * The rule defines what the matching will be made on. It also determines the type of the * property to match against. * @param rule one of {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or * {@link AudioMixingRule#RULE_MATCH_UID}. * @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. * @throws IllegalArgumentException * @see {@link #excludeMixRule(int, Object)} */ @SystemApi public Builder addMixRule(int rule, Object property) throws IllegalArgumentException { if (!isValidSystemApiRule(rule)) { throw new IllegalArgumentException("Illegal rule value " + rule); } return addRuleInt(attrToMatch, rule | RULE_EXCLUSION_MASK); return checkAddRuleObjInternal(rule, property); } /** * Add or exclude a rule for the selection of which streams are mixed together. * @param attrToMatch a non-null AudioAttributes instance for which a contradictory * rule hasn't been set yet. * @param rule one of {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, * Add a rule by exclusion for the selection of which streams are mixed together. * <br>For instance the following code * <br><pre> * AudioAttributes mediaAttr = new AudioAttributes.Builder() * .setUsage(AudioAttributes.USAGE_MEDIA) * .build(); * AudioMixingRule noMediaRule = new AudioMixingRule.Builder() * .addMixRule(AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE, mediaAttr) * .excludeMixRule(AudioMixingRule.RULE_MATCH_UID, new Integer(uidToExclude) * .build(); * </pre> * <br>will create a rule which maps to usage USAGE_MEDIA, but excludes any stream * coming from the specified UID. * @param rule one of {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or * {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET}. * {@link AudioMixingRule#RULE_MATCH_UID}. * @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. * @throws IllegalArgumentException */ Builder addRuleInt(AudioAttributes attrToMatch, int rule) @SystemApi public Builder excludeMixRule(int rule, Object property) throws IllegalArgumentException { if (!isValidSystemApiRule(rule)) { throw new IllegalArgumentException("Illegal rule value " + rule); } return checkAddRuleObjInternal(rule | RULE_EXCLUSION_MASK, property); } /** * Add or exclude a rule for the selection of which streams are mixed together. * Does error checking on the parameters. * @param rule * @param property * @return the same Builder instance. * @throws IllegalArgumentException */ private Builder checkAddRuleObjInternal(int rule, Object property) throws IllegalArgumentException { if (attrToMatch == null) { throw new IllegalArgumentException("Illegal null AudioAttributes argument"); if (property == null) { throw new IllegalArgumentException("Illegal null Object argument"); } if (!isValidIntRule(rule)) { if (!isValidRule(rule)) { throw new IllegalArgumentException("Illegal rule value " + rule); } else { // as rules are added to the Builder, we verify they are consistent with the type Loading @@ -229,36 +346,87 @@ public class AudioMixingRule { throw new IllegalArgumentException("Incompatible rule for mix"); } } final int match_rule = rule & ~RULE_EXCLUSION_MASK; if (isAudioAttributeRule(match_rule)) { if (!(property instanceof AudioAttributes)) { throw new IllegalArgumentException("Invalid AudioAttributes argument"); } return addRuleInternal((AudioAttributes) property, null, rule); } else { // implies integer match rule if (!(property instanceof Integer)) { throw new IllegalArgumentException("Invalid Integer argument"); } return addRuleInternal(null, (Integer) property, rule); } } /** * Add or exclude a rule on AudioAttributes or integer property for the selection of which * streams are mixed together. * No rule-to-parameter type check, all done in {@link #checkAddRuleObjInternal(int, Object)}. * Exceptions are thrown only when incompatible rules are added. * @param attrToMatch a non-null AudioAttributes instance for which a contradictory * rule hasn't been set yet, null if not used. * @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_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET}, * {@link AudioMixingRule#RULE_MATCH_UID}, {@link AudioMixingRule#RULE_EXCLUDE_UID}. * @return the same Builder instance. * @throws IllegalArgumentException */ private Builder addRuleInternal(AudioAttributes attrToMatch, Integer intProp, int rule) throws IllegalArgumentException { synchronized (mCriteria) { Iterator<AttributeMatchCriterion> crIterator = mCriteria.iterator(); final int match_rule = rule & ~RULE_EXCLUSION_MASK; while (crIterator.hasNext()) { final AttributeMatchCriterion criterion = crIterator.next(); if ((rule == RULE_MATCH_ATTRIBUTE_USAGE) || (rule == RULE_EXCLUDE_ATTRIBUTE_USAGE)) { switch (match_rule) { case RULE_MATCH_ATTRIBUTE_USAGE: // "usage"-based rule if (criterion.mAttr.getUsage() == attrToMatch.getUsage()) { if (criterion.mRule == rule) { // rule already exists, we're done return this; } else { // criterion already exists with a another rule, it is incompatible throw new IllegalArgumentException("Contradictory rule exists for " + attrToMatch); // criterion already exists with a another rule, // it is incompatible throw new IllegalArgumentException("Contradictory rule exists" + " for " + attrToMatch); } } } else if ((rule == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET) || (rule == RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET)) { break; case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: // "capture preset"-base rule if (criterion.mAttr.getCapturePreset() == attrToMatch.getCapturePreset()) { if (criterion.mRule == rule) { // rule already exists, we're done return this; } else { // criterion already exists with a another rule, it is incompatible throw new IllegalArgumentException("Contradictory rule exists for " + attrToMatch); // criterion already exists with a another rule, // it is incompatible throw new IllegalArgumentException("Contradictory rule exists" + " for " + attrToMatch); } } break; case RULE_MATCH_UID: // "usage"-based rule if (criterion.mIntProp.intValue() == intProp.intValue()) { if (criterion.mRule == rule) { // rule already exists, we're done return this; } else { // criterion already exists with a another rule, // it is incompatible throw new IllegalArgumentException("Contradictory rule exists" + " for UID " + intProp); } } break; } } // rule didn't exist, add it Loading @@ -268,22 +436,30 @@ public class AudioMixingRule { } Builder addRuleFromParcel(Parcel in) throws IllegalArgumentException { int rule = in.readInt(); AudioAttributes attr; if ((rule == RULE_MATCH_ATTRIBUTE_USAGE) || (rule == RULE_EXCLUDE_ATTRIBUTE_USAGE)) { final int rule = in.readInt(); final int match_rule = rule & ~RULE_EXCLUSION_MASK; AudioAttributes attr = null; Integer intProp = null; switch (match_rule) { case RULE_MATCH_ATTRIBUTE_USAGE: int usage = in.readInt(); attr = new AudioAttributes.Builder() .setUsage(usage).build(); } else if ((rule == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET) || (rule == RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET)) { break; case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: int preset = in.readInt(); attr = new AudioAttributes.Builder() .setInternalCapturePreset(preset).build(); } else { in.readInt(); // assume there was in int value to read as for now they come in pair break; case RULE_MATCH_UID: intProp = new Integer(in.readInt()); break; default: // assume there was in int value to read as for now they come in pair in.readInt(); throw new IllegalArgumentException("Illegal rule value " + rule + " in parcel"); } return addRuleInt(attr, rule); return addRuleInternal(attr, intProp, rule); } /** Loading
media/java/android/media/audiopolicy/AudioPolicyConfig.java +8 −0 Original line number Diff line number Diff line Loading @@ -169,6 +169,14 @@ public class AudioPolicyConfig implements Parcelable { textDump += " match capture preset "; textDump += criterion.mAttr.getCapturePreset(); break; case AudioMixingRule.RULE_MATCH_UID: textDump += " match UID "; textDump += criterion.mIntProp.toString(); break; case AudioMixingRule.RULE_EXCLUDE_UID: textDump += " exclude UID "; textDump += criterion.mIntProp.toString(); break; default: textDump += "invalid rule!"; } Loading