blob: 372202f11995f8f3ad6f500255a2e870e6135508 [file] [log] [blame]
Lei Qian7bf98232018-09-20 17:56:38 +08001/*
2**
3** Copyright 2012, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16** @author Hugo Hong
17** @version 1.0
18** @date 2018/04/01
19** @par function description:
20** - 1 bluetooth rc audio hardware input man
21*/
22
23#define LOG_TAG "AudioHAL:AudioHardwareInput"
xingri.gao989a73a2022-12-28 06:58:14 +000024#include <cutils/log.h>
25
Lei Qian7bf98232018-09-20 17:56:38 +080026
27#include <fcntl.h>
28#include <sys/eventfd.h>
29#include <sys/stat.h>
30#include <sys/types.h>
31#include <unistd.h>
32
33#include <utils/String8.h>
34
35#include "AudioHardwareInput.h"
36#include "AudioHotplugThread.h"
37#include "AudioHidrawStreamIn.h"
38#include "AudioSoundCardStreamIn.h"
39
Lei Qian7bf98232018-09-20 17:56:38 +080040namespace android {
41
42AudioHardwareInput::AudioHardwareInput()
43 : mMicMute(false)
44{
45 mHotplugThread = new AudioHotplugThread(*this);
46 if (mHotplugThread == NULL) {
47 ALOGE("Unable to create ATV Remote audio hotplug thread. "
48 "Pluggable audio input devices will not function.");
49 } else if (!mHotplugThread->start()) {
50 ALOGE("Unable to start ATV Remote audio hotplug thread. "
51 "Pluggable audio input devices will not function.");
52 mHotplugThread.clear();
53 }
54
55 for (int i = 0; i < MAX_DEVICE_TYPE; i++) {
56 for (int j=0; j<kMaxDevices; j++) {
57 memset(&mDeviceInfos[i][j], 0, sizeof(AudioHotplugThread::DeviceInfo));
58 }
59 }
60}
61
62AudioHardwareInput::~AudioHardwareInput()
63{
64 if (mHotplugThread != NULL) {
65 mHotplugThread->shutdown();
66 mHotplugThread.clear();
67 }
68
69 closeAllInputStreams();
70}
71
72status_t AudioHardwareInput::initCheck() {
73 return NO_ERROR;
74}
75
76char* AudioHardwareInput::getParameters(const char* keys) {
77 (void) keys;
78 return strdup("");
79}
80
81status_t AudioHardwareInput::setParameters(const char* kvpairs) {
82 (void) kvpairs;
83 return NO_ERROR;
84}
85
86status_t AudioHardwareInput::setMicMute(bool mute)
87{
88 mMicMute = mute;
89 return NO_ERROR;
90}
91
92status_t AudioHardwareInput::getMicMute(bool* mute)
93{
94 *mute = mMicMute;
95 return NO_ERROR;
96}
97
98// milliseconds per ALSA period
99const uint32_t AudioHardwareInput::kPeriodMsec = 10;
100
101size_t AudioHardwareInput::calculateInputBufferSize(uint32_t outputSampleRate,
102 audio_format_t format,
103 uint32_t channelCount)
104{
105 size_t size;
106
107 // AudioFlinger expects audio buffers to be a multiple of 16 frames
108 size = (kPeriodMsec * outputSampleRate) / 1000;
109 size = ((size + 15) / 16) * 16;
110
111 return size * channelCount * audio_bytes_per_sample(format);
112}
113
114status_t AudioHardwareInput::getInputBufferSize(const audio_config* config)
115{
116 size_t size = calculateInputBufferSize(config->sample_rate,
117 config->format,
118 audio_channel_count_from_in_mask(config->channel_mask));
119 return size;
120}
121
122AudioStreamIn* AudioHardwareInput::openInputStream(struct audio_stream_in *stream,
123 audio_format_t* format, uint32_t* channelMask, uint32_t* sampleRate,
124 status_t* status)
125{
126 ALOGI("%s: ++", __func__);
127 Mutex::Autolock _l(mLock);
128 AudioStreamIn* in = NULL;
129 const AudioHotplugThread::DeviceInfo* devInfo = getBestDevice(AUDIO_SOURCE_VOICE_RECOGNITION);
130
131 if (devInfo != NULL) {
132 if (devInfo->pcmCard > 0 && devInfo->pcmDevice > 0) {
133 in = new AudioSoundCardStreamIn(*this);
134 }
135 else {
136 in = new AudioHidrawStreamIn(*this);
137 }
138 }
139 if (in == NULL) {
140 *status = NO_MEMORY;
141 goto done;
142 }
143
144 *status = in->set(stream, format, channelMask, sampleRate);
145
146 if (*status != NO_ERROR) {
147 delete in;
148 in = NULL;
149 goto done;
150 }
151
152 mInputStreams.add(in);
153
154done:
155 ALOGI("%s: --", __func__);
156 return in;
157}
158
159void AudioHardwareInput::closeInputStream(AudioStreamIn* in)
160{
161 Mutex::Autolock _l(mLock);
162
163 for (size_t i = 0; i < mInputStreams.size(); i++) {
164 if (in == mInputStreams[i]) {
165 mInputStreams.removeAt(i);
166 in->standby();
167 delete in;
168 break;
169 }
170 }
171}
172
173void AudioHardwareInput::closeAllInputStreams()
174{
175 while (mInputStreams.size() != 0) {
176 AudioStreamIn* in = mInputStreams[0];
177 mInputStreams.removeAt(0);
178 in->standby();
179 delete in;
180 }
181}
182
183void AudioHardwareInput::standbyAllInputStreams(const AudioHotplugThread::DeviceInfo* deviceInfo)
184{
185 for (size_t i = 0; i < mInputStreams.size(); i++) {
186 if (deviceInfo == NULL || deviceInfo == mInputStreams[i]->getDeviceInfo()) {
187 mInputStreams[i]->standby();
188 }
189 }
190}
191
192// called on the audio hotplug thread
193void AudioHardwareInput::onDeviceFound(
194 const AudioHotplugThread::DeviceInfo& devInfo, bool fgHidraw)
195{
196 bool foundSlot = false;
197 Mutex::Autolock _l(mLock);
198
199 ALOGD("AudioHardwareInput::onDeviceFound hidraw flag = %d", fgHidraw);
200
201 for (int i=0; i<kMaxDevices; i++) {
202 if (fgHidraw) {
203 if (mDeviceInfos[HIDRAW_DEVICE][i].valid) {
204 if (mDeviceInfos[HIDRAW_DEVICE][i].hidraw_index == devInfo.hidraw_index) {
205 ALOGW("AudioHardwareInput::onDeviceFound already has %d",
206 devInfo.hidraw_index);
207 return; // Got it already so no action needed.
208 }
209 }
210 }
211 else if (mDeviceInfos[SOUNDCARD_DEVICE][i].valid){
212 if ((mDeviceInfos[SOUNDCARD_DEVICE][i].pcmCard == devInfo.pcmCard)
213 && (mDeviceInfos[SOUNDCARD_DEVICE][i].pcmDevice == devInfo.pcmDevice)) {
214 ALOGW("AudioHardwareInput::onDeviceFound already has %d:%d",
215 devInfo.pcmCard, devInfo.pcmDevice);
216 return; // Got it already so no action needed.
217 }
218 }
219 }
220
221 // New device so find an empty slot and save it.
222 for (int i=0; i<kMaxDevices; i++) {
223 if (fgHidraw) {
224 if (!mDeviceInfos[HIDRAW_DEVICE][i].valid) {
225 ALOGD("AudioHardwareInput::onDeviceFound saving as device #%d", i);
226 mDeviceInfos[HIDRAW_DEVICE][i] = devInfo;
227 mDeviceInfos[HIDRAW_DEVICE][i].valid = true;
228 foundSlot = true;
229 /* Restart any currently running streams. */
230 standbyAllInputStreams(NULL);
231 break;
232 }
233 }
234 else if (!mDeviceInfos[SOUNDCARD_DEVICE][i].valid) {
235 ALOGD("AudioHardwareInput::onDeviceFound saving as device #%d", i);
236 mDeviceInfos[SOUNDCARD_DEVICE][i] = devInfo;
237 mDeviceInfos[SOUNDCARD_DEVICE][i].valid = true;
238 foundSlot = true;
239 /* Restart any currently running streams. */
240 standbyAllInputStreams(NULL);
241 break;
242 }
243 }
244
245 if (!foundSlot) {
246 ALOGW("AudioHardwareInput::onDeviceFound found more devices than expected! Dropped");
247 }
Lei Qian7bf98232018-09-20 17:56:38 +0800248}
249
250// called on the audio hotplug thread
251void AudioHardwareInput::onDeviceRemoved(unsigned int pcmCard, unsigned int pcmDevice)
252{
253 Mutex::Autolock _l(mLock);
254
255 ALOGD("AudioHardwareInput::onDeviceRemoved pcmCard = %d", pcmCard);
256 // Find matching DeviceInfo.
257 for (int i=0; i<kMaxDevices; i++) {
258 if (mDeviceInfos[SOUNDCARD_DEVICE][i].valid) {
259 if ((mDeviceInfos[SOUNDCARD_DEVICE][i].pcmCard == pcmCard) && (mDeviceInfos[0][i].pcmDevice == pcmDevice)) {
260 ALOGD("AudioHardwareInput::onDeviceRemoved matches #%d", i);
261 mDeviceInfos[SOUNDCARD_DEVICE][i].valid = false;
262 /* If currently active stream is using this device then restart. */
263 standbyAllInputStreams(&mDeviceInfos[SOUNDCARD_DEVICE][i]);
Lei Qian7bf98232018-09-20 17:56:38 +0800264 break;
265 }
266 }
267 }
268}
269
270// called on the audio hotplug thread
271void AudioHardwareInput::onDeviceRemoved(unsigned int hidrawIndex)
272{
273 Mutex::Autolock _l(mLock);
274
275 ALOGD("AudioHardwareInput::onDeviceRemoved hidrawIndex = %d", hidrawIndex);
276 // Find matching DeviceInfo.
277 for (int i=0; i<kMaxDevices; i++) {
278 if (mDeviceInfos[HIDRAW_DEVICE][i].valid) {
279 if (mDeviceInfos[HIDRAW_DEVICE][i].hidraw_index == hidrawIndex) {
280 ALOGD("AudioHardwareInput::onDeviceRemoved matches #%d", i);
281 mDeviceInfos[HIDRAW_DEVICE][i].valid = false;
282 /* If currently active stream is using this device then restart. */
283 standbyAllInputStreams(&mDeviceInfos[HIDRAW_DEVICE][i]);
Lei Qian7bf98232018-09-20 17:56:38 +0800284 break;
285 }
286 }
287 }
288}
289
Lei Qian7bf98232018-09-20 17:56:38 +0800290const AudioHotplugThread::DeviceInfo* AudioHardwareInput::getBestDevice(int inputSource)
291{
292 bool doVoiceRecognition = (inputSource == AUDIO_SOURCE_VOICE_RECOGNITION);
293 int chosenDeviceType = -1;
294 int chosenDeviceIndex = -1;
295 //Mutex::Autolock _l(mLock);
296
297 //ALOGD("%s: inputSource = %d, doVoiceRecognition = %d", __func__,
298 // inputSource, (doVoiceRecognition ? 1 : 0));
299 // RemoteControl is the only input device usable for voice recognition
300 // and no other devices are used for voice recognition.
301 // Currently the RemoteControl is the only device marked with forVoiceRecognition=true.
302 // A connected USB mic could be used for anything but voice recognition.
303 for (int i = 0; i < MAX_DEVICE_TYPE; i++) {
304 for (int j=0; j<kMaxDevices; j++) {
305 if (mDeviceInfos[i][j].valid) {
306 if (mDeviceInfos[i][j].forVoiceRecognition == doVoiceRecognition) {
307 chosenDeviceType = i;
308 chosenDeviceIndex = j;
309 break;
310 }
311 }
312 }
313 }
314
315
316 if (chosenDeviceIndex < 0) {
317 ALOGE("ERROR AudioHardwareInput::getBestDevice, none for source %d", inputSource);
318 } else {
319 ALOGD("AudioHardwareInput::getBestDevice chose #%d", chosenDeviceType);
320 }
321
322 return (chosenDeviceIndex >= 0) ? &mDeviceInfos[chosenDeviceType][chosenDeviceIndex] : NULL;
323}
324
Lei Qian7bf98232018-09-20 17:56:38 +0800325}; // namespace android