1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 #include <sys/types.h>
17 #include <regex.h>
18 #include <stdlib.h>
19 
20 #include <tinyalsa/asoundlib.h>
21 
22 #include "Log.h"
23 #include "StringUtil.h"
24 #include "SimpleScriptExec.h"
25 #include "audio/AudioHardware.h"
26 #include "audio/Buffer.h"
27 #include "audio/AudioPlaybackLocal.h"
28 #include "audio/AudioRecordingLocal.h"
29 #include "audio/AudioRemote.h"
30 #include "task/TaskCase.h"
31 
32 int AudioHardware::mHwId = -1;
33 
detectAudioHw()34 int AudioHardware::detectAudioHw()
35 {
36     android::String8 script("test_description/conf/detect_usb_audio.py");
37     /* This is the list of supported devices.
38        MobilePre: M-Audio MobilePre
39        Track: M-Audio FastTrack
40      */
41     android::String8 param("MobilePre Track");
42     android::String8 resultStr;
43     if (!SimpleScriptExec::runScript(script, param, resultStr)) {
44         LOGE("cannot run script");
45         return -1;
46     }
47 
48     android::String8 match("[ \t]+([A-Za-z0-9_]+)[ \t]+([0-9]+)");
49     const int nmatch = 3;
50     regmatch_t pmatch[nmatch];
51     if (!SimpleScriptExec::checkIfPassed(resultStr, match, nmatch, pmatch)) {
52         LOGE("result not correct %s", resultStr.string());
53         return -1;
54     }
55     LOGV("pmatch 0: %d, %d  1:%d, %d  2:%d, %d",
56         pmatch[0].rm_so, pmatch[0].rm_eo,
57         pmatch[1].rm_so, pmatch[1].rm_eo,
58         pmatch[2].rm_so, pmatch[2].rm_eo);
59 
60     if (pmatch[1].rm_so == -1) {
61         return -1;
62     }
63     if (pmatch[2].rm_so == -1) {
64         return -1;
65     }
66     android::String8 product = StringUtil::substr(resultStr, pmatch[1].rm_so,
67             pmatch[1].rm_eo - pmatch[1].rm_so);
68     LOGI("Audio device %s found", product.string());
69     android::String8 cardNumber = StringUtil::substr(resultStr, pmatch[2].rm_so,
70             pmatch[2].rm_eo - pmatch[2].rm_so);
71     int cardN = atoi(cardNumber.string());
72     LOGI("Card number : %d", cardN);
73     return cardN;
74 }
75 
createAudioHw(bool local,bool playback,TaskCase * testCase)76 android::sp<AudioHardware> AudioHardware::createAudioHw(bool local, bool playback,
77         TaskCase* testCase)
78 {
79     android::sp<AudioHardware> hw;
80     if (local) {
81         if (mHwId < 0) {
82             mHwId = detectAudioHw();
83         }
84         if (mHwId < 0) {
85             return NULL;
86         }
87         if (playback) {
88             hw = new AudioPlaybackLocal(mHwId);
89         } else {
90             hw = new AudioRecordingLocal(mHwId);
91         }
92     } else {
93         if (testCase != NULL) {
94             if (playback) {
95                 hw = new AudioRemotePlayback(testCase->getRemoteAudio());
96             } else {
97                 hw = new AudioRemoteRecording(testCase->getRemoteAudio());
98             }
99         }
100     }
101     return hw;
102 }
103 
~AudioHardware()104 AudioHardware::~AudioHardware()
105 {
106 
107 }
108 
startPlaybackOrRecordById(const android::String8 & id,TaskCase * testCase)109 bool AudioHardware::startPlaybackOrRecordById(const android::String8& id, TaskCase* testCase)
110 {
111     if (testCase == NULL) { // default implementation only handles local buffer.
112         return false;
113     }
114     android::sp<Buffer> buffer = testCase->findBuffer(id);
115     if (buffer.get() == NULL) {
116         return false;
117     }
118     return startPlaybackOrRecord(buffer);
119 }
120