Loading services/audioflinger/AudioFlinger.cpp +9 −3 Original line number Diff line number Diff line Loading @@ -1013,6 +1013,14 @@ bool AudioFlinger::streamMute(audio_stream_type_t stream) const return streamMute_l(stream); } void AudioFlinger::broacastParametersToRecordThreads_l(const String8& keyValuePairs) { for (size_t i = 0; i < mRecordThreads.size(); i++) { mRecordThreads.valueAt(i)->setParameters(keyValuePairs); } } status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) { ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d", Loading Loading @@ -1087,9 +1095,7 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& int value; if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) && (value != 0)) { for (size_t i = 0; i < mRecordThreads.size(); i++) { mRecordThreads.valueAt(i)->setParameters(keyValuePairs); } broacastParametersToRecordThreads_l(keyValuePairs); } } } Loading services/audioflinger/AudioFlinger.h +1 −0 Original line number Diff line number Diff line Loading @@ -590,6 +590,7 @@ private: // Return true if the effect was found in mOrphanEffectChains, false otherwise. bool updateOrphanEffectChains(const sp<EffectModule>& effect); void broacastParametersToRecordThreads_l(const String8& keyValuePairs); // AudioStreamIn is immutable, so their fields are const. // For emphasis, we could also make all pointers to them be "const *", Loading services/audioflinger/PatchPanel.cpp +36 −96 Original line number Diff line number Diff line Loading @@ -274,7 +274,6 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa goto exit; } } else { if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { sp<ThreadBase> thread = audioflinger->checkRecordThread_l( patch->sinks[0].ext.mix.handle); Loading @@ -286,6 +285,11 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa } status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); } else { if (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) { status = INVALID_OPERATION; goto exit; } audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); status = hwDevice->create_audio_patch(hwDevice, patch->num_sources, Loading @@ -294,38 +298,6 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa patch->sinks, &halHandle); } } else { if (patch->sinks[0].type != AUDIO_PORT_TYPE_MIX) { status = INVALID_OPERATION; goto exit; } sp<ThreadBase> thread = audioflinger->checkRecordThread_l( patch->sinks[0].ext.mix.handle); if (thread == 0) { ALOGW("createAudioPatch() bad capture I/O handle %d", patch->sinks[0].ext.mix.handle); status = BAD_VALUE; goto exit; } char *address; if (strcmp(patch->sources[0].ext.device.address, "") != 0) { address = audio_device_address_to_parameter( patch->sources[0].ext.device.type, patch->sources[0].ext.device.address); } else { address = (char *)calloc(1, 1); } AudioParameter param = AudioParameter(String8(address)); free(address); param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)patch->sources[0].ext.device.type); param.addInt(String8(AUDIO_PARAMETER_STREAM_INPUT_SOURCE), (int)patch->sinks[0].ext.mix.usecase.source); ALOGV("createAudioPatch() AUDIO_PORT_TYPE_DEVICE setParameters %s", param.toString().string()); status = thread->setParameters(param.toString()); } } } break; case AUDIO_PORT_TYPE_MIX: { Loading @@ -337,6 +309,7 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa goto exit; } // limit to connections between devices and output streams audio_devices_t type = AUDIO_DEVICE_NONE; for (unsigned int i = 0; i < patch->num_sinks; i++) { if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { ALOGW("createAudioPatch() invalid sink type %d for mix source", Loading @@ -349,8 +322,8 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa status = BAD_VALUE; goto exit; } type |= patch->sinks[i].ext.device.type; } AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); sp<ThreadBase> thread = audioflinger->checkPlaybackThread_l(patch->sources[0].ext.mix.handle); if (thread == 0) { Loading @@ -359,28 +332,14 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa status = BAD_VALUE; goto exit; } if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); } else { audio_devices_t type = AUDIO_DEVICE_NONE; for (unsigned int i = 0; i < patch->num_sinks; i++) { type |= patch->sinks[i].ext.device.type; } char *address; if (strcmp(patch->sinks[0].ext.device.address, "") != 0) { //FIXME: we only support address on first sink with HAL version < 3.0 address = audio_device_address_to_parameter( patch->sinks[0].ext.device.type, patch->sinks[0].ext.device.address); } else { address = (char *)calloc(1, 1); } AudioParameter param = AudioParameter(String8(address)); free(address); if (thread == audioflinger->primaryPlaybackThread_l()) { AudioParameter param = AudioParameter(); param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)type); status = thread->setParameters(param.toString()); audioflinger->broacastParametersToRecordThreads_l(param.toString()); } status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); } break; default: status = BAD_VALUE; Loading Loading @@ -581,8 +540,6 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle break; } AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { sp<ThreadBase> thread = audioflinger->checkRecordThread_l( patch->sinks[0].ext.mix.handle); Loading @@ -594,23 +551,13 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle } status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); } else { audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); status = hwDevice->release_audio_patch(hwDevice, removedPatch->mHalHandle); } } else { sp<ThreadBase> thread = audioflinger->checkRecordThread_l( patch->sinks[0].ext.mix.handle); if (thread == 0) { ALOGW("releaseAudioPatch() bad capture I/O handle %d", patch->sinks[0].ext.mix.handle); status = BAD_VALUE; AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); if (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) { status = INVALID_OPERATION; break; } AudioParameter param; param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0); ALOGV("releaseAudioPatch() AUDIO_PORT_TYPE_DEVICE setParameters %s", param.toString().string()); status = thread->setParameters(param.toString()); audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); status = hwDevice->release_audio_patch(hwDevice, removedPatch->mHalHandle); } } break; case AUDIO_PORT_TYPE_MIX: { Loading @@ -629,14 +576,7 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle status = BAD_VALUE; break; } AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); } else { AudioParameter param; param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0); status = thread->setParameters(param.toString()); } } break; default: status = BAD_VALUE; Loading services/audioflinger/Threads.cpp +169 −36 Original line number Diff line number Diff line Loading @@ -2933,21 +2933,78 @@ status_t AudioFlinger::PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp) return INVALID_OPERATION; } status_t AudioFlinger::MixerThread::createAudioPatch_l(const struct audio_patch *patch, audio_patch_handle_t *handle) { // if !&IDLE, holds the FastMixer state to restore after new parameters processed FastMixerState::Command previousCommand = FastMixerState::HOT_IDLE; if (mFastMixer != 0) { FastMixerStateQueue *sq = mFastMixer->sq(); FastMixerState *state = sq->begin(); if (!(state->mCommand & FastMixerState::IDLE)) { previousCommand = state->mCommand; state->mCommand = FastMixerState::HOT_IDLE; sq->end(); sq->push(FastMixerStateQueue::BLOCK_UNTIL_ACKED); } else { sq->end(false /*didModify*/); } } status_t status = PlaybackThread::createAudioPatch_l(patch, handle); if (!(previousCommand & FastMixerState::IDLE)) { ALOG_ASSERT(mFastMixer != 0); FastMixerStateQueue *sq = mFastMixer->sq(); FastMixerState *state = sq->begin(); ALOG_ASSERT(state->mCommand == FastMixerState::HOT_IDLE); state->mCommand = previousCommand; sq->end(); sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED); } return status; } status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_patch *patch, audio_patch_handle_t *handle) { status_t status = NO_ERROR; if (mOutput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) { // store new device and send to effects audio_devices_t type = AUDIO_DEVICE_NONE; for (unsigned int i = 0; i < patch->num_sinks; i++) { type |= patch->sinks[i].ext.device.type; } mOutDevice = type; #ifdef ADD_BATTERY_DATA // when changing the audio output device, call addBatteryData to notify // the change if (mOutDevice != type) { uint32_t params = 0; // check whether speaker is on if (type & AUDIO_DEVICE_OUT_SPEAKER) { params |= IMediaPlayerService::kBatteryDataSpeakerOn; } audio_devices_t deviceWithoutSpeaker = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER; // check if any other device (except speaker) is on if (type & deviceWithoutSpeaker) { params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn; } if (params != 0) { addBatteryData(params); } } #endif for (size_t i = 0; i < mEffectChains.size(); i++) { mEffectChains[i]->setDevice_l(mOutDevice); mEffectChains[i]->setDevice_l(type); } mOutDevice = type; if (mOutput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) { audio_hw_device_t *hwDevice = mOutput->audioHwDev->hwDevice(); status = hwDevice->create_audio_patch(hwDevice, patch->num_sources, Loading @@ -2956,19 +3013,71 @@ status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_pat patch->sinks, handle); } else { ALOG_ASSERT(false, "createAudioPatch_l() called on a pre 3.0 HAL"); char *address; if (strcmp(patch->sinks[0].ext.device.address, "") != 0) { //FIXME: we only support address on first sink with HAL version < 3.0 address = audio_device_address_to_parameter( patch->sinks[0].ext.device.type, patch->sinks[0].ext.device.address); } else { address = (char *)calloc(1, 1); } AudioParameter param = AudioParameter(String8(address)); free(address); param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)type); status = mOutput->stream->common.set_parameters(&mOutput->stream->common, param.toString().string()); *handle = AUDIO_PATCH_HANDLE_NONE; } return status; } status_t AudioFlinger::MixerThread::releaseAudioPatch_l(const audio_patch_handle_t handle) { // if !&IDLE, holds the FastMixer state to restore after new parameters processed FastMixerState::Command previousCommand = FastMixerState::HOT_IDLE; if (mFastMixer != 0) { FastMixerStateQueue *sq = mFastMixer->sq(); FastMixerState *state = sq->begin(); if (!(state->mCommand & FastMixerState::IDLE)) { previousCommand = state->mCommand; state->mCommand = FastMixerState::HOT_IDLE; sq->end(); sq->push(FastMixerStateQueue::BLOCK_UNTIL_ACKED); } else { sq->end(false /*didModify*/); } } status_t status = PlaybackThread::releaseAudioPatch_l(handle); if (!(previousCommand & FastMixerState::IDLE)) { ALOG_ASSERT(mFastMixer != 0); FastMixerStateQueue *sq = mFastMixer->sq(); FastMixerState *state = sq->begin(); ALOG_ASSERT(state->mCommand == FastMixerState::HOT_IDLE); state->mCommand = previousCommand; sq->end(); sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED); } return status; } status_t AudioFlinger::PlaybackThread::releaseAudioPatch_l(const audio_patch_handle_t handle) { status_t status = NO_ERROR; mOutDevice = AUDIO_DEVICE_NONE; if (mOutput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) { audio_hw_device_t *hwDevice = mOutput->audioHwDev->hwDevice(); status = hwDevice->release_audio_patch(hwDevice, handle); } else { ALOG_ASSERT(false, "releaseAudioPatch_l() called on a pre 3.0 HAL"); AudioParameter param; param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0); status = mOutput->stream->common.set_parameters(&mOutput->stream->common, param.toString().string()); } return status; } Loading Loading @@ -6775,7 +6884,7 @@ status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch audio_patch_handle_t *handle) { status_t status = NO_ERROR; if (mInput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) { // store new device and send to effects mInDevice = patch->sources[0].ext.device.type; for (size_t i = 0; i < mEffectChains.size(); i++) { Loading @@ -6802,6 +6911,7 @@ status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch } } if (mInput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) { audio_hw_device_t *hwDevice = mInput->audioHwDev->hwDevice(); status = hwDevice->create_audio_patch(hwDevice, patch->num_sources, Loading @@ -6810,19 +6920,42 @@ status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch patch->sinks, handle); } else { ALOG_ASSERT(false, "createAudioPatch_l() called on a pre 3.0 HAL"); char *address; if (strcmp(patch->sources[0].ext.device.address, "") != 0) { address = audio_device_address_to_parameter( patch->sources[0].ext.device.type, patch->sources[0].ext.device.address); } else { address = (char *)calloc(1, 1); } AudioParameter param = AudioParameter(String8(address)); free(address); param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)patch->sources[0].ext.device.type); param.addInt(String8(AUDIO_PARAMETER_STREAM_INPUT_SOURCE), (int)patch->sinks[0].ext.mix.usecase.source); status = mInput->stream->common.set_parameters(&mInput->stream->common, param.toString().string()); *handle = AUDIO_PATCH_HANDLE_NONE; } return status; } status_t AudioFlinger::RecordThread::releaseAudioPatch_l(const audio_patch_handle_t handle) { status_t status = NO_ERROR; mInDevice = AUDIO_DEVICE_NONE; if (mInput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) { audio_hw_device_t *hwDevice = mInput->audioHwDev->hwDevice(); status = hwDevice->release_audio_patch(hwDevice, handle); } else { ALOG_ASSERT(false, "releaseAudioPatch_l() called on a pre 3.0 HAL"); AudioParameter param; param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0); status = mInput->stream->common.set_parameters(&mInput->stream->common, param.toString().string()); } return status; } Loading services/audioflinger/Threads.h +4 −0 Original line number Diff line number Diff line Loading @@ -865,6 +865,10 @@ protected: virtual void threadLoop_removeTracks(const Vector< sp<Track> >& tracksToRemove); virtual uint32_t correctLatency_l(uint32_t latency) const; virtual status_t createAudioPatch_l(const struct audio_patch *patch, audio_patch_handle_t *handle); virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle); AudioMixer* mAudioMixer; // normal mixer private: // one-time initialization, no locks required Loading Loading
services/audioflinger/AudioFlinger.cpp +9 −3 Original line number Diff line number Diff line Loading @@ -1013,6 +1013,14 @@ bool AudioFlinger::streamMute(audio_stream_type_t stream) const return streamMute_l(stream); } void AudioFlinger::broacastParametersToRecordThreads_l(const String8& keyValuePairs) { for (size_t i = 0; i < mRecordThreads.size(); i++) { mRecordThreads.valueAt(i)->setParameters(keyValuePairs); } } status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) { ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d", Loading Loading @@ -1087,9 +1095,7 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& int value; if ((param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) && (value != 0)) { for (size_t i = 0; i < mRecordThreads.size(); i++) { mRecordThreads.valueAt(i)->setParameters(keyValuePairs); } broacastParametersToRecordThreads_l(keyValuePairs); } } } Loading
services/audioflinger/AudioFlinger.h +1 −0 Original line number Diff line number Diff line Loading @@ -590,6 +590,7 @@ private: // Return true if the effect was found in mOrphanEffectChains, false otherwise. bool updateOrphanEffectChains(const sp<EffectModule>& effect); void broacastParametersToRecordThreads_l(const String8& keyValuePairs); // AudioStreamIn is immutable, so their fields are const. // For emphasis, we could also make all pointers to them be "const *", Loading
services/audioflinger/PatchPanel.cpp +36 −96 Original line number Diff line number Diff line Loading @@ -274,7 +274,6 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa goto exit; } } else { if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { sp<ThreadBase> thread = audioflinger->checkRecordThread_l( patch->sinks[0].ext.mix.handle); Loading @@ -286,6 +285,11 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa } status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); } else { if (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) { status = INVALID_OPERATION; goto exit; } audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); status = hwDevice->create_audio_patch(hwDevice, patch->num_sources, Loading @@ -294,38 +298,6 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa patch->sinks, &halHandle); } } else { if (patch->sinks[0].type != AUDIO_PORT_TYPE_MIX) { status = INVALID_OPERATION; goto exit; } sp<ThreadBase> thread = audioflinger->checkRecordThread_l( patch->sinks[0].ext.mix.handle); if (thread == 0) { ALOGW("createAudioPatch() bad capture I/O handle %d", patch->sinks[0].ext.mix.handle); status = BAD_VALUE; goto exit; } char *address; if (strcmp(patch->sources[0].ext.device.address, "") != 0) { address = audio_device_address_to_parameter( patch->sources[0].ext.device.type, patch->sources[0].ext.device.address); } else { address = (char *)calloc(1, 1); } AudioParameter param = AudioParameter(String8(address)); free(address); param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)patch->sources[0].ext.device.type); param.addInt(String8(AUDIO_PARAMETER_STREAM_INPUT_SOURCE), (int)patch->sinks[0].ext.mix.usecase.source); ALOGV("createAudioPatch() AUDIO_PORT_TYPE_DEVICE setParameters %s", param.toString().string()); status = thread->setParameters(param.toString()); } } } break; case AUDIO_PORT_TYPE_MIX: { Loading @@ -337,6 +309,7 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa goto exit; } // limit to connections between devices and output streams audio_devices_t type = AUDIO_DEVICE_NONE; for (unsigned int i = 0; i < patch->num_sinks; i++) { if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { ALOGW("createAudioPatch() invalid sink type %d for mix source", Loading @@ -349,8 +322,8 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa status = BAD_VALUE; goto exit; } type |= patch->sinks[i].ext.device.type; } AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); sp<ThreadBase> thread = audioflinger->checkPlaybackThread_l(patch->sources[0].ext.mix.handle); if (thread == 0) { Loading @@ -359,28 +332,14 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa status = BAD_VALUE; goto exit; } if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); } else { audio_devices_t type = AUDIO_DEVICE_NONE; for (unsigned int i = 0; i < patch->num_sinks; i++) { type |= patch->sinks[i].ext.device.type; } char *address; if (strcmp(patch->sinks[0].ext.device.address, "") != 0) { //FIXME: we only support address on first sink with HAL version < 3.0 address = audio_device_address_to_parameter( patch->sinks[0].ext.device.type, patch->sinks[0].ext.device.address); } else { address = (char *)calloc(1, 1); } AudioParameter param = AudioParameter(String8(address)); free(address); if (thread == audioflinger->primaryPlaybackThread_l()) { AudioParameter param = AudioParameter(); param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)type); status = thread->setParameters(param.toString()); audioflinger->broacastParametersToRecordThreads_l(param.toString()); } status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); } break; default: status = BAD_VALUE; Loading Loading @@ -581,8 +540,6 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle break; } AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { sp<ThreadBase> thread = audioflinger->checkRecordThread_l( patch->sinks[0].ext.mix.handle); Loading @@ -594,23 +551,13 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle } status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); } else { audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); status = hwDevice->release_audio_patch(hwDevice, removedPatch->mHalHandle); } } else { sp<ThreadBase> thread = audioflinger->checkRecordThread_l( patch->sinks[0].ext.mix.handle); if (thread == 0) { ALOGW("releaseAudioPatch() bad capture I/O handle %d", patch->sinks[0].ext.mix.handle); status = BAD_VALUE; AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); if (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) { status = INVALID_OPERATION; break; } AudioParameter param; param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0); ALOGV("releaseAudioPatch() AUDIO_PORT_TYPE_DEVICE setParameters %s", param.toString().string()); status = thread->setParameters(param.toString()); audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); status = hwDevice->release_audio_patch(hwDevice, removedPatch->mHalHandle); } } break; case AUDIO_PORT_TYPE_MIX: { Loading @@ -629,14 +576,7 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle status = BAD_VALUE; break; } AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); } else { AudioParameter param; param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0); status = thread->setParameters(param.toString()); } } break; default: status = BAD_VALUE; Loading
services/audioflinger/Threads.cpp +169 −36 Original line number Diff line number Diff line Loading @@ -2933,21 +2933,78 @@ status_t AudioFlinger::PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp) return INVALID_OPERATION; } status_t AudioFlinger::MixerThread::createAudioPatch_l(const struct audio_patch *patch, audio_patch_handle_t *handle) { // if !&IDLE, holds the FastMixer state to restore after new parameters processed FastMixerState::Command previousCommand = FastMixerState::HOT_IDLE; if (mFastMixer != 0) { FastMixerStateQueue *sq = mFastMixer->sq(); FastMixerState *state = sq->begin(); if (!(state->mCommand & FastMixerState::IDLE)) { previousCommand = state->mCommand; state->mCommand = FastMixerState::HOT_IDLE; sq->end(); sq->push(FastMixerStateQueue::BLOCK_UNTIL_ACKED); } else { sq->end(false /*didModify*/); } } status_t status = PlaybackThread::createAudioPatch_l(patch, handle); if (!(previousCommand & FastMixerState::IDLE)) { ALOG_ASSERT(mFastMixer != 0); FastMixerStateQueue *sq = mFastMixer->sq(); FastMixerState *state = sq->begin(); ALOG_ASSERT(state->mCommand == FastMixerState::HOT_IDLE); state->mCommand = previousCommand; sq->end(); sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED); } return status; } status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_patch *patch, audio_patch_handle_t *handle) { status_t status = NO_ERROR; if (mOutput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) { // store new device and send to effects audio_devices_t type = AUDIO_DEVICE_NONE; for (unsigned int i = 0; i < patch->num_sinks; i++) { type |= patch->sinks[i].ext.device.type; } mOutDevice = type; #ifdef ADD_BATTERY_DATA // when changing the audio output device, call addBatteryData to notify // the change if (mOutDevice != type) { uint32_t params = 0; // check whether speaker is on if (type & AUDIO_DEVICE_OUT_SPEAKER) { params |= IMediaPlayerService::kBatteryDataSpeakerOn; } audio_devices_t deviceWithoutSpeaker = AUDIO_DEVICE_OUT_ALL & ~AUDIO_DEVICE_OUT_SPEAKER; // check if any other device (except speaker) is on if (type & deviceWithoutSpeaker) { params |= IMediaPlayerService::kBatteryDataOtherAudioDeviceOn; } if (params != 0) { addBatteryData(params); } } #endif for (size_t i = 0; i < mEffectChains.size(); i++) { mEffectChains[i]->setDevice_l(mOutDevice); mEffectChains[i]->setDevice_l(type); } mOutDevice = type; if (mOutput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) { audio_hw_device_t *hwDevice = mOutput->audioHwDev->hwDevice(); status = hwDevice->create_audio_patch(hwDevice, patch->num_sources, Loading @@ -2956,19 +3013,71 @@ status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_pat patch->sinks, handle); } else { ALOG_ASSERT(false, "createAudioPatch_l() called on a pre 3.0 HAL"); char *address; if (strcmp(patch->sinks[0].ext.device.address, "") != 0) { //FIXME: we only support address on first sink with HAL version < 3.0 address = audio_device_address_to_parameter( patch->sinks[0].ext.device.type, patch->sinks[0].ext.device.address); } else { address = (char *)calloc(1, 1); } AudioParameter param = AudioParameter(String8(address)); free(address); param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)type); status = mOutput->stream->common.set_parameters(&mOutput->stream->common, param.toString().string()); *handle = AUDIO_PATCH_HANDLE_NONE; } return status; } status_t AudioFlinger::MixerThread::releaseAudioPatch_l(const audio_patch_handle_t handle) { // if !&IDLE, holds the FastMixer state to restore after new parameters processed FastMixerState::Command previousCommand = FastMixerState::HOT_IDLE; if (mFastMixer != 0) { FastMixerStateQueue *sq = mFastMixer->sq(); FastMixerState *state = sq->begin(); if (!(state->mCommand & FastMixerState::IDLE)) { previousCommand = state->mCommand; state->mCommand = FastMixerState::HOT_IDLE; sq->end(); sq->push(FastMixerStateQueue::BLOCK_UNTIL_ACKED); } else { sq->end(false /*didModify*/); } } status_t status = PlaybackThread::releaseAudioPatch_l(handle); if (!(previousCommand & FastMixerState::IDLE)) { ALOG_ASSERT(mFastMixer != 0); FastMixerStateQueue *sq = mFastMixer->sq(); FastMixerState *state = sq->begin(); ALOG_ASSERT(state->mCommand == FastMixerState::HOT_IDLE); state->mCommand = previousCommand; sq->end(); sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED); } return status; } status_t AudioFlinger::PlaybackThread::releaseAudioPatch_l(const audio_patch_handle_t handle) { status_t status = NO_ERROR; mOutDevice = AUDIO_DEVICE_NONE; if (mOutput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) { audio_hw_device_t *hwDevice = mOutput->audioHwDev->hwDevice(); status = hwDevice->release_audio_patch(hwDevice, handle); } else { ALOG_ASSERT(false, "releaseAudioPatch_l() called on a pre 3.0 HAL"); AudioParameter param; param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0); status = mOutput->stream->common.set_parameters(&mOutput->stream->common, param.toString().string()); } return status; } Loading Loading @@ -6775,7 +6884,7 @@ status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch audio_patch_handle_t *handle) { status_t status = NO_ERROR; if (mInput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) { // store new device and send to effects mInDevice = patch->sources[0].ext.device.type; for (size_t i = 0; i < mEffectChains.size(); i++) { Loading @@ -6802,6 +6911,7 @@ status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch } } if (mInput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) { audio_hw_device_t *hwDevice = mInput->audioHwDev->hwDevice(); status = hwDevice->create_audio_patch(hwDevice, patch->num_sources, Loading @@ -6810,19 +6920,42 @@ status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch patch->sinks, handle); } else { ALOG_ASSERT(false, "createAudioPatch_l() called on a pre 3.0 HAL"); char *address; if (strcmp(patch->sources[0].ext.device.address, "") != 0) { address = audio_device_address_to_parameter( patch->sources[0].ext.device.type, patch->sources[0].ext.device.address); } else { address = (char *)calloc(1, 1); } AudioParameter param = AudioParameter(String8(address)); free(address); param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)patch->sources[0].ext.device.type); param.addInt(String8(AUDIO_PARAMETER_STREAM_INPUT_SOURCE), (int)patch->sinks[0].ext.mix.usecase.source); status = mInput->stream->common.set_parameters(&mInput->stream->common, param.toString().string()); *handle = AUDIO_PATCH_HANDLE_NONE; } return status; } status_t AudioFlinger::RecordThread::releaseAudioPatch_l(const audio_patch_handle_t handle) { status_t status = NO_ERROR; mInDevice = AUDIO_DEVICE_NONE; if (mInput->audioHwDev->version() >= AUDIO_DEVICE_API_VERSION_3_0) { audio_hw_device_t *hwDevice = mInput->audioHwDev->hwDevice(); status = hwDevice->release_audio_patch(hwDevice, handle); } else { ALOG_ASSERT(false, "releaseAudioPatch_l() called on a pre 3.0 HAL"); AudioParameter param; param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0); status = mInput->stream->common.set_parameters(&mInput->stream->common, param.toString().string()); } return status; } Loading
services/audioflinger/Threads.h +4 −0 Original line number Diff line number Diff line Loading @@ -865,6 +865,10 @@ protected: virtual void threadLoop_removeTracks(const Vector< sp<Track> >& tracksToRemove); virtual uint32_t correctLatency_l(uint32_t latency) const; virtual status_t createAudioPatch_l(const struct audio_patch *patch, audio_patch_handle_t *handle); virtual status_t releaseAudioPatch_l(const audio_patch_handle_t handle); AudioMixer* mAudioMixer; // normal mixer private: // one-time initialization, no locks required Loading