1a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi/* 2a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Copyright (C) 2014 The Android Open Source Project 3a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * 4a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 5a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * you may not use this file except in compliance with the License. 6a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * You may obtain a copy of the License at 7a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * 8a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 9a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * 10a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 11a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 12a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * See the License for the specific language governing permissions and 14a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * limitations under the License. 15a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */ 16a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 17a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivipackage android.media.audiopolicy; 18a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 191b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Triviimport android.annotation.SystemApi; 20a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.media.AudioAttributes; 211b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Triviimport android.os.Parcel; 22a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 23a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport java.util.ArrayList; 24a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport java.util.Iterator; 251b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Triviimport java.util.Objects; 26a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 27a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 28a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi/** 298fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi * @hide 30a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * 31a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Here's an example of creating a mixing rule for all media playback: 32a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * <pre> 33a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * AudioAttributes mediaAttr = new AudioAttributes.Builder() 34a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * .setUsage(AudioAttributes.USAGE_MEDIA) 35a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * .build(); 36a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * AudioMixingRule mediaRule = new AudioMixingRule.Builder() 37a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * .addRule(mediaAttr, AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE) 38a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * .build(); 39a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * </pre> 40a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */ 411b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi@SystemApi 42a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivipublic class AudioMixingRule { 43a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 441b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi private AudioMixingRule(int mixType, ArrayList<AttributeMatchCriterion> criteria) { 45a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi mCriteria = criteria; 461b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi mTargetMixType = mixType; 47a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 48a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 49a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi /** 501b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * A rule requiring the usage information of the {@link AudioAttributes} to match. 51a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */ 521b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi @SystemApi 53a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi public static final int RULE_MATCH_ATTRIBUTE_USAGE = 0x1; 54a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi /** 551b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * A rule requiring the capture preset information of the {@link AudioAttributes} to match. 56a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */ 571b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi @SystemApi 581b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi public static final int RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET = 0x1 << 1; 591b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 601b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi private final static int RULE_EXCLUSION_MASK = 0x8000; 611b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi /** 621b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * @hide 631b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * A rule requiring the usage information of the {@link AudioAttributes} to differ. 641b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi */ 651b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi public static final int RULE_EXCLUDE_ATTRIBUTE_USAGE = 661b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi RULE_EXCLUSION_MASK | RULE_MATCH_ATTRIBUTE_USAGE; 671b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi /** 681b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * @hide 691b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * A rule requiring the capture preset information of the {@link AudioAttributes} to differ. 701b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi */ 711b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi public static final int RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET = 721b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi RULE_EXCLUSION_MASK | RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET; 73a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 74a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi static final class AttributeMatchCriterion { 75a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi AudioAttributes mAttr; 76a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi int mRule; 77a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 781b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi /** input parameters must be valid */ 79a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi AttributeMatchCriterion(AudioAttributes attributes, int rule) { 80a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi mAttr = attributes; 81a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi mRule = rule; 82a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 831b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 841b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi @Override 851b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi public int hashCode() { 861b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return Objects.hash(mAttr, mRule); 871b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 881b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 891b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi void writeToParcel(Parcel dest) { 901b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi dest.writeInt(mRule); 911b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi if ((mRule == RULE_MATCH_ATTRIBUTE_USAGE) || (mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE)) { 921b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi dest.writeInt(mAttr.getUsage()); 931b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } else { 941b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi // capture preset rule 951b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi dest.writeInt(mAttr.getCapturePreset()); 961b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 971b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 98a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 99a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 1001b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi private final int mTargetMixType; 1011b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi int getTargetMixType() { return mTargetMixType; } 1021b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi private final ArrayList<AttributeMatchCriterion> mCriteria; 103a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi ArrayList<AttributeMatchCriterion> getCriteria() { return mCriteria; } 104a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 1051b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi @Override 1061b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi public int hashCode() { 1071b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return Objects.hash(mTargetMixType, mCriteria); 1081b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 1091b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 1101b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi private static boolean isValidSystemApiRule(int rule) { 1111b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi switch(rule) { 1121b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi case RULE_MATCH_ATTRIBUTE_USAGE: 1131b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: 1141b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return true; 1151b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi default: 1161b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return false; 1171b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 1181b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 1191b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 1201b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi private static boolean isValidIntRule(int rule) { 1211b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi switch(rule) { 1221b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi case RULE_MATCH_ATTRIBUTE_USAGE: 1231b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi case RULE_EXCLUDE_ATTRIBUTE_USAGE: 1241b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: 1251b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi case RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET: 1261b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return true; 1271b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi default: 1281b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return false; 1291b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 1301b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 1311b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 1321b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi private static boolean isPlayerRule(int rule) { 1331b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return ((rule == RULE_MATCH_ATTRIBUTE_USAGE) 1341b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi || (rule == RULE_EXCLUDE_ATTRIBUTE_USAGE)); 1351b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 1361b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 137a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi /** 138a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Builder class for {@link AudioMixingRule} objects 139a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */ 1401b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi @SystemApi 141a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi public static class Builder { 142a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi private ArrayList<AttributeMatchCriterion> mCriteria; 1431b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi private int mTargetMixType = AudioMix.MIX_TYPE_INVALID; 144a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 145a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi /** 146a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Constructs a new Builder with no rules. 147a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */ 1481b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi @SystemApi 149a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi public Builder() { 150a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi mCriteria = new ArrayList<AttributeMatchCriterion>(); 151a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 152a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 153a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi /** 154a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Add a rule for the selection of which streams are mixed together. 155a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * @param attrToMatch a non-null AudioAttributes instance for which a contradictory 156a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * rule hasn't been set yet. 1571b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * @param rule {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE} or 1581b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}. 159a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * @return the same Builder instance. 160a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * @throws IllegalArgumentException 161a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */ 1621b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi @SystemApi 163a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi public Builder addRule(AudioAttributes attrToMatch, int rule) 164a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi throws IllegalArgumentException { 1651b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi if (!isValidSystemApiRule(rule)) { 1661b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi throw new IllegalArgumentException("Illegal rule value " + rule); 1671b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 1681b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return addRuleInt(attrToMatch, rule); 1691b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 1701b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 1711b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi /** 1721b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * Add a rule by exclusion for the selection of which streams are mixed together. 1731b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * <br>For instance the following code 1741b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * <br><pre> 1751b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * AudioAttributes mediaAttr = new AudioAttributes.Builder() 1761b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * .setUsage(AudioAttributes.USAGE_MEDIA) 1771b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * .build(); 1781b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * AudioMixingRule noMediaRule = new AudioMixingRule.Builder() 1791b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * .excludeRule(mediaAttr, AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE) 1801b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * .build(); 1811b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * </pre> 1821b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * <br>will create a rule which maps to any usage value, except USAGE_MEDIA. 1831b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * @param attrToMatch a non-null AudioAttributes instance for which a contradictory 1841b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * rule hasn't been set yet. 1851b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * @param rule {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE} or 1861b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}. 1871b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * @return the same Builder instance. 1881b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * @throws IllegalArgumentException 1891b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi */ 1901b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi @SystemApi 1911b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi public Builder excludeRule(AudioAttributes attrToMatch, int rule) 1921b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi throws IllegalArgumentException { 1931b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi if (!isValidSystemApiRule(rule)) { 1941b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi throw new IllegalArgumentException("Illegal rule value " + rule); 1951b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 1961b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return addRuleInt(attrToMatch, rule | RULE_EXCLUSION_MASK); 1971b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 1981b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 1991b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi /** 2001b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * Add or exclude a rule for the selection of which streams are mixed together. 2011b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * @param attrToMatch a non-null AudioAttributes instance for which a contradictory 2021b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * rule hasn't been set yet. 2031b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * @param rule one of {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_USAGE}, 2041b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_USAGE}, 2051b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET} or 2061b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * {@link AudioMixingRule#RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET}. 2071b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * @return the same Builder instance. 2081b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * @throws IllegalArgumentException 2091b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi */ 2101b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi Builder addRuleInt(AudioAttributes attrToMatch, int rule) 2111b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi throws IllegalArgumentException { 212a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi if (attrToMatch == null) { 213a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi throw new IllegalArgumentException("Illegal null AudioAttributes argument"); 214a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 2151b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi if (!isValidIntRule(rule)) { 216a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi throw new IllegalArgumentException("Illegal rule value " + rule); 2171b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } else { 2181b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi // as rules are added to the Builder, we verify they are consistent with the type 2191b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi // of mix being built. When adding the first rule, the mix type is MIX_TYPE_INVALID. 2201b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi if (mTargetMixType == AudioMix.MIX_TYPE_INVALID) { 2211b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi if (isPlayerRule(rule)) { 2221b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi mTargetMixType = AudioMix.MIX_TYPE_PLAYERS; 2231b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } else { 2241b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi mTargetMixType = AudioMix.MIX_TYPE_RECORDERS; 2251b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 2261b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } else if (((mTargetMixType == AudioMix.MIX_TYPE_PLAYERS) && !isPlayerRule(rule)) 2271b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi || ((mTargetMixType == AudioMix.MIX_TYPE_RECORDERS) && isPlayerRule(rule))) 2281b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi { 2291b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi throw new IllegalArgumentException("Incompatible rule for mix"); 2301b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 231a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 232a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi synchronized (mCriteria) { 233a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi Iterator<AttributeMatchCriterion> crIterator = mCriteria.iterator(); 234a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi while (crIterator.hasNext()) { 235a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi final AttributeMatchCriterion criterion = crIterator.next(); 236a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi if ((rule == RULE_MATCH_ATTRIBUTE_USAGE) 237a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi || (rule == RULE_EXCLUDE_ATTRIBUTE_USAGE)) { 238a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi // "usage"-based rule 239a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi if (criterion.mAttr.getUsage() == attrToMatch.getUsage()) { 240a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi if (criterion.mRule == rule) { 241a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi // rule already exists, we're done 242a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi return this; 243a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } else { 244a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi // criterion already exists with a another rule, it is incompatible 245a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi throw new IllegalArgumentException("Contradictory rule exists for " 246a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi + attrToMatch); 247a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 248a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 2491b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } else if ((rule == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET) 2501b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi || (rule == RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET)) { 2511b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi // "capture preset"-base rule 2521b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi if (criterion.mAttr.getCapturePreset() == attrToMatch.getCapturePreset()) { 2531b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi if (criterion.mRule == rule) { 2541b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi // rule already exists, we're done 2551b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return this; 2561b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } else { 2571b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi // criterion already exists with a another rule, it is incompatible 2581b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi throw new IllegalArgumentException("Contradictory rule exists for " 2591b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi + attrToMatch); 2601b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 2611b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 262a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 263a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 264a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi // rule didn't exist, add it 265a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi mCriteria.add(new AttributeMatchCriterion(attrToMatch, rule)); 266a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 267a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi return this; 268a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 269a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 2701b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi Builder addRuleFromParcel(Parcel in) throws IllegalArgumentException { 2711b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi int rule = in.readInt(); 2721b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi AudioAttributes attr; 2731b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi if ((rule == RULE_MATCH_ATTRIBUTE_USAGE) || (rule == RULE_EXCLUDE_ATTRIBUTE_USAGE)) { 2741b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi int usage = in.readInt(); 2751b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi attr = new AudioAttributes.Builder() 2761b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi .setUsage(usage).build(); 2771b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } else if ((rule == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET) 2781b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi || (rule == RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET)) { 2791b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi int preset = in.readInt(); 2801b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi attr = new AudioAttributes.Builder() 2811b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi .setInternalCapturePreset(preset).build(); 2821b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } else { 2831b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi in.readInt(); // assume there was in int value to read as for now they come in pair 2841b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi throw new IllegalArgumentException("Illegal rule value " + rule + " in parcel"); 2851b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 2861b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return addRuleInt(attr, rule); 2871b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 2881b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 289a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi /** 290a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Combines all of the matching and exclusion rules that have been set and return a new 291a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * {@link AudioMixingRule} object. 292a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * @return a new {@link AudioMixingRule} object 293a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */ 294a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi public AudioMixingRule build() { 2951b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return new AudioMixingRule(mTargetMixType, mCriteria); 296a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 297a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 298a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi} 299