Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5325314 authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "Revert "Initial implementation of USB Audio output.""

parents e2c45526 f2f80c09
Loading
Loading
Loading
Loading
+0 −116
Original line number Original line Diff line number Diff line
/*
 * 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() {}
}
+0 −240
Original line number Original line Diff line number Diff line
/*
 * 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
+0 −57
Original line number Original line Diff line number Diff line
/*
 * 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;
    }
}
+7 −23
Original line number Original line Diff line number Diff line
@@ -43,7 +43,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.content.res.XmlResourceParser;
import android.database.ContentObserver;
import android.database.ContentObserver;
import android.hardware.usb.UsbManager;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Binder;
import android.os.Binder;
@@ -529,7 +528,6 @@ public class AudioService extends IAudioService.Stub {
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
        intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);


        intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
        intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
        // TODO merge orientation and rotation
        // TODO merge orientation and rotation
@@ -3977,8 +3975,7 @@ public class AudioService extends IAudioService.Stub {
                    (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
                    (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
                setBluetoothA2dpOnInt(true);
                setBluetoothA2dpOnInt(true);
            }
            }
            boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0) ||
            boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0);
                            ((device & AudioSystem.DEVICE_IN_ALL_USB) != 0);
            handleDeviceConnection((state == 1), device, (isUsb ? name : ""));
            handleDeviceConnection((state == 1), device, (isUsb ? name : ""));
            if (state != 0) {
            if (state != 0) {
                if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
                if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
@@ -4086,31 +4083,18 @@ public class AudioService extends IAudioService.Stub {
            } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ||
            } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ||
                           action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) {
                           action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) {
                state = intent.getIntExtra("state", 0);
                state = intent.getIntExtra("state", 0);

                int alsaCard = intent.getIntExtra("card", -1);
                int alsaCard = intent.getIntExtra("card", -1);
                int alsaDevice = intent.getIntExtra("device", -1);
                int alsaDevice = intent.getIntExtra("device", -1);
                boolean hasPlayback = intent.getBooleanExtra("hasPlayback", false);
                boolean hasCapture = intent.getBooleanExtra("hasCapture", false);
                boolean hasMIDI = intent.getBooleanExtra("hasMIDI", false);

                String params = (alsaCard == -1 && alsaDevice == -1 ? ""
                String params = (alsaCard == -1 && alsaDevice == -1 ? ""
                                    : "card=" + alsaCard + ";device=" + alsaDevice);
                                    : "card=" + alsaCard + ";device=" + alsaDevice);

                //TODO(pmclean) - Ignore for now the hasPlayback & hasCapture flags since we
                // still need to call setWiredDeviceConnectionState() on disconnect (when we
                // don't have card/device files to parse for this info). We will need to store
                // that info here when we get smarter about multiple USB card/devices.
                // Playback Device
                device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
                device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
                        AudioSystem.DEVICE_OUT_USB_ACCESSORY : AudioSystem.DEVICE_OUT_USB_DEVICE;
                        AudioSystem.DEVICE_OUT_USB_ACCESSORY : AudioSystem.DEVICE_OUT_USB_DEVICE;
                Log.v(TAG, "Broadcast Receiver: Got "
                        + (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
                              "ACTION_USB_AUDIO_ACCESSORY_PLUG" : "ACTION_USB_AUDIO_DEVICE_PLUG")
                        + ", state = " + state + ", card: " + alsaCard + ", device: " + alsaDevice);
                setWiredDeviceConnectionState(device, state, params);
                setWiredDeviceConnectionState(device, state, params);

            } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
                // Capture Device
                device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
                    AudioSystem.DEVICE_IN_USB_ACCESSORY : AudioSystem.DEVICE_IN_USB_DEVICE;
                setWiredDeviceConnectionState(device, state, params);
            }
            else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
                boolean broadcast = false;
                boolean broadcast = false;
                int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
                int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
                synchronized (mScoClients) {
                synchronized (mScoClients) {
@@ -4215,7 +4199,7 @@ public class AudioService extends IAudioService.Stub {
                        mStreamStates[AudioSystem.STREAM_MUSIC], 0);
                        mStreamStates[AudioSystem.STREAM_MUSIC], 0);
            }
            }
        }
        }
    } // end class AudioServiceBroadcastReceiver
    }


    //==========================================================================================
    //==========================================================================================
    // RemoteControlDisplay / RemoteControlClient / Remote info
    // RemoteControlDisplay / RemoteControlClient / Remote info
+0 −2
Original line number Original line Diff line number Diff line
@@ -288,8 +288,6 @@ public class AudioSystem
                                             DEVICE_IN_USB_DEVICE |
                                             DEVICE_IN_USB_DEVICE |
                                             DEVICE_IN_DEFAULT);
                                             DEVICE_IN_DEFAULT);
    public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
    public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
    public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
                                                 DEVICE_IN_USB_DEVICE);


    // device states, must match AudioSystem::device_connection_state
    // device states, must match AudioSystem::device_connection_state
    public static final int DEVICE_STATE_UNAVAILABLE = 0;
    public static final int DEVICE_STATE_UNAVAILABLE = 0;
Loading