summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorPaul McLean <pmclean@google.com>2014-04-09 09:04:43 -0700
committerPaul McLean <pmclean@google.com>2014-04-09 09:04:43 -0700
commitc837a451946b64d70ed7c642fbde03c182c28b6f (patch)
treed063e26cbd6b942ad3e04f19b4be3f97b9e5fc72 /core
parent121db9e8525163a867915adfd23a08cf1300d4fa (diff)
downloadframeworks_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.java116
-rw-r--r--core/java/android/alsa/AlsaDevicesParser.java240
-rw-r--r--core/java/android/alsa/LineTokenizer.java57
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;
+ }
+}