• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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 package android.alsa;
17 
18 import android.util.Slog;
19 import java.io.BufferedReader;
20 import java.io.File;
21 import java.io.FileNotFoundException;
22 import java.io.FileReader;
23 import java.io.IOException;
24 import java.util.Vector;
25 
26 /**
27  * @hide
28  * Retrieves information from an ALSA "devices" file.
29  */
30 public class AlsaDevicesParser {
31     private static final String TAG = "AlsaDevicesParser";
32 
33     private static final int kIndex_CardDeviceField = 5;
34     private static final int kStartIndex_CardNum = 6;
35     private static final int kEndIndex_CardNum = 8; // one past
36     private static final int kStartIndex_DeviceNum = 9;
37     private static final int kEndIndex_DeviceNum = 11; // one past
38     private static final int kStartIndex_Type = 14;
39 
40     private static LineTokenizer mTokenizer = new LineTokenizer(" :[]-");
41 
42     private boolean mHasCaptureDevices = false;
43     private boolean mHasPlaybackDevices = false;
44     private boolean mHasMIDIDevices = false;
45 
46     public class AlsaDeviceRecord {
47         public static final int kDeviceType_Unknown = -1;
48         public static final int kDeviceType_Audio = 0;
49         public static final int kDeviceType_Control = 1;
50         public static final int kDeviceType_MIDI = 2;
51 
52         public static final int kDeviceDir_Unknown = -1;
53         public static final int kDeviceDir_Capture = 0;
54         public static final int kDeviceDir_Playback = 1;
55 
56         int mCardNum = -1;
57         int mDeviceNum = -1;
58         int mDeviceType = kDeviceType_Unknown;
59         int mDeviceDir = kDeviceDir_Unknown;
60 
AlsaDeviceRecord()61         public AlsaDeviceRecord() {
62         }
63 
parse(String line)64         public boolean parse(String line) {
65             // "0123456789012345678901234567890"
66             // "  2: [ 0-31]: digital audio playback"
67             // "  3: [ 0-30]: digital audio capture"
68             // " 35: [ 1]   : control"
69             // " 36: [ 2- 0]: raw midi"
70 
71             final int kToken_LineNum = 0;
72             final int kToken_CardNum = 1;
73             final int kToken_DeviceNum = 2;
74             final int kToken_Type0 = 3; // "digital", "control", "raw"
75             final int kToken_Type1 = 4; // "audio", "midi"
76             final int kToken_Type2 = 5; // "capture", "playback"
77 
78             int tokenOffset = 0;
79             int delimOffset = 0;
80             int tokenIndex = kToken_LineNum;
81             while (true) {
82                 tokenOffset = mTokenizer.nextToken(line, delimOffset);
83                 if (tokenOffset == LineTokenizer.kTokenNotFound) {
84                     break; // bail
85                 }
86                 delimOffset = mTokenizer.nextDelimiter(line, tokenOffset);
87                 if (delimOffset == LineTokenizer.kTokenNotFound) {
88                     delimOffset = line.length();
89                 }
90                 String token = line.substring(tokenOffset, delimOffset);
91 
92                 switch (tokenIndex) {
93                 case kToken_LineNum:
94                     // ignore
95                     break;
96 
97                 case kToken_CardNum:
98                     mCardNum = Integer.parseInt(token);
99                     if (line.charAt(delimOffset) != '-') {
100                         tokenIndex++; // no device # in the token stream
101                     }
102                     break;
103 
104                 case kToken_DeviceNum:
105                     mDeviceNum = Integer.parseInt(token);
106                     break;
107 
108                 case kToken_Type0:
109                     if (token.equals("digital")) {
110                         // NOP
111                     } else if (token.equals("control")) {
112                         mDeviceType = kDeviceType_Control;
113                     } else if (token.equals("raw")) {
114                         // NOP
115                     }
116                     break;
117 
118                 case kToken_Type1:
119                     if (token.equals("audio")) {
120                         mDeviceType = kDeviceType_Audio;
121                     } else if (token.equals("midi")) {
122                         mDeviceType = kDeviceType_MIDI;
123                         mHasMIDIDevices = true;
124                     }
125                     break;
126 
127                 case kToken_Type2:
128                     if (token.equals("capture")) {
129                         mDeviceDir = kDeviceDir_Capture;
130                         mHasCaptureDevices = true;
131                     } else if (token.equals("playback")) {
132                         mDeviceDir = kDeviceDir_Playback;
133                         mHasPlaybackDevices = true;
134                     }
135                     break;
136                 } // switch (tokenIndex)
137 
138                 tokenIndex++;
139             } // while (true)
140 
141             return true;
142         } // parse()
143 
textFormat()144         public String textFormat() {
145             StringBuilder sb = new StringBuilder();
146             sb.append("[" + mCardNum + ":" + mDeviceNum + "]");
147 
148             switch (mDeviceType) {
149             case kDeviceType_Unknown:
150                 sb.append(" N/A");
151                 break;
152             case kDeviceType_Audio:
153                 sb.append(" Audio");
154                 break;
155             case kDeviceType_Control:
156                 sb.append(" Control");
157                 break;
158             case kDeviceType_MIDI:
159                 sb.append(" MIDI");
160                 break;
161             }
162 
163             switch (mDeviceDir) {
164             case kDeviceDir_Unknown:
165                 sb.append(" N/A");
166                 break;
167             case kDeviceDir_Capture:
168                 sb.append(" Capture");
169                 break;
170             case kDeviceDir_Playback:
171                 sb.append(" Playback");
172                 break;
173             }
174 
175             return sb.toString();
176         }
177     }
178 
179     private Vector<AlsaDeviceRecord>
180             deviceRecords_ = new Vector<AlsaDeviceRecord>();
181 
isLineDeviceRecord(String line)182     private boolean isLineDeviceRecord(String line) {
183         return line.charAt(kIndex_CardDeviceField) == '[';
184     }
185 
AlsaDevicesParser()186     public AlsaDevicesParser() {
187     }
188 
getNumDeviceRecords()189     public int getNumDeviceRecords() {
190         return deviceRecords_.size();
191     }
192 
getDeviceRecordAt(int index)193     public AlsaDeviceRecord getDeviceRecordAt(int index) {
194         return deviceRecords_.get(index);
195     }
196 
Log()197     public void Log() {
198         int numDevRecs = getNumDeviceRecords();
199         for (int index = 0; index < numDevRecs; ++index) {
200             Slog.w(TAG, "usb:" + getDeviceRecordAt(index).textFormat());
201         }
202     }
203 
hasPlaybackDevices()204     public boolean hasPlaybackDevices() {
205         return mHasPlaybackDevices;
206     }
207 
hasPlaybackDevices(int card)208     public boolean hasPlaybackDevices(int card) {
209         for (int index = 0; index < deviceRecords_.size(); index++) {
210             AlsaDeviceRecord deviceRecord = deviceRecords_.get(index);
211             if (deviceRecord.mCardNum == card &&
212                 deviceRecord.mDeviceType == AlsaDeviceRecord.kDeviceType_Audio &&
213                 deviceRecord.mDeviceDir == AlsaDeviceRecord.kDeviceDir_Playback) {
214                 return true;
215             }
216         }
217         return false;
218     }
219 
hasCaptureDevices()220     public boolean hasCaptureDevices() {
221         return mHasCaptureDevices;
222     }
223 
hasCaptureDevices(int card)224     public boolean hasCaptureDevices(int card) {
225         for (int index = 0; index < deviceRecords_.size(); index++) {
226             AlsaDeviceRecord deviceRecord = deviceRecords_.get(index);
227             if (deviceRecord.mCardNum == card &&
228                 deviceRecord.mDeviceType == AlsaDeviceRecord.kDeviceType_Audio &&
229                 deviceRecord.mDeviceDir == AlsaDeviceRecord.kDeviceDir_Capture) {
230                 return true;
231             }
232         }
233         return false;
234     }
235 
hasMIDIDevices()236     public boolean hasMIDIDevices() {
237         return mHasMIDIDevices;
238     }
239 
hasMIDIDevices(int card)240     public boolean hasMIDIDevices(int card) {
241         for (int index = 0; index < deviceRecords_.size(); index++) {
242             AlsaDeviceRecord deviceRecord = deviceRecords_.get(index);
243             if (deviceRecord.mCardNum == card &&
244                 deviceRecord.mDeviceType == AlsaDeviceRecord.kDeviceType_MIDI) {
245                 return true;
246             }
247         }
248         return false;
249     }
250 
scan()251     public void scan() {
252         deviceRecords_.clear();
253 
254         final String devicesFilePath = "/proc/asound/devices";
255         File devicesFile = new File(devicesFilePath);
256         try {
257             FileReader reader = new FileReader(devicesFile);
258             BufferedReader bufferedReader = new BufferedReader(reader);
259             String line = "";
260             while ((line = bufferedReader.readLine()) != null) {
261                 if (isLineDeviceRecord(line)) {
262                     AlsaDeviceRecord deviceRecord = new AlsaDeviceRecord();
263                     deviceRecord.parse(line);
264                     deviceRecords_.add(deviceRecord);
265                 }
266             }
267             reader.close();
268         } catch (FileNotFoundException e) {
269             e.printStackTrace();
270         } catch (IOException e) {
271             e.printStackTrace();
272         }
273     }
274 } // class AlsaDevicesParser
275 
276