1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.verifier.audio.peripheralprofile; 18 19 import android.media.AudioDeviceInfo; 20 import androidx.annotation.NonNull; 21 22 import com.android.cts.verifier.audio.peripheralprofile.ListsHelper; 23 24 import java.io.IOException; 25 26 import org.xml.sax.Attributes; 27 import org.xml.sax.SAXException; 28 import org.xml.sax.helpers.DefaultHandler; 29 30 public class PeripheralProfile extends DefaultHandler { 31 private String mProfileName; 32 private String mProfileDescription; 33 34 private String mProductName = ""; // From AudioDeviceInfo 35 36 public class ProfileAttributes { 37 public int[] mChannelCounts; 38 public int[] mChannelIndexMasks; 39 public int[] mChannelPositionMasks; 40 public int[] mEncodings; 41 public int[] mSampleRates; 42 } 43 44 ProfileAttributes mOutputAttributes; 45 ProfileAttributes mInputAttributes; 46 47 ProfileButtonAttributes mButtonAttributes; 48 49 // 50 // Accessors 51 // getName()52 public String getName() { return mProfileName; } getDescription()53 public String getDescription() { return mProfileDescription; } getProductName()54 public String getProductName() { return mProductName; } 55 getOutputAttributes()56 public ProfileAttributes getOutputAttributes() { 57 return mOutputAttributes; 58 } getInputAttributes()59 public ProfileAttributes getInputAttributes() { 60 return mInputAttributes; 61 } getButtonAttributes()62 public ProfileButtonAttributes getButtonAttributes() { 63 return mButtonAttributes; 64 } 65 66 @Override toString()67 public String toString() { return mProfileName; } 68 PeripheralProfile(String profileName, String profileDescription, AudioDeviceInfo outDeviceInfo, AudioDeviceInfo inDeviceInfo, ProfileButtonAttributes buttonAttributes)69 public PeripheralProfile(String profileName, String profileDescription, 70 AudioDeviceInfo outDeviceInfo, 71 AudioDeviceInfo inDeviceInfo, 72 ProfileButtonAttributes buttonAttributes) { 73 mProfileName = profileName; 74 mProfileDescription = profileDescription; 75 76 if (outDeviceInfo != null) { 77 mProductName = outDeviceInfo.getProductName().toString(); 78 79 mOutputAttributes = new ProfileAttributes(); 80 mOutputAttributes.mChannelCounts = 81 outDeviceInfo.getChannelCounts(); 82 mOutputAttributes.mChannelIndexMasks = 83 outDeviceInfo.getChannelIndexMasks(); 84 mOutputAttributes.mChannelPositionMasks = 85 outDeviceInfo.getChannelMasks(); 86 mOutputAttributes.mEncodings = outDeviceInfo.getEncodings(); 87 mOutputAttributes.mSampleRates = outDeviceInfo.getSampleRates(); 88 } else { 89 mOutputAttributes = null; 90 } 91 92 if (inDeviceInfo != null) { 93 mProductName = outDeviceInfo.getProductName().toString(); 94 95 mInputAttributes = new ProfileAttributes(); 96 mInputAttributes.mChannelCounts = inDeviceInfo.getChannelCounts(); 97 mInputAttributes.mChannelIndexMasks = inDeviceInfo.getChannelIndexMasks(); 98 mInputAttributes.mChannelPositionMasks = inDeviceInfo.getChannelMasks(); 99 mInputAttributes.mEncodings = inDeviceInfo.getEncodings(); 100 mInputAttributes.mSampleRates = inDeviceInfo.getSampleRates(); 101 } else { 102 mInputAttributes = null; 103 } 104 105 mButtonAttributes = buttonAttributes; 106 } 107 matches(ProfileAttributes attribs, AudioDeviceInfo deviceInfo)108 public static boolean matches(ProfileAttributes attribs, AudioDeviceInfo deviceInfo) { 109 boolean match = 110 ListsHelper.isMatch(deviceInfo.getChannelCounts(), attribs.mChannelCounts) && 111 ListsHelper.isMatch(deviceInfo.getChannelIndexMasks(), attribs.mChannelIndexMasks) && 112 ListsHelper.isMatch(deviceInfo.getChannelMasks(), attribs.mChannelPositionMasks) && 113 ListsHelper.isMatch(deviceInfo.getEncodings(), attribs.mEncodings) && 114 ListsHelper.isMatch(deviceInfo.getSampleRates(), attribs.mSampleRates); 115 return match; 116 } 117 118 // 119 // Peripheral (XML) Loading 120 // parseIntList(String intList)121 private static int[] parseIntList(String intList) { 122 String[] strings = intList.split(","); 123 int[] ints = new int[strings.length]; 124 for (int index = 0; index < strings.length; index++) { 125 try { 126 ints[index] = Integer.parseInt(strings[index]); 127 } 128 catch (NumberFormatException ex) { 129 ints[index] = 0; 130 } 131 } 132 return ints; 133 } 134 135 // XML Tags 136 public static final String kTag_Profile = "PeripheralProfile"; 137 public static final String kTag_OutputDevInfo = "OutputDevInfo"; 138 public static final String kTag_InputDevInfo = "InputDevInfo"; 139 public static final String kTag_ButtonInfo = "ButtonInfo"; 140 141 // XML Attributes 142 // - Attributes for Profile Tag 143 private static final String kAttr_ProfileName = "ProfileName"; 144 private static final String kAttr_ProfileDescription = "ProfileDescription"; 145 private static final String kAttr_Product = "ProductName"; 146 147 // - Attributes for DevInfo tags 148 private static final String kAttr_ChanCounts = "ChanCounts"; 149 private static final String kAttr_ChanPosMasks = "ChanPosMasks"; 150 private static final String kAttr_ChanIndexMasks = "ChanIndexMasks"; 151 private static final String kAttr_Encodings = "Encodings"; 152 private static final String kAttr_SampleRates = "SampleRates"; 153 private static final String kAttr_HasBtnA = "HasBtnA"; 154 private static final String kAttr_HasBtnB = "HasBtnB"; 155 private static final String kAttr_HasBtnC = "HasBtnC"; 156 parseProfileAttributes(ProfileAttributes attribs, String elementName, Attributes xmlAtts)157 private void parseProfileAttributes(ProfileAttributes attribs, String elementName, 158 Attributes xmlAtts) { 159 attribs.mChannelCounts = parseIntList(xmlAtts.getValue(kAttr_ChanCounts)); 160 attribs.mChannelPositionMasks = parseIntList(xmlAtts.getValue(kAttr_ChanPosMasks)); 161 attribs.mChannelIndexMasks = parseIntList(xmlAtts.getValue(kAttr_ChanIndexMasks)); 162 attribs.mEncodings = parseIntList(xmlAtts.getValue(kAttr_Encodings)); 163 attribs.mSampleRates = parseIntList(xmlAtts.getValue(kAttr_SampleRates)); 164 } 165 parseProfileButtons(ProfileButtonAttributes buttonAttributes, String elementName, Attributes xmlAtts)166 private void parseProfileButtons(ProfileButtonAttributes buttonAttributes, String elementName, 167 Attributes xmlAtts) { 168 buttonAttributes.mHasBtnA = Integer.parseInt(xmlAtts.getValue(kAttr_HasBtnA)) == 1; 169 buttonAttributes.mHasBtnB = Integer.parseInt(xmlAtts.getValue(kAttr_HasBtnB)) == 1; 170 buttonAttributes.mHasBtnC = Integer.parseInt(xmlAtts.getValue(kAttr_HasBtnC)) == 1; 171 } 172 173 // 174 // org.xml.sax.helpers.DefaultHandler overrides 175 // 176 @Override startElement(String namespaceURI, String localName, String qName, Attributes atts)177 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { 178 if (qName.equals(kTag_Profile)) { 179 mProfileName = atts.getValue(kAttr_ProfileName); 180 mProfileDescription = atts.getValue(kAttr_ProfileDescription); 181 mProductName = atts.getValue(kAttr_Product); 182 } else if (qName.equals(kTag_OutputDevInfo)) { 183 mOutputAttributes = new ProfileAttributes(); 184 parseProfileAttributes(mOutputAttributes, localName, atts); 185 } else if (qName.equals(kTag_InputDevInfo)) { 186 mInputAttributes = new ProfileAttributes(); 187 parseProfileAttributes(mInputAttributes, localName, atts); 188 } else if (qName.equals(kTag_ButtonInfo)) { 189 mButtonAttributes = new ProfileButtonAttributes(); 190 parseProfileButtons(mButtonAttributes, localName, atts); 191 } 192 } 193 194 @Override endElement(String uri, String localName, String qName)195 public void endElement(String uri, String localName, String qName) { 196 } 197 } 198