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