audioflinger: enumerate all the possible audio interfaces
Keep track of the primary interface that handles the master volume,
etc.
Change-Id: Ib0701fccff8d8783a99035a241ab7c8ec75c00ac
Signed-off-by: Dima Zavin <dima@android.com>
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 301f467..e494d05 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -136,49 +136,98 @@
service->addBatteryData(params);
}
+static int load_audio_interface(const char *if_name, const hw_module_t **mod,
+ audio_hw_device_t **dev)
+{
+ int rc;
+
+ rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, mod);
+ if (rc)
+ goto out;
+
+ rc = audio_hw_device_open(*mod, dev);
+ LOGE_IF(rc, "couldn't open audio hw device in %s.%s (%s)",
+ AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
+ if (rc)
+ goto out;
+
+ return 0;
+
+out:
+ *mod = NULL;
+ *dev = NULL;
+ return rc;
+}
+
+static const char *audio_interfaces[] = {
+ "primary",
+ "a2dp",
+ "usb",
+};
+#define ARRAY_SIZE(x) (sizeof((x))/sizeof(((x)[0])))
+
// ----------------------------------------------------------------------------
AudioFlinger::AudioFlinger()
: BnAudioFlinger(),
- mAudioHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
+ mPrimaryHardwareDev(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
{
- const hw_module_t *module;
- int rc;
- char mod_name[PATH_MAX];
+ int rc = 0;
Mutex::Autolock _l(mLock);
+ /* TODO: move all this work into an Init() function */
mHardwareStatus = AUDIO_HW_IDLE;
- /* get the audio hw module and create an audio_hw device */
- snprintf(mod_name, PATH_MAX, "%s.%s", AUDIO_HARDWARE_MODULE_ID, "primary");
- rc = hw_get_module(mod_name, &module);
- if (rc)
- return;
+ for (size_t i = 0; i < ARRAY_SIZE(audio_interfaces); i++) {
+ const hw_module_t *mod;
+ audio_hw_device_t *dev;
- rc = audio_hw_device_open(module, &mAudioHardwareDev);
- LOGE_IF(rc, "couldn't open audio hw device (%s)", strerror(-rc));
- if (rc)
- return;
+ rc = load_audio_interface(audio_interfaces[i], &mod, &dev);
+ if (rc)
+ continue;
+
+ LOGI("Loaded %s audio interface from %s (%s)", audio_interfaces[i],
+ mod->name, mod->id);
+ mAudioHwDevs.push(dev);
+
+ if (!mPrimaryHardwareDev) {
+ mPrimaryHardwareDev = dev;
+ LOGI("Using '%s' (%s.%s) as the primary audio interface",
+ AUDIO_HARDWARE_INTERFACE, mod->name, mod->id,
+ audio_interfaces[i]);
+ }
+ }
mHardwareStatus = AUDIO_HW_INIT;
- rc = mAudioHardwareDev->init_check(mAudioHardwareDev);
- if (rc == 0) {
- AutoMutex lock(mHardwareLock);
- mMode = AUDIO_MODE_NORMAL;
- mHardwareStatus = AUDIO_HW_SET_MODE;
- mAudioHardwareDev->set_mode(mAudioHardwareDev, mMode);
- mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
- mAudioHardwareDev->set_master_volume(mAudioHardwareDev, 1.0f);
- mHardwareStatus = AUDIO_HW_IDLE;
- } else {
- LOGE("Couldn't even initialize the stubbed audio hardware!");
+ if (!mPrimaryHardwareDev || mAudioHwDevs.size() == 0) {
+ LOGE("Primary audio interface not found");
+ return;
+ }
+
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+
+ mHardwareStatus = AUDIO_HW_INIT;
+ rc = dev->init_check(dev);
+ if (rc == 0) {
+ AutoMutex lock(mHardwareLock);
+
+ mMode = AUDIO_MODE_NORMAL;
+ mHardwareStatus = AUDIO_HW_SET_MODE;
+ dev->set_mode(dev, mMode);
+ mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+ dev->set_master_volume(dev, 1.0f);
+ mHardwareStatus = AUDIO_HW_IDLE;
+ }
}
}
AudioFlinger::~AudioFlinger()
{
+ int num_devs = mAudioHwDevs.size();
+
while (!mRecordThreads.isEmpty()) {
// closeInput() will remove first entry from mRecordThreads
closeInput(mRecordThreads.keyAt(0));
@@ -187,12 +236,24 @@
// closeOutput() will remove first entry from mPlaybackThreads
closeOutput(mPlaybackThreads.keyAt(0));
}
- if (mAudioHardwareDev) {
- audio_hw_device_close(mAudioHardwareDev);
+
+ for (int i = 0; i < num_devs; i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ audio_hw_device_close(dev);
}
+ mAudioHwDevs.clear();
}
-
+audio_hw_device_t* AudioFlinger::findSuitableHwDev_l(uint32_t devices)
+{
+ /* first matching HW device is returned */
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ if ((dev->get_supported_devices(dev) & devices) == devices)
+ return dev;
+ }
+ return NULL;
+}
status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
{
@@ -291,8 +352,10 @@
mRecordThreads.valueAt(i)->dump(fd, args);
}
- if (mAudioHardwareDev) {
- mAudioHardwareDev->dump(mAudioHardwareDev, fd);
+ // dump all hardware devs
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ dev->dump(dev, fd);
}
if (locked) mLock.unlock();
}
@@ -468,7 +531,7 @@
{ // scope for the lock
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
- if (mAudioHardwareDev->set_master_volume(mAudioHardwareDev, value) == NO_ERROR) {
+ if (mPrimaryHardwareDev->set_master_volume(mPrimaryHardwareDev, value) == NO_ERROR) {
value = 1.0f;
}
mHardwareStatus = AUDIO_HW_IDLE;
@@ -498,7 +561,7 @@
{ // scope for the lock
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_MODE;
- ret = mAudioHardwareDev->set_mode(mAudioHardwareDev, mode);
+ ret = mPrimaryHardwareDev->set_mode(mPrimaryHardwareDev, mode);
mHardwareStatus = AUDIO_HW_IDLE;
}
@@ -521,7 +584,7 @@
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
- status_t ret = mAudioHardwareDev->set_mic_mute(mAudioHardwareDev, state);
+ status_t ret = mPrimaryHardwareDev->set_mic_mute(mPrimaryHardwareDev, state);
mHardwareStatus = AUDIO_HW_IDLE;
return ret;
}
@@ -530,7 +593,7 @@
{
bool state = AUDIO_MODE_INVALID;
mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
- mAudioHardwareDev->get_mic_mute(mAudioHardwareDev, &state);
+ mPrimaryHardwareDev->get_mic_mute(mPrimaryHardwareDev, &state);
mHardwareStatus = AUDIO_HW_IDLE;
return state;
}
@@ -658,9 +721,14 @@
if (ioHandle == 0) {
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_SET_PARAMETER;
- result = mAudioHardwareDev->set_parameters(mAudioHardwareDev, keyValuePairs.string());
+ status_t final_result = NO_ERROR;
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ result = dev->set_parameters(dev, keyValuePairs.string());
+ final_result = result ?: final_result;
+ }
mHardwareStatus = AUDIO_HW_IDLE;
- return result;
+ return final_result;
}
// hold a strong ref on thread in case closeOutput() or closeInput() is called
@@ -686,12 +754,14 @@
// ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
if (ioHandle == 0) {
- char *s;
String8 out_s8;
- s = mAudioHardwareDev->get_parameters(mAudioHardwareDev, keys.string());
- out_s8 = String8(s);
- free(s);
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ audio_hw_device_t *dev = mAudioHwDevs[i];
+ char *s = dev->get_parameters(dev, keys.string());
+ out_s8 += String8(s);
+ free(s);
+ }
return out_s8;
}
@@ -710,7 +780,7 @@
size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
{
- return mAudioHardwareDev->get_input_buffer_size(mAudioHardwareDev, sampleRate, format, channelCount);
+ return mPrimaryHardwareDev->get_input_buffer_size(mPrimaryHardwareDev, sampleRate, format, channelCount);
}
unsigned int AudioFlinger::getInputFramesLost(int ioHandle)
@@ -737,7 +807,7 @@
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
- status_t ret = mAudioHardwareDev->set_voice_volume(mAudioHardwareDev, value);
+ status_t ret = mPrimaryHardwareDev->set_voice_volume(mPrimaryHardwareDev, value);
mHardwareStatus = AUDIO_HW_IDLE;
return ret;
@@ -977,7 +1047,7 @@
// ----------------------------------------------------------------------------
-AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device)
+AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
: ThreadBase(audioFlinger, id),
mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
@@ -1190,7 +1260,7 @@
uint32_t AudioFlinger::PlaybackThread::latency() const
{
if (mOutput) {
- return mOutput->get_latency(mOutput);
+ return mOutput->stream->get_latency(mOutput->stream);
}
else {
return 0;
@@ -1287,7 +1357,7 @@
String8 out_s8;
char *s;
- s = mOutput->common.get_parameters(&mOutput->common, keys.string());
+ s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
out_s8 = String8(s);
free(s);
return out_s8;
@@ -1322,12 +1392,12 @@
void AudioFlinger::PlaybackThread::readOutputParameters()
{
- mSampleRate = mOutput->common.get_sample_rate(&mOutput->common);
- mChannels = mOutput->common.get_channels(&mOutput->common);
+ mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common);
+ mChannels = mOutput->stream->common.get_channels(&mOutput->stream->common);
mChannelCount = (uint16_t)popcount(mChannels);
- mFormat = mOutput->common.get_format(&mOutput->common);
- mFrameSize = (uint16_t)audio_stream_frame_size(&mOutput->common);
- mFrameCount = mOutput->common.get_buffer_size(&mOutput->common) / mFrameSize;
+ mFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
+ mFrameSize = (uint16_t)audio_stream_frame_size(&mOutput->stream->common);
+ mFrameCount = mOutput->stream->common.get_buffer_size(&mOutput->stream->common) / mFrameSize;
// FIXME - Current mixer implementation only supports stereo output: Always
// Allocate a stereo buffer even if HW output is mono.
@@ -1355,9 +1425,9 @@
if (mOutput == 0) {
return INVALID_OPERATION;
}
- *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->common);
+ *halFrames = mBytesWritten / audio_stream_frame_size(&mOutput->stream->common);
- return mOutput->get_render_position(mOutput, dspFrames);
+ return mOutput->stream->get_render_position(mOutput->stream, dspFrames);
}
uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
@@ -1428,7 +1498,7 @@
// ----------------------------------------------------------------------------
-AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device)
+AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
: PlaybackThread(audioFlinger, output, id, device),
mAudioMixer(0)
{
@@ -1487,7 +1557,7 @@
mSuspended) {
if (!mStandby) {
LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
- mOutput->common.standby(&mOutput->common);
+ mOutput->stream->common.standby(&mOutput->stream->common);
mStandby = true;
mBytesWritten = 0;
}
@@ -1564,7 +1634,7 @@
mInWrite = true;
mBytesWritten += mixBufferSize;
- int bytesWritten = (int)mOutput->write(mOutput, mMixBuffer, mixBufferSize);
+ int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
mNumWrites++;
mInWrite = false;
@@ -1599,7 +1669,7 @@
}
if (!mStandby) {
- mOutput->common.standby(&mOutput->common);
+ mOutput->stream->common.standby(&mOutput->stream->common);
}
LOGV("MixerThread %p exiting", this);
@@ -1903,13 +1973,13 @@
}
if (status == NO_ERROR) {
- status = mOutput->common.set_parameters(&mOutput->common,
+ status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
keyValuePair.string());
if (!mStandby && status == INVALID_OPERATION) {
- mOutput->common.standby(&mOutput->common);
+ mOutput->stream->common.standby(&mOutput->stream->common);
mStandby = true;
mBytesWritten = 0;
- status = mOutput->common.set_parameters(&mOutput->common,
+ status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
keyValuePair.string());
}
if (status == NO_ERROR && reconfig) {
@@ -1954,7 +2024,7 @@
uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
{
- return (uint32_t)(mOutput->get_latency(mOutput) * 1000) / 2;
+ return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
}
uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
@@ -1968,7 +2038,7 @@
}
// ----------------------------------------------------------------------------
-AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device)
+AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
: PlaybackThread(audioFlinger, output, id, device)
{
mType = PlaybackThread::DIRECT;
@@ -2118,7 +2188,7 @@
// wait until we have something to do...
if (!mStandby) {
LOGV("Audio hardware entering standby, mixer %p\n", this);
- mOutput->common.standby(&mOutput->common);
+ mOutput->stream->common.standby(&mOutput->stream->common);
mStandby = true;
mBytesWritten = 0;
}
@@ -2203,7 +2273,7 @@
// If audio HAL implements volume control,
// force software volume to nominal value
- if (mOutput->set_volume(mOutput, left, right) == NO_ERROR) {
+ if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
left = 1.0f;
right = 1.0f;
}
@@ -2326,7 +2396,7 @@
mLastWriteTime = systemTime();
mInWrite = true;
mBytesWritten += mixBufferSize;
- int bytesWritten = (int)mOutput->write(mOutput, mMixBuffer, mixBufferSize);
+ int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
mNumWrites++;
mInWrite = false;
@@ -2348,7 +2418,7 @@
}
if (!mStandby) {
- mOutput->common.standby(&mOutput->common);
+ mOutput->stream->common.standby(&mOutput->stream->common);
}
LOGV("DirectOutputThread %p exiting", this);
@@ -2388,13 +2458,13 @@
}
}
if (status == NO_ERROR) {
- status = mOutput->common.set_parameters(&mOutput->common,
+ status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
keyValuePair.string());
if (!mStandby && status == INVALID_OPERATION) {
- mOutput->common.standby(&mOutput->common);
+ mOutput->stream->common.standby(&mOutput->stream->common);
mStandby = true;
mBytesWritten = 0;
- status = mOutput->common.set_parameters(&mOutput->common,
+ status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
keyValuePair.string());
}
if (status == NO_ERROR && reconfig) {
@@ -2416,7 +2486,7 @@
{
uint32_t time;
if (audio_is_linear_pcm(mFormat)) {
- time = (uint32_t)(mOutput->get_latency(mOutput) * 1000) / 2;
+ time = (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
} else {
time = 10000;
}
@@ -3705,7 +3775,7 @@
// ----------------------------------------------------------------------------
-AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, struct audio_stream_in *input, uint32_t sampleRate, uint32_t channels, int id) :
+AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
ThreadBase(audioFlinger, id),
mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
{
@@ -3751,7 +3821,7 @@
checkForNewParameters_l();
if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
if (!mStandby) {
- mInput->common.standby(&mInput->common);
+ mInput->stream->common.standby(&mInput->stream->common);
mStandby = true;
}
@@ -3766,7 +3836,7 @@
if (mActiveTrack != 0) {
if (mActiveTrack->mState == TrackBase::PAUSING) {
if (!mStandby) {
- mInput->common.standby(&mInput->common);
+ mInput->stream->common.standby(&mInput->stream->common);
mStandby = true;
}
mActiveTrack.clear();
@@ -3832,10 +3902,10 @@
if (framesOut && mFrameCount == mRsmpInIndex) {
if (framesOut == mFrameCount &&
((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) {
- mBytesRead = mInput->read(mInput, buffer.raw, mInputBytes);
+ mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes);
framesOut = 0;
} else {
- mBytesRead = mInput->read(mInput, mRsmpInBuffer, mInputBytes);
+ mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
mRsmpInIndex = 0;
}
if (mBytesRead < 0) {
@@ -3843,7 +3913,7 @@
if (mActiveTrack->mState == TrackBase::ACTIVE) {
// Force input into standby so that it tries to
// recover at next read attempt
- mInput->common.standby(&mInput->common);
+ mInput->stream->common.standby(&mInput->stream->common);
usleep(5000);
}
mRsmpInIndex = mFrameCount;
@@ -3898,7 +3968,7 @@
}
if (!mStandby) {
- mInput->common.standby(&mInput->common);
+ mInput->stream->common.standby(&mInput->stream->common);
}
mActiveTrack.clear();
@@ -4030,13 +4100,13 @@
int channelCount;
if (framesReady == 0) {
- mBytesRead = mInput->read(mInput, mRsmpInBuffer, mInputBytes);
+ mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes);
if (mBytesRead < 0) {
LOGE("RecordThread::getNextBuffer() Error reading audio input");
if (mActiveTrack->mState == TrackBase::ACTIVE) {
// Force input into standby so that it tries to
// recover at next read attempt
- mInput->common.standby(&mInput->common);
+ mInput->stream->common.standby(&mInput->stream->common);
usleep(5000);
}
buffer->raw = 0;
@@ -4103,17 +4173,17 @@
}
}
if (status == NO_ERROR) {
- status = mInput->common.set_parameters(&mInput->common, keyValuePair.string());
+ status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
if (status == INVALID_OPERATION) {
- mInput->common.standby(&mInput->common);
- status = mInput->common.set_parameters(&mInput->common, keyValuePair.string());
+ mInput->stream->common.standby(&mInput->stream->common);
+ status = mInput->stream->common.set_parameters(&mInput->stream->common, keyValuePair.string());
}
if (reconfig) {
if (status == BAD_VALUE &&
- reqFormat == mInput->common.get_format(&mInput->common) &&
+ reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
- ((int)mInput->common.get_sample_rate(&mInput->common) <= (2 * reqSamplingRate)) &&
- (popcount(mInput->common.get_channels(&mInput->common)) < 3) &&
+ ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
+ (popcount(mInput->stream->common.get_channels(&mInput->stream->common)) < 3) &&
(reqChannelCount < 3)) {
status = NO_ERROR;
}
@@ -4138,7 +4208,7 @@
char *s;
String8 out_s8;
- s = mInput->common.get_parameters(&mInput->common, keys.string());
+ s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
out_s8 = String8(s);
free(s);
return out_s8;
@@ -4173,12 +4243,12 @@
if (mResampler) delete mResampler;
mResampler = 0;
- mSampleRate = mInput->common.get_sample_rate(&mInput->common);
- mChannels = mInput->common.get_channels(&mInput->common);
+ mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
+ mChannels = mInput->stream->common.get_channels(&mInput->stream->common);
mChannelCount = (uint16_t)popcount(mChannels);
- mFormat = mInput->common.get_format(&mInput->common);
- mFrameSize = (uint16_t)audio_stream_frame_size(&mInput->common);
- mInputBytes = mInput->common.get_buffer_size(&mInput->common);
+ mFormat = mInput->stream->common.get_format(&mInput->stream->common);
+ mFrameSize = (uint16_t)audio_stream_frame_size(&mInput->stream->common);
+ mInputBytes = mInput->stream->common.get_buffer_size(&mInput->stream->common);
mFrameCount = mInputBytes / mFrameSize;
mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
@@ -4208,7 +4278,7 @@
unsigned int AudioFlinger::RecordThread::getInputFramesLost()
{
- return mInput->get_input_frames_lost(mInput);
+ return mInput->stream->get_input_frames_lost(mInput->stream);
}
// ----------------------------------------------------------------------------
@@ -4227,7 +4297,8 @@
uint32_t format = pFormat ? *pFormat : 0;
uint32_t channels = pChannels ? *pChannels : 0;
uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
- struct audio_stream_out *output;
+ audio_stream_out_t *outStream;
+ audio_hw_device_t *outHwDev;
LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
pDevices ? *pDevices : 0,
@@ -4239,23 +4310,27 @@
if (pDevices == NULL || *pDevices == 0) {
return 0;
}
+
Mutex::Autolock _l(mLock);
- status = mAudioHardwareDev->open_output_stream(mAudioHardwareDev, *pDevices,
- (int *)&format,
- &channels,
- &samplingRate,
- &output);
+ outHwDev = findSuitableHwDev_l(*pDevices);
+ if (outHwDev == NULL)
+ return 0;
+
+ status = outHwDev->open_output_stream(outHwDev, *pDevices, (int *)&format,
+ &channels, &samplingRate, &outStream);
LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
- output,
+ outStream,
samplingRate,
format,
channels,
status);
mHardwareStatus = AUDIO_HW_IDLE;
- if (output != 0) {
+ if (outStream != NULL) {
+ AudioStreamOut *output = new AudioStreamOut(outHwDev, outStream);
int id = nextUniqueId_l();
+
if ((flags & AUDIO_POLICY_OUTPUT_FLAG_DIRECT) ||
(format != AUDIO_FORMAT_PCM_16_BIT) ||
(channels != AUDIO_CHANNEL_OUT_STEREO)) {
@@ -4329,7 +4404,9 @@
thread->exit();
if (thread->type() != PlaybackThread::DUPLICATING) {
- mAudioHardwareDev->close_output_stream(mAudioHardwareDev, thread->getOutput());
+ AudioStreamOut *out = thread->getOutput();
+ out->hwDev->close_output_stream(out->hwDev, out->stream);
+ delete out;
}
return NO_ERROR;
}
@@ -4379,22 +4456,25 @@
uint32_t reqSamplingRate = samplingRate;
uint32_t reqFormat = format;
uint32_t reqChannels = channels;
- struct audio_stream_in *input;
+ audio_stream_in_t *inStream;
+ audio_hw_device_t *inHwDev;
if (pDevices == NULL || *pDevices == 0) {
return 0;
}
+
Mutex::Autolock _l(mLock);
- status = mAudioHardwareDev->open_input_stream(mAudioHardwareDev,
- *pDevices,
- (int *)&format,
- &channels,
- &samplingRate,
+ inHwDev = findSuitableHwDev_l(*pDevices);
+ if (inHwDev == NULL)
+ return 0;
+
+ status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,
+ &channels, &samplingRate,
(audio_in_acoustics_t)acoustics,
- &input);
+ &inStream);
LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
- input,
+ inStream,
samplingRate,
format,
channels,
@@ -4404,21 +4484,20 @@
// If the input could not be opened with the requested parameters and we can handle the conversion internally,
// try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
// or stereo to mono conversions on 16 bit PCM inputs.
- if (input == 0 && status == BAD_VALUE &&
+ if (inStream == NULL && status == BAD_VALUE &&
reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
(samplingRate <= 2 * reqSamplingRate) &&
(popcount(channels) < 3) && (popcount(reqChannels) < 3)) {
LOGV("openInput() reopening with proposed sampling rate and channels");
- status = mAudioHardwareDev->open_input_stream(mAudioHardwareDev,
- *pDevices,
- (int *)&format,
- &channels,
- &samplingRate,
+ status = inHwDev->open_input_stream(inHwDev, *pDevices, (int *)&format,
+ &channels, &samplingRate,
(audio_in_acoustics_t)acoustics,
- &input);
+ &inStream);
}
- if (input != 0) {
+ if (inStream != NULL) {
+ AudioStreamIn *input = new AudioStreamIn(inHwDev, inStream);
+
int id = nextUniqueId_l();
// Start record thread
thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id);
@@ -4428,7 +4507,7 @@
if (pFormat) *pFormat = format;
if (pChannels) *pChannels = reqChannels;
- input->common.standby(&input->common);
+ input->stream->common.standby(&input->stream->common);
// notify client processes of the new input creation
thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
@@ -4457,7 +4536,9 @@
}
thread->exit();
- mAudioHardwareDev->close_input_stream(mAudioHardwareDev, thread->getInput());
+ AudioStreamIn *in = thread->getInput();
+ in->hwDev->close_input_stream(in->hwDev, in->stream);
+ delete in;
return NO_ERROR;
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 4ac1ee3..94f7861 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -32,12 +32,14 @@
#include <utils/Errors.h>
#include <utils/threads.h>
#include <utils/SortedVector.h>
+#include <utils/TypeHelpers.h>
#include <utils/Vector.h>
#include <binder/BinderService.h>
#include <binder/MemoryDealer.h>
#include <hardware/audio.h>
+#include <hardware/audio_hal.h>
#include "AudioBufferProvider.h"
@@ -49,7 +51,6 @@
class AudioBuffer;
class AudioResampler;
-
// ----------------------------------------------------------------------------
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
@@ -211,6 +212,7 @@
AudioFlinger();
virtual ~AudioFlinger();
+ audio_hw_device_t* findSuitableHwDev_l(uint32_t devices);
// Internal dump utilites.
status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
@@ -268,6 +270,8 @@
class EffectModule;
class EffectHandle;
class EffectChain;
+ struct AudioStreamOut;
+ struct AudioStreamIn;
class ThreadBase : public Thread {
public:
@@ -554,7 +558,7 @@
DuplicatingThread* mSourceThread;
}; // end of OutputTrack
- PlaybackThread (const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device);
+ PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device);
virtual ~PlaybackThread();
virtual status_t dump(int fd, const Vector<String16>& args);
@@ -588,7 +592,7 @@
int sessionId,
status_t *status);
- struct audio_stream_out* getOutput() { return mOutput; }
+ AudioStreamOut* getOutput() { return mOutput; }
virtual int type() const { return mType; }
void suspend() { mSuspended++; }
@@ -690,7 +694,7 @@
SortedVector< sp<Track> > mTracks;
// mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread
stream_type_t mStreamTypes[AUDIO_STREAM_CNT + 1];
- struct audio_stream_out* mOutput;
+ AudioStreamOut* mOutput;
float mMasterVolume;
nsecs_t mLastWriteTime;
int mNumWrites;
@@ -703,7 +707,7 @@
class MixerThread : public PlaybackThread {
public:
MixerThread (const sp<AudioFlinger>& audioFlinger,
- struct audio_stream_out* output,
+ AudioStreamOut* output,
int id,
uint32_t device);
virtual ~MixerThread();
@@ -730,7 +734,7 @@
class DirectOutputThread : public PlaybackThread {
public:
- DirectOutputThread (const sp<AudioFlinger>& audioFlinger, struct audio_stream_out* output, int id, uint32_t device);
+ DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device);
~DirectOutputThread();
// Thread virtuals
@@ -854,7 +858,7 @@
RecordThread(const sp<AudioFlinger>& audioFlinger,
- struct audio_stream_in *input,
+ AudioStreamIn *input,
uint32_t sampleRate,
uint32_t channels,
int id);
@@ -867,7 +871,7 @@
status_t start(RecordTrack* recordTrack);
void stop(RecordTrack* recordTrack);
status_t dump(int fd, const Vector<String16>& args);
- struct audio_stream_in* getInput() { return mInput; }
+ AudioStreamIn* getInput() { return mInput; }
virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
@@ -879,7 +883,7 @@
private:
RecordThread();
- struct audio_stream_in *mInput;
+ AudioStreamIn *mInput;
sp<RecordTrack> mActiveTrack;
Condition mStartStopCond;
AudioResampler *mResampler;
@@ -1159,17 +1163,32 @@
uint32_t mStrategy; // strategy for this effect chain
};
+ struct AudioStreamOut {
+ audio_hw_device_t *hwDev;
+ audio_stream_out_t *stream;
+
+ AudioStreamOut(audio_hw_device_t *dev, audio_stream_out_t *out) :
+ hwDev(dev), stream(out) {}
+ };
+
+ struct AudioStreamIn {
+ audio_hw_device_t *hwDev;
+ audio_stream_in_t *stream;
+
+ AudioStreamIn(audio_hw_device_t *dev, audio_stream_in_t *in) :
+ hwDev(dev), stream(in) {}
+ };
+
friend class RecordThread;
friend class PlaybackThread;
-
mutable Mutex mLock;
DefaultKeyedVector< pid_t, wp<Client> > mClients;
mutable Mutex mHardwareLock;
- struct audio_hw_device* mAudioHardwareDev;
- Vector<struct audio_hw_device *> mAudioHwDevs;
+ audio_hw_device_t* mPrimaryHardwareDev;
+ Vector<audio_hw_device_t*> mAudioHwDevs;
mutable int mHardwareStatus;
@@ -1186,6 +1205,7 @@
};
+
// ----------------------------------------------------------------------------
}; // namespace android