diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/libmedia/AudioRecord.cpp | 71 | ||||
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 249 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 61 | ||||
-rw-r--r-- | media/libmedia/IAudioFlingerClient.cpp | 2 |
4 files changed, 320 insertions, 63 deletions
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index a4d6c7d..3868f13 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -114,6 +114,10 @@ AudioRecord::~AudioRecord() mAudioRecordThread->requestExitAndWait(); mAudioRecordThread.clear(); } + // No lock here: worst case we remove a NULL callback which will be a nop + if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { + AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); + } IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); mAudioRecord.clear(); mCblkMemory.clear(); @@ -304,6 +308,8 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession) mNewPosition = mProxy->getPosition() + mUpdatePeriod; int32_t flags = android_atomic_acquire_load(&mCblk->mFlags); + mActive = true; + status_t status = NO_ERROR; if (!(flags & CBLK_INVALID)) { status = mAudioRecord->start(event, triggerSession); @@ -316,9 +322,9 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession) } if (status != NO_ERROR) { + mActive = false; ALOGE("start() status %d", status); } else { - mActive = true; sp<AudioRecordThread> t = mAudioRecordThread; if (t != 0) { t->resume(); @@ -443,6 +449,11 @@ status_t AudioRecord::setInputDevice(audio_port_handle_t deviceId) { AutoMutex lock(mLock); if (mSelectedDeviceId != deviceId) { mSelectedDeviceId = deviceId; + // stop capture so that audio policy manager does not reject the new instance start request + // as only one capture can be active at a time. + if (mAudioRecord != 0 && mActive) { + mAudioRecord->stop(); + } android_atomic_or(CBLK_INVALID, &mCblk->mFlags); } return NO_ERROR; @@ -453,6 +464,14 @@ audio_port_handle_t AudioRecord::getInputDevice() { return mSelectedDeviceId; } +audio_port_handle_t AudioRecord::getRoutedDeviceId() { + AutoMutex lock(mLock); + if (mInput == AUDIO_IO_HANDLE_NONE) { + return AUDIO_PORT_HANDLE_NONE; + } + return AudioSystem::getDeviceIdForIo(mInput); +} + // ------------------------------------------------------------------------- // must be called with mLock held @@ -496,6 +515,10 @@ status_t AudioRecord::openRecord_l(size_t epoch, const String16& opPackageName) } } + if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { + AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); + } + audio_io_handle_t input; status_t status = AudioSystem::getInputForAttr(&mAttributes, &input, (audio_session_t)mSessionId, @@ -628,6 +651,10 @@ status_t AudioRecord::openRecord_l(size_t epoch, const String16& opPackageName) mDeathNotifier = new DeathNotifier(this); IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this); + if (mDeviceCallback != 0) { + AudioSystem::addAudioDeviceCallback(mDeviceCallback, mInput); + } + return NO_ERROR; } @@ -1073,6 +1100,48 @@ status_t AudioRecord::restoreRecord_l(const char *from) return result; } +status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback) +{ + if (callback == 0) { + ALOGW("%s adding NULL callback!", __FUNCTION__); + return BAD_VALUE; + } + AutoMutex lock(mLock); + if (mDeviceCallback == callback) { + ALOGW("%s adding same callback!", __FUNCTION__); + return INVALID_OPERATION; + } + status_t status = NO_ERROR; + if (mInput != AUDIO_IO_HANDLE_NONE) { + if (mDeviceCallback != 0) { + ALOGW("%s callback already present!", __FUNCTION__); + AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); + } + status = AudioSystem::addAudioDeviceCallback(callback, mInput); + } + mDeviceCallback = callback; + return status; +} + +status_t AudioRecord::removeAudioDeviceCallback( + const sp<AudioSystem::AudioDeviceCallback>& callback) +{ + if (callback == 0) { + ALOGW("%s removing NULL callback!", __FUNCTION__); + return BAD_VALUE; + } + AutoMutex lock(mLock); + if (mDeviceCallback != callback) { + ALOGW("%s removing different callback!", __FUNCTION__); + return INVALID_OPERATION; + } + if (mInput != AUDIO_IO_HANDLE_NONE) { + AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); + } + mDeviceCallback = 0; + return NO_ERROR; +} + // ========================================================================= void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused) diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index 85ed2b1..4c2e77b 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -76,6 +76,25 @@ const sp<IAudioFlinger> AudioSystem::get_audio_flinger() return af; } +const sp<AudioSystem::AudioFlingerClient> AudioSystem::getAudioFlingerClient() +{ + // calling get_audio_flinger() will initialize gAudioFlingerClient if needed + const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); + if (af == 0) return 0; + Mutex::Autolock _l(gLock); + return gAudioFlingerClient; +} + +sp<AudioIoDescriptor> AudioSystem::getIoDescriptor(audio_io_handle_t ioHandle) +{ + sp<AudioIoDescriptor> desc; + const sp<AudioFlingerClient> afc = getAudioFlingerClient(); + if (afc != 0) { + desc = afc->getIoDescriptor(ioHandle); + } + return desc; +} + /* static */ status_t AudioSystem::checkAudioFlinger() { if (defaultServiceManager()->checkService(String16("media.audio_flinger")) != 0) { @@ -249,9 +268,7 @@ status_t AudioSystem::getSamplingRate(audio_io_handle_t output, { const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; - - LOG_ALWAYS_FATAL_IF(gAudioFlingerClient == 0); - sp<AudioIoDescriptor> outputDesc = gAudioFlingerClient->getIoDescriptor(output); + sp<AudioIoDescriptor> outputDesc = getIoDescriptor(output); if (outputDesc == 0) { ALOGV("getOutputSamplingRate() no output descriptor for output %d in gOutputs", output); *samplingRate = af->sampleRate(output); @@ -290,9 +307,7 @@ status_t AudioSystem::getFrameCount(audio_io_handle_t output, { const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; - - LOG_ALWAYS_FATAL_IF(gAudioFlingerClient == 0); - sp<AudioIoDescriptor> outputDesc = gAudioFlingerClient->getIoDescriptor(output); + sp<AudioIoDescriptor> outputDesc = getIoDescriptor(output); if (outputDesc == 0) { *frameCount = af->frameCount(output); } else { @@ -329,9 +344,7 @@ status_t AudioSystem::getLatency(audio_io_handle_t output, { const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af == 0) return PERMISSION_DENIED; - - LOG_ALWAYS_FATAL_IF(gAudioFlingerClient == 0); - sp<AudioIoDescriptor> outputDesc = gAudioFlingerClient->getIoDescriptor(output); + sp<AudioIoDescriptor> outputDesc = getIoDescriptor(output); if (outputDesc == 0) { *latency = af->latency(output); } else { @@ -346,10 +359,11 @@ status_t AudioSystem::getLatency(audio_io_handle_t output, status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, size_t* buffSize) { - const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); - if (af == 0) return PERMISSION_DENIED; - LOG_ALWAYS_FATAL_IF(gAudioFlingerClient == 0); - return gAudioFlingerClient->getInputBufferSize(sampleRate, format, channelMask, buffSize); + const sp<AudioFlingerClient> afc = getAudioFlingerClient(); + if (afc == 0) { + return NO_INIT; + } + return afc->getInputBufferSize(sampleRate, format, channelMask, buffSize); } status_t AudioSystem::setVoiceVolume(float value) @@ -446,47 +460,77 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return; - Mutex::Autolock _l(mLock); + audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE; + Vector < sp<AudioDeviceCallback> > callbacks; - switch (event) { - case AUDIO_OUTPUT_OPENED: - case AUDIO_INPUT_OPENED: { - if (getIoDescriptor(ioDesc->mIoHandle) != 0) { - ALOGV("ioConfigChanged() opening already existing output! %d", ioDesc->mIoHandle); - break; - } - mIoDescriptors.add(ioDesc->mIoHandle, ioDesc); - ALOGV("ioConfigChanged() new %s opened %d samplingRate %u, format %#x channel mask %#x " - "frameCount %zu", event == AUDIO_OUTPUT_OPENED ? "output" : "input", - ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat, ioDesc->mChannelMask, - ioDesc->mFrameCount); - } break; - case AUDIO_OUTPUT_CLOSED: - case AUDIO_INPUT_CLOSED: { - if (getIoDescriptor(ioDesc->mIoHandle) == 0) { - ALOGW("ioConfigChanged() closing unknown %s %d", + { + Mutex::Autolock _l(mLock); + + switch (event) { + case AUDIO_OUTPUT_OPENED: + case AUDIO_INPUT_OPENED: { + if (getIoDescriptor(ioDesc->mIoHandle) != 0) { + ALOGV("ioConfigChanged() opening already existing output! %d", ioDesc->mIoHandle); + break; + } + mIoDescriptors.add(ioDesc->mIoHandle, ioDesc); + + if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) { + deviceId = ioDesc->getDeviceId(); + ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle); + if (ioIndex >= 0) { + callbacks = mAudioDeviceCallbacks.valueAt(ioIndex); + } + } + ALOGV("ioConfigChanged() new %s opened %d samplingRate %u, format %#x channel mask %#x " + "frameCount %zu deviceId %d", event == AUDIO_OUTPUT_OPENED ? "output" : "input", + ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat, ioDesc->mChannelMask, + ioDesc->mFrameCount, ioDesc->getDeviceId()); + } break; + case AUDIO_OUTPUT_CLOSED: + case AUDIO_INPUT_CLOSED: { + if (getIoDescriptor(ioDesc->mIoHandle) == 0) { + ALOGW("ioConfigChanged() closing unknown %s %d", + event == AUDIO_OUTPUT_CLOSED ? "output" : "input", ioDesc->mIoHandle); + break; + } + ALOGV("ioConfigChanged() %s %d closed", event == AUDIO_OUTPUT_CLOSED ? "output" : "input", ioDesc->mIoHandle); - break; - } - ALOGV("ioConfigChanged() %s %d closed", event == AUDIO_OUTPUT_CLOSED ? "output" : "input", - ioDesc->mIoHandle); - mIoDescriptors.removeItem(ioDesc->mIoHandle); - } break; + mIoDescriptors.removeItem(ioDesc->mIoHandle); + mAudioDeviceCallbacks.removeItem(ioDesc->mIoHandle); + } break; - case AUDIO_OUTPUT_CONFIG_CHANGED: - case AUDIO_INPUT_CONFIG_CHANGED: { - if (getIoDescriptor(ioDesc->mIoHandle) == 0) { - ALOGW("ioConfigChanged() modifying unknown output! %d", ioDesc->mIoHandle); - break; + case AUDIO_OUTPUT_CONFIG_CHANGED: + case AUDIO_INPUT_CONFIG_CHANGED: { + sp<AudioIoDescriptor> oldDesc = getIoDescriptor(ioDesc->mIoHandle); + if (oldDesc == 0) { + ALOGW("ioConfigChanged() modifying unknown output! %d", ioDesc->mIoHandle); + break; + } + + deviceId = oldDesc->getDeviceId(); + mIoDescriptors.replaceValueFor(ioDesc->mIoHandle, ioDesc); + + if (deviceId != ioDesc->getDeviceId()) { + deviceId = ioDesc->getDeviceId(); + ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(ioDesc->mIoHandle); + if (ioIndex >= 0) { + callbacks = mAudioDeviceCallbacks.valueAt(ioIndex); + } + } + ALOGV("ioConfigChanged() new config for %s %d samplingRate %u, format %#x " + "channel mask %#x frameCount %zu deviceId %d", + event == AUDIO_OUTPUT_CONFIG_CHANGED ? "output" : "input", + ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat, + ioDesc->mChannelMask, ioDesc->mFrameCount, ioDesc->getDeviceId()); + + } break; } - mIoDescriptors.replaceValueFor(ioDesc->mIoHandle, ioDesc); - ALOGV("ioConfigChanged() new config for %s %d samplingRate %u, format %#x " - "channel mask %#x frameCount %zu", - event == AUDIO_OUTPUT_CONFIG_CHANGED ? "output" : "input", - ioDesc->mIoHandle, ioDesc->mSamplingRate, ioDesc->mFormat, - ioDesc->mChannelMask, ioDesc->mFrameCount); - } break; + } + // callbacks.size() != 0 => ioDesc->mIoHandle and deviceId are valid + for (size_t i = 0; i < callbacks.size(); i++) { + callbacks[i]->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId); } } @@ -532,7 +576,56 @@ sp<AudioIoDescriptor> AudioSystem::AudioFlingerClient::getIoDescriptor(audio_io_ return desc; } -/*static*/ void AudioSystem::setErrorCallback(audio_error_callback cb) +status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback( + const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) +{ + Mutex::Autolock _l(mLock); + Vector < sp<AudioDeviceCallback> > callbacks; + ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo); + if (ioIndex >= 0) { + callbacks = mAudioDeviceCallbacks.valueAt(ioIndex); + } + + for (size_t cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) { + if (callbacks[cbIndex] == callback) { + return INVALID_OPERATION; + } + } + callbacks.add(callback); + + mAudioDeviceCallbacks.replaceValueFor(audioIo, callbacks); + return NO_ERROR; +} + +status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback( + const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) +{ + Mutex::Autolock _l(mLock); + ssize_t ioIndex = mAudioDeviceCallbacks.indexOfKey(audioIo); + if (ioIndex < 0) { + return INVALID_OPERATION; + } + Vector < sp<AudioDeviceCallback> > callbacks = mAudioDeviceCallbacks.valueAt(ioIndex); + + size_t cbIndex; + for (cbIndex = 0; cbIndex < callbacks.size(); cbIndex++) { + if (callbacks[cbIndex] == callback) { + break; + } + } + if (cbIndex == callbacks.size()) { + return INVALID_OPERATION; + } + callbacks.removeAt(cbIndex); + if (callbacks.size() != 0) { + mAudioDeviceCallbacks.replaceValueFor(audioIo, callbacks); + } else { + mAudioDeviceCallbacks.removeItem(audioIo); + } + return NO_ERROR; +} + +/* static */ void AudioSystem::setErrorCallback(audio_error_callback cb) { Mutex::Autolock _l(gLock); gAudioErrorCallback = cb; @@ -864,11 +957,11 @@ void AudioSystem::clearAudioConfigCache() { // called by restoreTrack_l(), which needs new IAudioFlinger and IAudioPolicyService instances ALOGV("clearAudioConfigCache()"); - if (gAudioFlingerClient != 0) { - gAudioFlingerClient->clearIoCache(); - } { Mutex::Autolock _l(gLock); + if (gAudioFlingerClient != 0) { + gAudioFlingerClient->clearIoCache(); + } gAudioFlinger.clear(); } { @@ -934,7 +1027,7 @@ status_t AudioSystem::setAudioPortConfig(const struct audio_port_config *config) return aps->setAudioPortConfig(config); } -status_t AudioSystem::addAudioPortCallback(const sp<AudioPortCallback>& callBack) +status_t AudioSystem::addAudioPortCallback(const sp<AudioPortCallback>& callback) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; @@ -943,11 +1036,11 @@ status_t AudioSystem::addAudioPortCallback(const sp<AudioPortCallback>& callBack if (gAudioPolicyServiceClient == 0) { return NO_INIT; } - return gAudioPolicyServiceClient->addAudioPortCallback(callBack); + return gAudioPolicyServiceClient->addAudioPortCallback(callback); } /*static*/ -status_t AudioSystem::removeAudioPortCallback(const sp<AudioPortCallback>& callBack) +status_t AudioSystem::removeAudioPortCallback(const sp<AudioPortCallback>& callback) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return PERMISSION_DENIED; @@ -956,7 +1049,38 @@ status_t AudioSystem::removeAudioPortCallback(const sp<AudioPortCallback>& callB if (gAudioPolicyServiceClient == 0) { return NO_INIT; } - return gAudioPolicyServiceClient->removeAudioPortCallback(callBack); + return gAudioPolicyServiceClient->removeAudioPortCallback(callback); +} + +status_t AudioSystem::addAudioDeviceCallback( + const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) +{ + const sp<AudioFlingerClient> afc = getAudioFlingerClient(); + if (afc == 0) { + return NO_INIT; + } + return afc->addAudioDeviceCallback(callback, audioIo); +} + +status_t AudioSystem::removeAudioDeviceCallback( + const sp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) +{ + const sp<AudioFlingerClient> afc = getAudioFlingerClient(); + if (afc == 0) { + return NO_INIT; + } + return afc->removeAudioDeviceCallback(callback, audioIo); +} + +audio_port_handle_t AudioSystem::getDeviceIdForIo(audio_io_handle_t audioIo) +{ + const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); + if (af == 0) return PERMISSION_DENIED; + const sp<AudioIoDescriptor> desc = getIoDescriptor(audioIo); + if (desc == 0) { + return AUDIO_PORT_HANDLE_NONE; + } + return desc->getDeviceId(); } status_t AudioSystem::acquireSoundTriggerSession(audio_session_t *session, @@ -1008,25 +1132,25 @@ status_t AudioSystem::stopAudioSource(audio_io_handle_t handle) // --------------------------------------------------------------------------- status_t AudioSystem::AudioPolicyServiceClient::addAudioPortCallback( - const sp<AudioPortCallback>& callBack) + const sp<AudioPortCallback>& callback) { Mutex::Autolock _l(mLock); for (size_t i = 0; i < mAudioPortCallbacks.size(); i++) { - if (mAudioPortCallbacks[i] == callBack) { + if (mAudioPortCallbacks[i] == callback) { return INVALID_OPERATION; } } - mAudioPortCallbacks.add(callBack); + mAudioPortCallbacks.add(callback); return NO_ERROR; } status_t AudioSystem::AudioPolicyServiceClient::removeAudioPortCallback( - const sp<AudioPortCallback>& callBack) + const sp<AudioPortCallback>& callback) { Mutex::Autolock _l(mLock); size_t i; for (i = 0; i < mAudioPortCallbacks.size(); i++) { - if (mAudioPortCallbacks[i] == callBack) { + if (mAudioPortCallbacks[i] == callback) { break; } } @@ -1037,6 +1161,7 @@ status_t AudioSystem::AudioPolicyServiceClient::removeAudioPortCallback( return NO_ERROR; } + void AudioSystem::AudioPolicyServiceClient::onAudioPortListUpdate() { Mutex::Autolock _l(mLock); diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index bb47d3e..db316b0 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -234,6 +234,10 @@ AudioTrack::~AudioTrack() mAudioTrackThread->requestExitAndWait(); mAudioTrackThread.clear(); } + // No lock here: worst case we remove a NULL callback which will be a nop + if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) { + AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput); + } IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this); mAudioTrack.clear(); mCblkMemory.clear(); @@ -1042,6 +1046,14 @@ audio_port_handle_t AudioTrack::getOutputDevice() { return mSelectedDeviceId; } +audio_port_handle_t AudioTrack::getRoutedDeviceId() { + AutoMutex lock(mLock); + if (mOutput == AUDIO_IO_HANDLE_NONE) { + return AUDIO_PORT_HANDLE_NONE; + } + return AudioSystem::getDeviceIdForIo(mOutput); +} + status_t AudioTrack::attachAuxEffect(int effectId) { AutoMutex lock(mLock); @@ -1071,6 +1083,9 @@ status_t AudioTrack::createTrack_l() return NO_INIT; } + if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) { + AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput); + } audio_io_handle_t output; audio_stream_type_t streamType = mStreamType; audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL; @@ -1375,6 +1390,10 @@ status_t AudioTrack::createTrack_l() mDeathNotifier = new DeathNotifier(this); IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this); + if (mDeviceCallback != 0) { + AudioSystem::addAudioDeviceCallback(mDeviceCallback, mOutput); + } + return NO_ERROR; } @@ -2308,6 +2327,48 @@ uint32_t AudioTrack::getUnderrunFrames() const return mProxy->getUnderrunFrames(); } +status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback) +{ + if (callback == 0) { + ALOGW("%s adding NULL callback!", __FUNCTION__); + return BAD_VALUE; + } + AutoMutex lock(mLock); + if (mDeviceCallback == callback) { + ALOGW("%s adding same callback!", __FUNCTION__); + return INVALID_OPERATION; + } + status_t status = NO_ERROR; + if (mOutput != AUDIO_IO_HANDLE_NONE) { + if (mDeviceCallback != 0) { + ALOGW("%s callback already present!", __FUNCTION__); + AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput); + } + status = AudioSystem::addAudioDeviceCallback(callback, mOutput); + } + mDeviceCallback = callback; + return status; +} + +status_t AudioTrack::removeAudioDeviceCallback( + const sp<AudioSystem::AudioDeviceCallback>& callback) +{ + if (callback == 0) { + ALOGW("%s removing NULL callback!", __FUNCTION__); + return BAD_VALUE; + } + AutoMutex lock(mLock); + if (mDeviceCallback != callback) { + ALOGW("%s removing different callback!", __FUNCTION__); + return INVALID_OPERATION; + } + if (mOutput != AUDIO_IO_HANDLE_NONE) { + AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput); + } + mDeviceCallback = 0; + return NO_ERROR; +} + // ========================================================================= void AudioTrack::DeathNotifier::binderDied(const wp<IBinder>& who __unused) diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp index a622241..3429d36 100644 --- a/media/libmedia/IAudioFlingerClient.cpp +++ b/media/libmedia/IAudioFlingerClient.cpp @@ -45,6 +45,7 @@ public: data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor()); data.writeInt32(event); data.writeInt32((int32_t)ioDesc->mIoHandle); + data.write(&ioDesc->mPatch, sizeof(struct audio_patch)); data.writeInt32(ioDesc->mSamplingRate); data.writeInt32(ioDesc->mFormat); data.writeInt32(ioDesc->mChannelMask); @@ -67,6 +68,7 @@ status_t BnAudioFlingerClient::onTransact( audio_io_config_event event = (audio_io_config_event)data.readInt32(); sp<AudioIoDescriptor> ioDesc = new AudioIoDescriptor(); ioDesc->mIoHandle = (audio_io_handle_t) data.readInt32(); + data.read(&ioDesc->mPatch, sizeof(struct audio_patch)); ioDesc->mSamplingRate = data.readInt32(); ioDesc->mFormat = (audio_format_t) data.readInt32(); ioDesc->mChannelMask = (audio_channel_mask_t) data.readInt32(); |