• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 androidx.annotation.Nullable;
20 
21 import java.io.ByteArrayInputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.util.ArrayList;
25 
26 import javax.xml.parsers.ParserConfigurationException;
27 import javax.xml.parsers.SAXParser;
28 import javax.xml.parsers.SAXParserFactory;
29 
30 import org.xml.sax.Attributes;
31 import org.xml.sax.InputSource;
32 import org.xml.sax.SAXException;
33 import org.xml.sax.XMLReader;
34 import org.xml.sax.helpers.DefaultHandler;
35 
36 public class ProfileManager {
37     private static final String TAG = "ProfileManager";
38     private static final boolean DEBUG = false;
39 
40     private static final String mBuiltInprofiles =
41         "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>" +
42             "<ProfileList Version=\"1.0.0\">" +
43             "<PeripheralProfile ProfileName=\"Google USB-C Headset\" ProfileDescription=\"Google USB-C Headset\" ProductName=\"USB-Audio - Pixel USB-C earbuds\">" +
44                 "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"21,4\" SampleRates=\"44100,48000\" />" +
45                 "<InputDevInfo ChanCounts=\"1\" ChanPosMasks=\"16\" ChanIndexMasks=\"1\" Encodings=\"2\" SampleRates=\"44100,48000\" />" +
46                 "<ButtonInfo HasBtnA=\"1\" HasBtnB=\"1\" HasBtnC=\"1\" HasBtnD=\"0\" />" +
47             "</PeripheralProfile>" +
48             "<PeripheralProfile ProfileName=\"AudioBox USB 96\" ProfileDescription=\"PreSonus AudioBox USB 96\" ProductName=\"USB-Audio - AudioBox USB 96\">" +
49                 "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"22,4\" SampleRates=\"44100,48000,88200,96000\"/>" +
50                 "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3\" Encodings=\"22,4\" SampleRates=\"44100,48000,88200,96000\"/>" +
51             "</PeripheralProfile>" +
52             "<PeripheralProfile ProfileName=\"AudioBox 44VSL\" ProfileDescription=\"Presonus AudioBox 44VSL\" ProductName=\"USB-Audio - AudioBox 44 VSL\">" +
53                 "<OutputDevInfo ChanCounts=\"2,3,4\" ChanPosMasks=\"12\" ChanIndexMasks=\"3,7,15\" Encodings=\"21,22,4\" SampleRates=\"44100,48000,88200,96000\" />" +
54                 "<InputDevInfo ChanCounts=\"1,2,3,4\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3,7,15\" Encodings=\"21,22,4\" SampleRates=\"44100,48000,88200,96000\" />" +
55             "</PeripheralProfile>" +
56             "<PeripheralProfile ProfileName=\"AudioBox 22VSL\" ProfileDescription=\"Presonus AudioBox 22VSL\" ProductName=\"USB-Audio - AudioBox 22 VSL\">" +
57                 "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"21,22,4\" SampleRates=\"44100,48000,88200,96000\" />" +
58                 "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3\" Encodings=\"21,22,4\" SampleRates=\"44100,48000,88200,96000\" />" +
59             "</PeripheralProfile>" +
60             "<PeripheralProfile ProfileName=\"AudioBox USB\" ProfileDescription=\"Presonus AudioBox USB\" ProductName=\"USB-Audio - AudioBox USB\">" +
61                 "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"21,4\" SampleRates=\"44100,48000\" />" +
62                 "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3\" Encodings=\"21,4\" SampleRates=\"44100,48000\" />" +
63             "</PeripheralProfile>" +
64             "<PeripheralProfile ProfileName=\"Focusrite 2i4\" ProfileDescription=\"Focusrite Scarlett 2i4\" ProductName=\"USB-Audio - Scarlett 2i4 USB\">" +
65                 "<OutputDevInfo ChanCounts=\"2,3,4\" ChanPosMasks=\"12\" ChanIndexMasks=\"3,7,15\" Encodings=\"21,4\" SampleRates=\"44100,48000,88200,96000\"/>" +
66                 "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3\" Encodings=\"21,4\" SampleRates=\"44100,48000,88200,96000\"/>" +
67             "</PeripheralProfile>" +
68             "<PeripheralProfile ProfileName=\"Behringer UMC204HD\" ProfileDescription=\"Behringer UMC204HD\" ProductName=\"USB-Audio - UMC204HD 192k\">" +
69                 "<OutputDevInfo ChanCounts=\"2,3,4\" ChanPosMasks=\"12\" ChanIndexMasks=\"3,7,15\" Encodings=\"22,4,2\" SampleRates=\"44100,48000,88200,96000,176400,192000\"/>" +
70                 "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"16,12\" ChanIndexMasks=\"1,3\" Encodings=\"22,4\" SampleRates=\"44100,48000,88200,96000,176400,192000\"/>" +
71             "</PeripheralProfile>" +
72             "<PeripheralProfile ProfileName=\"Roland Rubix24\" ProfileDescription=\"Roland Rubix24\" ProductName=\"USB-Audio - Rubix24\">" +
73                 "<OutputDevInfo ChanCounts=\"2,3,4\" ChanPosMasks=\"12\" ChanIndexMasks=\"3,7,15\" Encodings=\"22,4\" SampleRates=\"44100,48000,96000,192000\"/>" +
74                 "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1,3\" Encodings=\"22,4\" SampleRates=\"44100,48000,96000,192000\"/>" +
75             "</PeripheralProfile>" +
76             "<PeripheralProfile ProfileName=\"Pixel USB-C Dongle + Wired Analog Headset\" ProfileDescription=\"Reference USB Dongle\" ProductName=\"USB-Audio - USB-C to 3.5mm-Headphone Adapte\">" +
77                 "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"21,4\" SampleRates=\"48000\" />" +
78                 "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"3\" Encodings=\"21,4\" SampleRates=\"48000\" />" +
79                 "<ButtonInfo HasBtnA=\"1\" HasBtnB=\"1\" HasBtnC=\"1\" />" +
80             "</PeripheralProfile>" +
81             "<PeripheralProfile ProfileName=\"HTC Dongle\" ProfileDescription=\"Type-C to 3.5mm Headphone\" ProductName=\"USB-Audio - HTC Type-C to 3.5mm Headphone J\">" +
82                 "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"21,4\" SampleRates=\"48000\" />" +
83                 "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"3\" Encodings=\"21,4\" SampleRates=\"48000\"/>" +
84                 "<ButtonInfo HasBtnA=\"1\" HasBtnB=\"1\" HasBtnC=\"1\" />" +
85             "</PeripheralProfile>" +
86             "<PeripheralProfile ProfileName=\"JBL Reflect Aware\" ProfileDescription=\"JBL Reflect Aware\" ProductName=\"USB-Audio - JBL Reflect Aware\">" +
87                 "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"2\" SampleRates=\"44100,48000\" />" +
88                 "<InputDevInfo ChanCounts=\"1\" ChanPosMasks=\"16\" ChanIndexMasks=\"1\" Encodings=\"2\" SampleRates=\"44100,48000\" />" +
89                 "<ButtonInfo HasBtnA=\"1\" HasBtnB=\"1\" HasBtnC=\"1\" />" +
90             "</PeripheralProfile>" +
91             "<PeripheralProfile ProfileName=\"Libratone Q Adapt\" ProfileDescription=\"Libratone Q Adapt Headset\" ProductName=\"USB-Audio - Libratone_INEAR\">" +
92                 "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"2\" SampleRates=\"48000\" />" +
93                 "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"1\" Encodings=\"2\" SampleRates=\"48000\" />"+
94                 "<ButtonInfo HasBtnA=\"1\" HasBtnB=\"1\" HasBtnC=\"1\" />" +
95             "</PeripheralProfile>" +
96             "<PeripheralProfile ProfileName=\"Vantec\" ProfileDescription=\"Vantec 7.1 USB Interface\" ProductName=\"USB-Audio - USB Sound Device\">" +
97                 "<OutputDevInfo ChanCounts=\"2,3,4,5,6,7,8\" ChanPosMasks=\"12\" ChanIndexMasks=\"3,7,15,31,63,127,255\" Encodings=\"2\" SampleRates=\"48000,96000,44100\" />" +
98                 "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"16,12\" ChanIndexMasks=\"1,3\" Encodings=\"2\" SampleRates=\"48000,44100\" />" +
99                 "<ButtonInfo HasBtnA=\"1\" HasBtnB=\"1\" HasBtnC=\"1\" />" +
100             "</PeripheralProfile>" +
101         "</ProfileList>";
102 
103     // XML Tags and Attributes
104     private final static String kTag_ProfileList = "ProfileList";
105     private final static String kAttrName_Version = "Version";
106     private final static String kValueStr_Version = "1.0.0";
107 
108     private final ArrayList<PeripheralProfile> mProfiles =
109         new ArrayList<PeripheralProfile>();
110 
111     private PeripheralProfile mParsingProfile = null;
112 
addProfile(PeripheralProfile profile)113     public boolean addProfile(PeripheralProfile profile) {
114         mProfiles.add(profile);
115 
116         return true;
117     }
118 
119     private class ProfileLoader extends DefaultHandler {
120         @Override
startElement(String namespaceURI, String localName, String qName, Attributes atts)121         public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
122             if (localName.equals(kTag_ProfileList)) {
123                 // Maybe check the version here.
124             } else if (localName.equals(PeripheralProfile.kTag_Profile)){
125                 mParsingProfile = new PeripheralProfile(null, null, null, null, null);
126                 mParsingProfile.startElement(namespaceURI, localName, qName, atts);
127             } else {
128                 mParsingProfile.startElement(namespaceURI, localName, qName, atts);
129             }
130         }
131 
132         @Override
endElement(String uri, String localName, String qName)133         public void endElement(String uri, String localName, String qName) {
134             if (localName.equals(kTag_ProfileList)) {
135                 // Version Checking here maybe?
136             } else if (localName.equals(PeripheralProfile.kTag_Profile)){
137                 mProfiles.add(mParsingProfile);
138                 mParsingProfile = null;
139             }
140         }
141     }
142 
143     @Override
toString()144     public String toString() {
145         return super.toString();
146     }
147 
loadProfiles(InputStream inStream)148     public boolean loadProfiles(InputStream inStream) {
149         SAXParserFactory spf = SAXParserFactory.newInstance();
150         SAXParser sp;
151         try {
152             sp = spf.newSAXParser();
153             XMLReader xr = sp.getXMLReader();
154             xr.setContentHandler(new ProfileLoader());
155             xr.parse(new InputSource(inStream));
156         } catch (ParserConfigurationException e) {
157             e.printStackTrace();
158         } catch (SAXException e) {
159             e.printStackTrace();
160         } catch (IOException e) {
161             e.printStackTrace();
162         }
163 
164         return true;
165     }
166 
loadProfiles(String profilesXML)167     public boolean loadProfiles(String profilesXML) {
168         mProfiles.clear();
169 
170         return loadProfiles(new ByteArrayInputStream(profilesXML.getBytes()));
171     }
172 
loadProfiles()173     public boolean loadProfiles() {
174         return loadProfiles(mBuiltInprofiles);
175     }
176 
177     //
178     // Access
179     //
getProfiles()180     public ArrayList<PeripheralProfile> getProfiles() { return mProfiles; }
181 
getNumProfiles()182     public int getNumProfiles() {
183         return mProfiles.size();
184     }
getProfile(int index)185     public PeripheralProfile getProfile(int index) {
186         return mProfiles.get(index);
187     }
188 
189     @Nullable
getProfile(String productName)190     public PeripheralProfile getProfile(String productName) {
191         for(PeripheralProfile profile : mProfiles) {
192             if (productName.equals(profile.getProductName())) {
193                 return profile;
194             }
195         }
196         return null;
197     }
198 }
199