diff options
author | Paul McLean <pmclean@google.com> | 2014-04-09 09:04:43 -0700 |
---|---|---|
committer | Paul McLean <pmclean@google.com> | 2014-04-09 09:04:43 -0700 |
commit | c837a451946b64d70ed7c642fbde03c182c28b6f (patch) | |
tree | d063e26cbd6b942ad3e04f19b4be3f97b9e5fc72 /core | |
parent | 121db9e8525163a867915adfd23a08cf1300d4fa (diff) | |
download | frameworks_base-c837a451946b64d70ed7c642fbde03c182c28b6f.zip frameworks_base-c837a451946b64d70ed7c642fbde03c182c28b6f.tar.gz frameworks_base-c837a451946b64d70ed7c642fbde03c182c28b6f.tar.bz2 |
Revert "Revert "Initial implementation of USB Audio output.""
This reverts commit f2f80c09b668176b3b1e619457ae628432636507.
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/alsa/AlsaCardsParser.java | 116 | ||||
-rw-r--r-- | core/java/android/alsa/AlsaDevicesParser.java | 240 | ||||
-rw-r--r-- | core/java/android/alsa/LineTokenizer.java | 57 |
3 files changed, 413 insertions, 0 deletions
diff --git a/core/java/android/alsa/AlsaCardsParser.java b/core/java/android/alsa/AlsaCardsParser.java new file mode 100644 index 0000000..f9af979 --- /dev/null +++ b/core/java/android/alsa/AlsaCardsParser.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.alsascan; + +import android.util.Slog; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.Vector; + +/** + * @hide Retrieves information from an ALSA "cards" file. + */ +public class AlsaCardsParser { + private static final String TAG = "AlsaCardsParser"; + + private static LineTokenizer tokenizer_ = new LineTokenizer(" :[]"); + + public class AlsaCardRecord { + public int mCardNum = -1; + public String mField1 = ""; + public String mCardName = ""; + public String mCardDescription = ""; + + public AlsaCardRecord() {} + + public boolean parse(String line, int lineIndex) { + int tokenIndex = 0; + int delimIndex = 0; + if (lineIndex == 0) { + // line # (skip) + tokenIndex = tokenizer_.nextToken(line, tokenIndex); + delimIndex = tokenizer_.nextDelimiter(line, tokenIndex); + + // mField1 + tokenIndex = tokenizer_.nextToken(line, delimIndex); + delimIndex = tokenizer_.nextDelimiter(line, tokenIndex); + mField1 = line.substring(tokenIndex, delimIndex); + + // mCardName + tokenIndex = tokenizer_.nextToken(line, delimIndex); + // delimIndex = tokenizer_.nextDelimiter(line, tokenIndex); + mCardName = line.substring(tokenIndex); + // done + } else if (lineIndex == 1) { + tokenIndex = tokenizer_.nextToken(line, 0); + if (tokenIndex != -1) { + mCardDescription = line.substring(tokenIndex); + } + } + + return true; + } + + public String textFormat() { + return mCardName + " : " + mCardDescription; + } + } + + private Vector<AlsaCardRecord> cardRecords_ = new Vector<AlsaCardRecord>(); + + public void scan() { + cardRecords_.clear(); + final String cardsFilePath = "/proc/asound/cards"; + File cardsFile = new File(cardsFilePath); + try { + FileReader reader = new FileReader(cardsFile); + BufferedReader bufferedReader = new BufferedReader(reader); + String line = ""; + while ((line = bufferedReader.readLine()) != null) { + AlsaCardRecord cardRecord = new AlsaCardRecord(); + cardRecord.parse(line, 0); + cardRecord.parse(line = bufferedReader.readLine(), 1); + cardRecords_.add(cardRecord); + } + reader.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public AlsaCardRecord getCardRecordAt(int index) { + return cardRecords_.get(index); + } + + public int getNumCardRecords() { + return cardRecords_.size(); + } + + public void Log() { + int numCardRecs = getNumCardRecords(); + for (int index = 0; index < numCardRecs; ++index) { + Slog.w(TAG, "usb:" + getCardRecordAt(index).textFormat()); + } + } + + public AlsaCardsParser() {} +} diff --git a/core/java/android/alsa/AlsaDevicesParser.java b/core/java/android/alsa/AlsaDevicesParser.java new file mode 100644 index 0000000..3835942 --- /dev/null +++ b/core/java/android/alsa/AlsaDevicesParser.java @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.alsascan; + +import android.util.Slog; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.Vector; + +/** + * @hide + * Retrieves information from an ALSA "devices" file. + */ +public class AlsaDevicesParser { + private static final String TAG = "AlsaDevicesParser"; + + private static final int kIndex_CardDeviceField = 5; + private static final int kStartIndex_CardNum = 6; + private static final int kEndIndex_CardNum = 8; // one past + private static final int kStartIndex_DeviceNum = 9; + private static final int kEndIndex_DeviceNum = 11; // one past + private static final int kStartIndex_Type = 14; + + private static LineTokenizer mTokenizer = new LineTokenizer(" :[]-"); + + private boolean mHasCaptureDevices = false; + private boolean mHasPlaybackDevices = false; + private boolean mHasMIDIDevices = false; + + public class AlsaDeviceRecord { + public static final int kDeviceType_Unknown = -1; + public static final int kDeviceType_Audio = 0; + public static final int kDeviceType_Control = 1; + public static final int kDeviceType_MIDI = 2; + + public static final int kDeviceDir_Unknown = -1; + public static final int kDeviceDir_Capture = 0; + public static final int kDeviceDir_Playback = 1; + + int mCardNum = -1; + int mDeviceNum = -1; + int mDeviceType = kDeviceType_Unknown; + int mDeviceDir = kDeviceDir_Unknown; + + public AlsaDeviceRecord() { + } + + public boolean parse(String line) { + // "0123456789012345678901234567890" + // " 2: [ 0-31]: digital audio playback" + // " 3: [ 0-30]: digital audio capture" + // " 35: [ 1] : control" + // " 36: [ 2- 0]: raw midi" + + final int kToken_LineNum = 0; + final int kToken_CardNum = 1; + final int kToken_DeviceNum = 2; + final int kToken_Type0 = 3; // "digital", "control", "raw" + final int kToken_Type1 = 4; // "audio", "midi" + final int kToken_Type2 = 5; // "capture", "playback" + + int tokenOffset = 0; + int delimOffset = 0; + int tokenIndex = kToken_LineNum; + while (true) { + tokenOffset = mTokenizer.nextToken(line, delimOffset); + if (tokenOffset == LineTokenizer.kTokenNotFound) { + break; // bail + } + delimOffset = mTokenizer.nextDelimiter(line, tokenOffset); + if (delimOffset == LineTokenizer.kTokenNotFound) { + delimOffset = line.length(); + } + String token = line.substring(tokenOffset, delimOffset); + + switch (tokenIndex) { + case kToken_LineNum: + // ignore + break; + + case kToken_CardNum: + mCardNum = Integer.parseInt(token); + if (line.charAt(delimOffset) != '-') { + tokenIndex++; // no device # in the token stream + } + break; + + case kToken_DeviceNum: + mDeviceNum = Integer.parseInt(token); + break; + + case kToken_Type0: + if (token.equals("digital")) { + // NOP + } else if (token.equals("control")) { + mDeviceType = kDeviceType_Control; + } else if (token.equals("raw")) { + // NOP + } + break; + + case kToken_Type1: + if (token.equals("audio")) { + mDeviceType = kDeviceType_Audio; + } else if (token.equals("midi")) { + mDeviceType = kDeviceType_MIDI; + mHasMIDIDevices = true; + } + break; + + case kToken_Type2: + if (token.equals("capture")) { + mDeviceDir = kDeviceDir_Capture; + mHasCaptureDevices = true; + } else if (token.equals("playback")) { + mDeviceDir = kDeviceDir_Playback; + mHasPlaybackDevices = true; + } + break; + } // switch (tokenIndex) + + tokenIndex++; + } // while (true) + + return true; + } // parse() + + public String textFormat() { + StringBuilder sb = new StringBuilder(); + sb.append("[" + mCardNum + ":" + mDeviceNum + "]"); + + switch (mDeviceType) { + case kDeviceType_Unknown: + sb.append(" N/A"); + break; + case kDeviceType_Audio: + sb.append(" Audio"); + break; + case kDeviceType_Control: + sb.append(" Control"); + break; + case kDeviceType_MIDI: + sb.append(" MIDI"); + break; + } + + switch (mDeviceDir) { + case kDeviceDir_Unknown: + sb.append(" N/A"); + break; + case kDeviceDir_Capture: + sb.append(" Capture"); + break; + case kDeviceDir_Playback: + sb.append(" Playback"); + break; + } + + return sb.toString(); + } + } + + private Vector<AlsaDeviceRecord> + deviceRecords_ = new Vector<AlsaDeviceRecord>(); + + private boolean isLineDeviceRecord(String line) { + return line.charAt(kIndex_CardDeviceField) == '['; + } + + public AlsaDevicesParser() { + } + + public int getNumDeviceRecords() { + return deviceRecords_.size(); + } + + public AlsaDeviceRecord getDeviceRecordAt(int index) { + return deviceRecords_.get(index); + } + + public void Log() { + int numDevRecs = getNumDeviceRecords(); + for (int index = 0; index < numDevRecs; ++index) { + Slog.w(TAG, "usb:" + getDeviceRecordAt(index).textFormat()); + } + } + + public boolean hasPlaybackDevices() { + return mHasPlaybackDevices; + } + + public boolean hasCaptureDevices() { + return mHasCaptureDevices; + } + + public boolean hasMIDIDevices() { + return mHasMIDIDevices; + } + + public void scan() { + deviceRecords_.clear(); + + final String devicesFilePath = "/proc/asound/devices"; + File devicesFile = new File(devicesFilePath); + try { + FileReader reader = new FileReader(devicesFile); + BufferedReader bufferedReader = new BufferedReader(reader); + String line = ""; + while ((line = bufferedReader.readLine()) != null) { + if (isLineDeviceRecord(line)) { + AlsaDeviceRecord deviceRecord = new AlsaDeviceRecord(); + deviceRecord.parse(line); + deviceRecords_.add(deviceRecord); + } + } + reader.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} // class AlsaDevicesParser + diff --git a/core/java/android/alsa/LineTokenizer.java b/core/java/android/alsa/LineTokenizer.java new file mode 100644 index 0000000..c138fc5 --- /dev/null +++ b/core/java/android/alsa/LineTokenizer.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.alsascan; + +/** + * @hide + * Breaks lines in an ALSA "cards" or "devices" file into tokens. + * TODO(pmclean) Look into replacing this with String.split(). + */ +public class LineTokenizer { + public static final int kTokenNotFound = -1; + + private String mDelimiters = ""; + + public LineTokenizer(String delimiters) { + mDelimiters = delimiters; + } + + int nextToken(String line, int startIndex) { + int len = line.length(); + int offset = startIndex; + for (; offset < len; offset++) { + if (mDelimiters.indexOf(line.charAt(offset)) == -1) { + // past a delimiter + break; + } + } + + return offset < len ? offset : kTokenNotFound; + } + + int nextDelimiter(String line, int startIndex) { + int len = line.length(); + int offset = startIndex; + for (; offset < len; offset++) { + if (mDelimiters.indexOf(line.charAt(offset)) != -1) { + // past a delimiter + break; + } + } + + return offset < len ? offset : kTokenNotFound; + } +} |