Home | History | Annotate | Download | only in alsa
      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 
     17 package com.android.internal.alsa;
     18 
     19 import android.util.Slog;
     20 import java.io.BufferedReader;
     21 import java.io.File;
     22 import java.io.FileNotFoundException;
     23 import java.io.FileReader;
     24 import java.io.IOException;
     25 import java.util.ArrayList;
     26 
     27 /**
     28  * @hide Retrieves information from an ALSA "cards" file.
     29  */
     30 public class AlsaCardsParser {
     31     private static final String TAG = "AlsaCardsParser";
     32     protected static final boolean DEBUG = false;
     33 
     34     private static final String kCardsFilePath = "/proc/asound/cards";
     35 
     36     private static LineTokenizer mTokenizer = new LineTokenizer(" :[]");
     37 
     38     private ArrayList<AlsaCardRecord> mCardRecords = new ArrayList<AlsaCardRecord>();
     39 
     40     public class AlsaCardRecord {
     41         private static final String TAG = "AlsaCardRecord";
     42         private static final String kUsbCardKeyStr = "at usb-";
     43 
     44         public int mCardNum = -1;
     45         public String mField1 = "";
     46         public String mCardName = "";
     47         public String mCardDescription = "";
     48         public boolean mIsUsb = false;
     49 
     50         public AlsaCardRecord() {}
     51 
     52         public boolean parse(String line, int lineIndex) {
     53             int tokenIndex = 0;
     54             int delimIndex = 0;
     55 
     56             if (lineIndex == 0) {
     57                 // line # (skip)
     58                 tokenIndex = mTokenizer.nextToken(line, tokenIndex);
     59                 delimIndex = mTokenizer.nextDelimiter(line, tokenIndex);
     60 
     61                 try {
     62                     // mCardNum
     63                     mCardNum = Integer.parseInt(line.substring(tokenIndex, delimIndex));
     64                 } catch (NumberFormatException e) {
     65                     Slog.e(TAG, "Failed to parse line " + lineIndex + " of " + kCardsFilePath
     66                         + ": " + line.substring(tokenIndex, delimIndex));
     67                     return false;
     68                 }
     69 
     70                 // mField1
     71                 tokenIndex = mTokenizer.nextToken(line, delimIndex);
     72                 delimIndex = mTokenizer.nextDelimiter(line, tokenIndex);
     73                 mField1 = line.substring(tokenIndex, delimIndex);
     74 
     75                 // mCardName
     76                 tokenIndex = mTokenizer.nextToken(line, delimIndex);
     77                 mCardName = line.substring(tokenIndex);
     78 
     79                 // done
     80               } else if (lineIndex == 1) {
     81                   tokenIndex = mTokenizer.nextToken(line, 0);
     82                   if (tokenIndex != -1) {
     83                       int keyIndex = line.indexOf(kUsbCardKeyStr);
     84                       mIsUsb = keyIndex != -1;
     85                       if (mIsUsb) {
     86                           mCardDescription = line.substring(tokenIndex, keyIndex - 1);
     87                       }
     88                   }
     89             }
     90 
     91             return true;
     92         }
     93 
     94         public String textFormat() {
     95           return mCardName + " : " + mCardDescription;
     96         }
     97     }
     98 
     99     public AlsaCardsParser() {}
    100 
    101     public void scan() {
    102         if (DEBUG) {
    103             Slog.i(TAG, "AlsaCardsParser.scan()");
    104         }
    105         mCardRecords = new ArrayList<AlsaCardRecord>();
    106 
    107         File cardsFile = new File(kCardsFilePath);
    108         try {
    109             FileReader reader = new FileReader(cardsFile);
    110             BufferedReader bufferedReader = new BufferedReader(reader);
    111             String line = "";
    112             while ((line = bufferedReader.readLine()) != null) {
    113                 AlsaCardRecord cardRecord = new AlsaCardRecord();
    114                 if (DEBUG) {
    115                     Slog.i(TAG, "  " + line);
    116                 }
    117                 cardRecord.parse(line, 0);
    118 
    119                 line = bufferedReader.readLine();
    120                 if (line == null) {
    121                     break;
    122                 }
    123                 if (DEBUG) {
    124                     Slog.i(TAG, "  " + line);
    125                 }
    126                 cardRecord.parse(line, 1);
    127 
    128                 mCardRecords.add(cardRecord);
    129             }
    130             reader.close();
    131         } catch (FileNotFoundException e) {
    132             e.printStackTrace();
    133         } catch (IOException e) {
    134             e.printStackTrace();
    135         }
    136     }
    137 
    138     public ArrayList<AlsaCardRecord> getScanRecords() {
    139         return mCardRecords;
    140     }
    141 
    142     public AlsaCardRecord getCardRecordAt(int index) {
    143         return mCardRecords.get(index);
    144     }
    145 
    146     public AlsaCardRecord getCardRecordFor(int cardNum) {
    147         for (AlsaCardRecord rec : mCardRecords) {
    148             if (rec.mCardNum == cardNum) {
    149                 return rec;
    150             }
    151         }
    152 
    153         return null;
    154     }
    155 
    156     public int getNumCardRecords() {
    157         return mCardRecords.size();
    158     }
    159 
    160     public boolean isCardUsb(int cardNum) {
    161         for (AlsaCardRecord rec : mCardRecords) {
    162             if (rec.mCardNum == cardNum) {
    163                 return rec.mIsUsb;
    164             }
    165         }
    166 
    167         return false;
    168     }
    169 
    170     // return -1 if none found
    171     public int getDefaultUsbCard() {
    172         // Choose the most-recently added EXTERNAL card
    173         // or return the first added EXTERNAL card?
    174         for (AlsaCardRecord rec : mCardRecords) {
    175             if (rec.mIsUsb) {
    176                 return rec.mCardNum;
    177             }
    178         }
    179 
    180         return -1;
    181     }
    182 
    183     public int getDefaultCard() {
    184         // return an external card if possible
    185         int card = getDefaultUsbCard();
    186 
    187         if (card < 0 && getNumCardRecords() > 0) {
    188             // otherwise return the (internal) card with the highest number
    189             card = getCardRecordAt(getNumCardRecords() - 1).mCardNum;
    190         }
    191         return card;
    192     }
    193 
    194     static public boolean hasCardNumber(ArrayList<AlsaCardRecord> recs, int cardNum) {
    195         for (AlsaCardRecord cardRec : recs) {
    196             if (cardRec.mCardNum == cardNum) {
    197                 return true;
    198             }
    199         }
    200         return false;
    201     }
    202 
    203     public ArrayList<AlsaCardRecord> getNewCardRecords(ArrayList<AlsaCardRecord> prevScanRecs) {
    204         ArrayList<AlsaCardRecord> newRecs = new ArrayList<AlsaCardRecord>();
    205         for (AlsaCardRecord rec : mCardRecords) {
    206             // now scan to see if this card number is in the previous scan list
    207             if (!hasCardNumber(prevScanRecs, rec.mCardNum)) {
    208                 newRecs.add(rec);
    209             }
    210         }
    211         return newRecs;
    212     }
    213 
    214     //
    215     // Logging
    216     //
    217     public void Log(String heading) {
    218         if (DEBUG) {
    219             Slog.i(TAG, heading);
    220             for (AlsaCardRecord cardRec : mCardRecords) {
    221                 Slog.i(TAG, cardRec.textFormat());
    222             }
    223         }
    224     }
    225 }
    226