blob: 36052b6668f6530b32cef9770b9ba2238e8a2d3c [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"
24#include <utils/Log.h>
25
26#include <fcntl.h>
27#include <sys/eventfd.h>
28#include <sys/stat.h>
29#include <sys/types.h>
30#include <unistd.h>
31
32#include <utils/String8.h>
33
34#include "AudioHardwareInput.h"
35#include "AudioHotplugThread.h"
36#include "AudioHidrawStreamIn.h"
37#include "AudioSoundCardStreamIn.h"
38
39#include <vendor/amlogic/hardware/remotecontrol/1.0/IRemoteControl.h>
40using ::vendor::amlogic::hardware::remotecontrol::V1_0::IRemoteControl;
41
42namespace android {
43
44AudioHardwareInput::AudioHardwareInput()
45 : mMicMute(false)
46{
47 mHotplugThread = new AudioHotplugThread(*this);
48 if (mHotplugThread == NULL) {
49 ALOGE("Unable to create ATV Remote audio hotplug thread. "
50 "Pluggable audio input devices will not function.");
51 } else if (!mHotplugThread->start()) {
52 ALOGE("Unable to start ATV Remote audio hotplug thread. "
53 "Pluggable audio input devices will not function.");
54 mHotplugThread.clear();
55 }
56
57 for (int i = 0; i < MAX_DEVICE_TYPE; i++) {
58 for (int j=0; j<kMaxDevices; j++) {
59 memset(&mDeviceInfos[i][j], 0, sizeof(AudioHotplugThread::DeviceInfo));
60 }
61 }
62}
63
64AudioHardwareInput::~AudioHardwareInput()
65{
66 if (mHotplugThread != NULL) {
67 mHotplugThread->shutdown();
68 mHotplugThread.clear();
69 }
70
71 closeAllInputStreams();
72}
73
74status_t AudioHardwareInput::initCheck() {
75 return NO_ERROR;
76}
77
78char* AudioHardwareInput::getParameters(const char* keys) {
79 (void) keys;
80 return strdup("");
81}
82
83status_t AudioHardwareInput::setParameters(const char* kvpairs) {
84 (void) kvpairs;
85 return NO_ERROR;
86}
87
88status_t AudioHardwareInput::setMicMute(bool mute)
89{
90 mMicMute = mute;
91 return NO_ERROR;
92}
93
94status_t AudioHardwareInput::getMicMute(bool* mute)
95{
96 *mute = mMicMute;
97 return NO_ERROR;
98}
99
100// milliseconds per ALSA period
101const uint32_t AudioHardwareInput::kPeriodMsec = 10;
102
103size_t AudioHardwareInput::calculateInputBufferSize(uint32_t outputSampleRate,
104 audio_format_t format,
105 uint32_t channelCount)
106{
107 size_t size;
108
109 // AudioFlinger expects audio buffers to be a multiple of 16 frames
110 size = (kPeriodMsec * outputSampleRate) / 1000;
111 size = ((size + 15) / 16) * 16;
112
113 return size * channelCount * audio_bytes_per_sample(format);
114}
115
116status_t AudioHardwareInput::getInputBufferSize(const audio_config* config)
117{
118 size_t size = calculateInputBufferSize(config->sample_rate,
119 config->format,
120 audio_channel_count_from_in_mask(config->channel_mask));
121 return size;
122}
123
124AudioStreamIn* AudioHardwareInput::openInputStream(struct audio_stream_in *stream,
125 audio_format_t* format, uint32_t* channelMask, uint32_t* sampleRate,
126 status_t* status)
127{
128 ALOGI("%s: ++", __func__);
129 Mutex::Autolock _l(mLock);
130 AudioStreamIn* in = NULL;
131 const AudioHotplugThread::DeviceInfo* devInfo = getBestDevice(AUDIO_SOURCE_VOICE_RECOGNITION);
132
133 if (devInfo != NULL) {
134 if (devInfo->pcmCard > 0 && devInfo->pcmDevice > 0) {
135 in = new AudioSoundCardStreamIn(*this);
136 }
137 else {
138 in = new AudioHidrawStreamIn(*this);
139 }
140 }
141 if (in == NULL) {
142 *status = NO_MEMORY;
143 goto done;
144 }
145
146 *status = in->set(stream, format, channelMask, sampleRate);
147
148 if (*status != NO_ERROR) {
149 delete in;
150 in = NULL;
151 goto done;
152 }
153
154 mInputStreams.add(in);
155
156done:
157 ALOGI("%s: --", __func__);
158 return in;
159}
160
161void AudioHardwareInput::closeInputStream(AudioStreamIn* in)
162{
163 Mutex::Autolock _l(mLock);
164
165 for (size_t i = 0; i < mInputStreams.size(); i++) {
166 if (in == mInputStreams[i]) {
167 mInputStreams.removeAt(i);
168 in->standby();
169 delete in;
170 break;
171 }
172 }
173}
174
175void AudioHardwareInput::closeAllInputStreams()
176{
177 while (mInputStreams.size() != 0) {
178 AudioStreamIn* in = mInputStreams[0];
179 mInputStreams.removeAt(0);
180 in->standby();
181 delete in;
182 }
183}
184
185void AudioHardwareInput::standbyAllInputStreams(const AudioHotplugThread::DeviceInfo* deviceInfo)
186{
187 for (size_t i = 0; i < mInputStreams.size(); i++) {
188 if (deviceInfo == NULL || deviceInfo == mInputStreams[i]->getDeviceInfo()) {
189 mInputStreams[i]->standby();
190 }
191 }
192}
193
194// called on the audio hotplug thread
195void AudioHardwareInput::onDeviceFound(
196 const AudioHotplugThread::DeviceInfo& devInfo, bool fgHidraw)
197{
198 bool foundSlot = false;
199 Mutex::Autolock _l(mLock);
200
201 ALOGD("AudioHardwareInput::onDeviceFound hidraw flag = %d", fgHidraw);
202
203 for (int i=0; i<kMaxDevices; i++) {
204 if (fgHidraw) {
205 if (mDeviceInfos[HIDRAW_DEVICE][i].valid) {
206 if (mDeviceInfos[HIDRAW_DEVICE][i].hidraw_index == devInfo.hidraw_index) {
207 ALOGW("AudioHardwareInput::onDeviceFound already has %d",
208 devInfo.hidraw_index);
209 return; // Got it already so no action needed.
210 }
211 }
212 }
213 else if (mDeviceInfos[SOUNDCARD_DEVICE][i].valid){
214 if ((mDeviceInfos[SOUNDCARD_DEVICE][i].pcmCard == devInfo.pcmCard)
215 && (mDeviceInfos[SOUNDCARD_DEVICE][i].pcmDevice == devInfo.pcmDevice)) {
216 ALOGW("AudioHardwareInput::onDeviceFound already has %d:%d",
217 devInfo.pcmCard, devInfo.pcmDevice);
218 return; // Got it already so no action needed.
219 }
220 }
221 }
222
223 // New device so find an empty slot and save it.
224 for (int i=0; i<kMaxDevices; i++) {
225 if (fgHidraw) {
226 if (!mDeviceInfos[HIDRAW_DEVICE][i].valid) {
227 ALOGD("AudioHardwareInput::onDeviceFound saving as device #%d", i);
228 mDeviceInfos[HIDRAW_DEVICE][i] = devInfo;
229 mDeviceInfos[HIDRAW_DEVICE][i].valid = true;
230 foundSlot = true;
231 /* Restart any currently running streams. */
232 standbyAllInputStreams(NULL);
233 break;
234 }
235 }
236 else if (!mDeviceInfos[SOUNDCARD_DEVICE][i].valid) {
237 ALOGD("AudioHardwareInput::onDeviceFound saving as device #%d", i);
238 mDeviceInfos[SOUNDCARD_DEVICE][i] = devInfo;
239 mDeviceInfos[SOUNDCARD_DEVICE][i].valid = true;
240 foundSlot = true;
241 /* Restart any currently running streams. */
242 standbyAllInputStreams(NULL);
243 break;
244 }
245 }
246
247 if (!foundSlot) {
248 ALOGW("AudioHardwareInput::onDeviceFound found more devices than expected! Dropped");
249 }
250 else {
251 setRemoteControlDeviceStatus(true);
252 }
253}
254
255// called on the audio hotplug thread
256void AudioHardwareInput::onDeviceRemoved(unsigned int pcmCard, unsigned int pcmDevice)
257{
258 Mutex::Autolock _l(mLock);
259
260 ALOGD("AudioHardwareInput::onDeviceRemoved pcmCard = %d", pcmCard);
261 // Find matching DeviceInfo.
262 for (int i=0; i<kMaxDevices; i++) {
263 if (mDeviceInfos[SOUNDCARD_DEVICE][i].valid) {
264 if ((mDeviceInfos[SOUNDCARD_DEVICE][i].pcmCard == pcmCard) && (mDeviceInfos[0][i].pcmDevice == pcmDevice)) {
265 ALOGD("AudioHardwareInput::onDeviceRemoved matches #%d", i);
266 mDeviceInfos[SOUNDCARD_DEVICE][i].valid = false;
267 /* If currently active stream is using this device then restart. */
268 standbyAllInputStreams(&mDeviceInfos[SOUNDCARD_DEVICE][i]);
269 setRemoteControlDeviceStatus(false);
270 break;
271 }
272 }
273 }
274}
275
276// called on the audio hotplug thread
277void AudioHardwareInput::onDeviceRemoved(unsigned int hidrawIndex)
278{
279 Mutex::Autolock _l(mLock);
280
281 ALOGD("AudioHardwareInput::onDeviceRemoved hidrawIndex = %d", hidrawIndex);
282 // Find matching DeviceInfo.
283 for (int i=0; i<kMaxDevices; i++) {
284 if (mDeviceInfos[HIDRAW_DEVICE][i].valid) {
285 if (mDeviceInfos[HIDRAW_DEVICE][i].hidraw_index == hidrawIndex) {
286 ALOGD("AudioHardwareInput::onDeviceRemoved matches #%d", i);
287 mDeviceInfos[HIDRAW_DEVICE][i].valid = false;
288 /* If currently active stream is using this device then restart. */
289 standbyAllInputStreams(&mDeviceInfos[HIDRAW_DEVICE][i]);
290 setRemoteControlDeviceStatus(false);
291 break;
292 }
293 }
294 }
295}
296
297bool AudioHardwareInput::onDeviceNotify() {
298 Mutex::Autolock _l(mLock);
299 bool flag = false;
300
301 for (int i = 0; i < MAX_DEVICE_TYPE; i++) {
302 for (int j=0; j<kMaxDevices; j++) {
303 if (mDeviceInfos[i][j].valid && mDeviceInfos[i][j].forVoiceRecognition) {
304 flag = true;
305 break;
306 }
307 }
308 }
309 return setRemoteControlDeviceStatus(flag);
310}
311
312const AudioHotplugThread::DeviceInfo* AudioHardwareInput::getBestDevice(int inputSource)
313{
314 bool doVoiceRecognition = (inputSource == AUDIO_SOURCE_VOICE_RECOGNITION);
315 int chosenDeviceType = -1;
316 int chosenDeviceIndex = -1;
317 //Mutex::Autolock _l(mLock);
318
319 //ALOGD("%s: inputSource = %d, doVoiceRecognition = %d", __func__,
320 // inputSource, (doVoiceRecognition ? 1 : 0));
321 // RemoteControl is the only input device usable for voice recognition
322 // and no other devices are used for voice recognition.
323 // Currently the RemoteControl is the only device marked with forVoiceRecognition=true.
324 // A connected USB mic could be used for anything but voice recognition.
325 for (int i = 0; i < MAX_DEVICE_TYPE; i++) {
326 for (int j=0; j<kMaxDevices; j++) {
327 if (mDeviceInfos[i][j].valid) {
328 if (mDeviceInfos[i][j].forVoiceRecognition == doVoiceRecognition) {
329 chosenDeviceType = i;
330 chosenDeviceIndex = j;
331 break;
332 }
333 }
334 }
335 }
336
337
338 if (chosenDeviceIndex < 0) {
339 ALOGE("ERROR AudioHardwareInput::getBestDevice, none for source %d", inputSource);
340 } else {
341 ALOGD("AudioHardwareInput::getBestDevice chose #%d", chosenDeviceType);
342 }
343
344 return (chosenDeviceIndex >= 0) ? &mDeviceInfos[chosenDeviceType][chosenDeviceIndex] : NULL;
345}
346
347void AudioHardwareInput::setRemoteControlMicEnabled(bool flag)
348{
349 sp<IRemoteControl> service = IRemoteControl::getService();
350 if (service == NULL) {
351 ALOGE("%s: No RemoteControl service detected, ignoring", __func__);
352 return;
353 }
354
355 service->setMicEnable(flag == true ? 1 : 0);
356}
357
358bool AudioHardwareInput::setRemoteControlDeviceStatus(bool flag)
359{
360 sp<IRemoteControl> service = IRemoteControl::getService();
361 if (service == NULL) {
362 ALOGW("%s: No RemoteControl service detected, start poll...", __func__);
363 mHotplugThread->polling(flag);
364 return false;
365 }
366
367 service->onDeviceChanged(flag == true ? 1 : 0);
368
369 return true;
370}
371
372}; // namespace android