/* ** ** Copyright 2012, 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. */ #define LOG_TAG "AudioHAL:AudioHardwareInput" #include #include #include #include #include #include #include #include "AudioHardwareInput.h" #include "AudioHotplugThread.h" #include "AudioStreamIn.h" namespace android { // Global singleton. AudioHardwareInput gAudioHardwareInput; AudioHardwareInput::AudioHardwareInput() : mMicMute(false) { mHotplugThread = new AudioHotplugThread(*this); if (mHotplugThread == NULL) { ALOGE("Unable to create ATV Remote audio hotplug thread. " "Pluggable audio input devices will not function."); } else if (!mHotplugThread->start()) { ALOGE("Unable to start ATV Remote audio hotplug thread. " "Pluggable audio input devices will not function."); mHotplugThread.clear(); } for (int i=0; ishutdown(); mHotplugThread.clear(); } closeAllInputStreams(); } status_t AudioHardwareInput::setMicMute(bool mute) { mMicMute = mute; return NO_ERROR; } status_t AudioHardwareInput::getMicMute(bool* mute) { *mute = mMicMute; return NO_ERROR; } // milliseconds per ALSA period const uint32_t AudioHardwareInput::kPeriodMsec = 20; size_t AudioHardwareInput::calculateInputBufferSize(uint32_t outputSampleRate, audio_format_t format, uint32_t channelCount) { size_t size; // AudioFlinger expects audio buffers to be a multiple of 16 frames size = (kPeriodMsec * outputSampleRate) / 1000; size = ((size + 15) / 16) * 16; return size * channelCount * audio_bytes_per_sample(format); } status_t AudioHardwareInput::getInputBufferSize(const audio_config* config) { size_t size = calculateInputBufferSize(config->sample_rate, config->format, audio_channel_count_from_in_mask(config->channel_mask)); return size; } AudioStreamIn* AudioHardwareInput::openInputStream(uint32_t devices, audio_format_t* format, uint32_t* channelMask, uint32_t* sampleRate, status_t* status) { (void) devices; Mutex::Autolock _l(mLock); AudioStreamIn* in; in = new AudioStreamIn(*this); if (in == NULL) { *status = NO_MEMORY; return NULL; } *status = in->set(format, channelMask, sampleRate); if (*status != NO_ERROR) { delete in; return NULL; } mInputStreams.add(in); return in; } void AudioHardwareInput::closeInputStream(AudioStreamIn* in) { Mutex::Autolock _l(mLock); for (size_t i = 0; i < mInputStreams.size(); i++) { if (in == mInputStreams[i]) { mInputStreams.removeAt(i); in->standby(); delete in; break; } } } void AudioHardwareInput::closeAllInputStreams() { while (mInputStreams.size() != 0) { AudioStreamIn* in = mInputStreams[0]; mInputStreams.removeAt(0); in->standby(); delete in; } } void AudioHardwareInput::standbyAllInputStreams(const AudioHotplugThread::DeviceInfo* deviceInfo) { for (size_t i = 0; i < mInputStreams.size(); i++) { if (deviceInfo == NULL || deviceInfo == mInputStreams[i]->getDeviceInfo()) { mInputStreams[i]->standby(); } } } #define DUMP(a...) \ snprintf(buffer, SIZE, a); \ buffer[SIZE - 1] = 0; \ result.append(buffer); #define B2STR(b) b ? "true" : "false" status_t AudioHardwareInput::dump(int fd) { const size_t SIZE = 256; char buffer[SIZE]; String8 result; DUMP("\nAudioHardwareInput::dump\n"); for (int i=0; idump(fd); } } return NO_ERROR; } #undef DUMP #undef B2STR // called on the audio hotplug thread void AudioHardwareInput::onDeviceFound( const AudioHotplugThread::DeviceInfo& devInfo) { bool foundSlot = false; Mutex::Autolock _l(mLock); ALOGD("AudioHardwareInput::onDeviceFound pcmCard = %d", devInfo.pcmCard); for (int i=0; i= 0) ? &mDeviceInfos[chosenDeviceIndex] : NULL; } }; // namespace android