Loading media/libaudioclient/AudioRecord.cpp +10 −10 Original line number Diff line number Diff line Loading @@ -177,7 +177,7 @@ AudioRecord::~AudioRecord() } // 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(this, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId); } IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); mAudioRecord.clear(); Loading Loading @@ -790,14 +790,13 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String mAudioRecord = record; mCblkMemory = output.cblk; mBufferMemory = output.buffers; mPortId = output.portId; IPCThreadState::self()->flushCommands(); mCblk = cblk; // note that output.frameCount is the (possibly revised) value of mReqFrameCount if (output.frameCount < mReqFrameCount || (mReqFrameCount == 0 && output.frameCount == 0)) { ALOGW("%s(%d): Requested frameCount %zu but received frameCount %zu", __func__, mPortId, __func__, output.portId, mReqFrameCount, output.frameCount); } Loading @@ -805,19 +804,20 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String // The computation is done on server side. if (mNotificationFramesReq > 0 && output.notificationFrameCount != mNotificationFramesReq) { ALOGW("%s(%d): Server adjusted notificationFrames from %u to %zu for frameCount %zu", __func__, mPortId, __func__, output.portId, mNotificationFramesReq, output.notificationFrameCount, output.frameCount); } mNotificationFramesAct = (uint32_t)output.notificationFrameCount; //mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation if (mDeviceCallback != 0 && mInput != output.inputId) { if (mDeviceCallback != 0) { if (mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId); } AudioSystem::addAudioDeviceCallback(this, output.inputId); AudioSystem::addAudioDeviceCallback(this, output.inputId, output.portId); } mPortId = output.portId; // We retain a copy of the I/O handle, but don't own the reference mInput = output.inputId; mRefreshRemaining = true; Loading Loading @@ -1332,9 +1332,9 @@ status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCa if (mInput != AUDIO_IO_HANDLE_NONE) { if (mDeviceCallback != 0) { ALOGW("%s(%d): callback already present!", __func__, mPortId); AudioSystem::removeAudioDeviceCallback(this, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId); } status = AudioSystem::addAudioDeviceCallback(this, mInput); status = AudioSystem::addAudioDeviceCallback(this, mInput, mPortId); } mDeviceCallback = callback; return status; Loading @@ -1354,7 +1354,7 @@ status_t AudioRecord::removeAudioDeviceCallback( } mDeviceCallback.clear(); if (mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId); } return NO_ERROR; } Loading media/libaudioclient/AudioSystem.cpp +57 −74 Original line number Diff line number Diff line Loading @@ -523,12 +523,10 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return; audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE; Vector<sp<AudioDeviceCallback>> callbacksToCall; std::vector<sp<AudioDeviceCallback>> callbacksToCall; { Mutex::Autolock _l(mLock); bool deviceValidOrChanged = false; bool sendCallbacks = false; ssize_t ioIndex = -1; auto callbacks = std::map<audio_port_handle_t, wp<AudioDeviceCallback>>(); switch (event) { case AUDIO_OUTPUT_OPENED: Loading @@ -546,17 +544,11 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) { deviceId = ioDesc->getDeviceId(); if (event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED) { ioIndex = mAudioDeviceCallbackProxies.indexOfKey(ioDesc->mIoHandle); if (ioIndex >= 0) { sendCallbacks = true; deviceValidOrChanged = true; auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle); if (it != mAudioDeviceCallbacks.end()) { callbacks = it->second; } } if (event == AUDIO_OUTPUT_REGISTERED || event == AUDIO_INPUT_REGISTERED) { ioIndex = mAudioDeviceCallbackProxies.indexOfKey(ioDesc->mIoHandle); sendCallbacks = (ioIndex >= 0) && !mAudioDeviceCallbackProxies.valueAt(ioIndex).notifiedOnce(); } } ALOGV("ioConfigChanged() new %s %s %d samplingRate %u, format %#x channel mask %#x " "frameCount %zu deviceId %d", Loading @@ -578,7 +570,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even event == AUDIO_OUTPUT_CLOSED ? "output" : "input", ioDesc->mIoHandle); mIoDescriptors.removeItem(ioDesc->mIoHandle); mAudioDeviceCallbackProxies.removeItem(ioDesc->mIoHandle); mAudioDeviceCallbacks.erase(ioDesc->mIoHandle); } break; case AUDIO_OUTPUT_CONFIG_CHANGED: Loading @@ -593,10 +585,11 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even mIoDescriptors.replaceValueFor(ioDesc->mIoHandle, ioDesc); if (deviceId != ioDesc->getDeviceId()) { deviceValidOrChanged = true; deviceId = ioDesc->getDeviceId(); ioIndex = mAudioDeviceCallbackProxies.indexOfKey(ioDesc->mIoHandle); sendCallbacks = ioIndex >= 0; auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle); if (it != mAudioDeviceCallbacks.end()) { callbacks = it->second; } } ALOGV("ioConfigChanged() new config for %s %d samplingRate %u, format %#x " "channel mask %#x frameCount %zu frameCountHAL %zu deviceId %d", Loading @@ -606,35 +599,40 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even ioDesc->getDeviceId()); } break; case AUDIO_CLIENT_STARTED: { sp<AudioIoDescriptor> oldDesc = getIoDescriptor_l(ioDesc->mIoHandle); if (oldDesc == 0) { ALOGW("ioConfigChanged() start client on unknown io! %d", ioDesc->mIoHandle); break; } // sendCallbacks true => ioDesc->mIoHandle and deviceId are valid if (sendCallbacks) { AudioDeviceCallbackProxies &callbackProxies = mAudioDeviceCallbackProxies.editValueAt(ioIndex); for (size_t i = 0; i < callbackProxies.size(); ) { sp<AudioDeviceCallback> callback = callbackProxies[i]->callback(); if (callback.get() != nullptr) { // Call the callback only if the device actually changed, the input or output // was opened or closed or the client was newly registered and the callback // was never called if (!callbackProxies[i]->notifiedOnce() || deviceValidOrChanged) { callbacksToCall.add(callback); callbackProxies[i]->setNotifiedOnce(); } i++; } else { callbackProxies.removeAt(i); ALOGV("ioConfigChanged() AUDIO_CLIENT_STARTED io %d port %d num callbacks %zu", ioDesc->mIoHandle, ioDesc->mPortId, mAudioDeviceCallbacks.size()); oldDesc->mPatch = ioDesc->mPatch; auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle); if (it != mAudioDeviceCallbacks.end()) { auto cbks = it->second; auto it2 = cbks.find(ioDesc->mPortId); if (it2 != cbks.end()) { callbacks.emplace(ioDesc->mPortId, it2->second); deviceId = oldDesc->getDeviceId(); } } callbackProxies.setNotifiedOnce(); } break; } for (auto wpCbk : callbacks) { sp<AudioDeviceCallback> spCbk = wpCbk.second.promote(); if (spCbk != nullptr) { callbacksToCall.push_back(spCbk); } } } // Callbacks must be called without mLock held. May lead to dead lock if calling for // example getRoutedDevice that updates the device and tries to acquire mLock. for (size_t i = 0; i < callbacksToCall.size(); i++) { callbacksToCall[i]->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId); for (auto cb : callbacksToCall) { // If callbacksToCall is not empty, it implies ioDesc->mIoHandle and deviceId are valid cb->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId); } } Loading Loading @@ -687,51 +685,34 @@ sp<AudioIoDescriptor> AudioSystem::AudioFlingerClient::getIoDescriptor(audio_io_ } status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback( const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo, audio_port_handle_t portId) { ALOGV("%s audioIo %d portId %d", __func__, audioIo, portId); Mutex::Autolock _l(mLock); AudioDeviceCallbackProxies callbackProxies; ssize_t ioIndex = mAudioDeviceCallbackProxies.indexOfKey(audioIo); if (ioIndex >= 0) { callbackProxies = mAudioDeviceCallbackProxies.valueAt(ioIndex); } for (size_t cbIndex = 0; cbIndex < callbackProxies.size(); cbIndex++) { sp<AudioDeviceCallback> cbk = callbackProxies[cbIndex]->callback(); if (cbk.get() == callback.unsafe_get()) { auto& callbacks = mAudioDeviceCallbacks.emplace(audioIo, std::map<audio_port_handle_t, wp<AudioDeviceCallback>>()).first->second; auto result = callbacks.try_emplace(portId, callback); if (!result.second) { return INVALID_OPERATION; } } callbackProxies.add(new AudioDeviceCallbackProxy(callback)); callbackProxies.resetNotifiedOnce(); mAudioDeviceCallbackProxies.replaceValueFor(audioIo, callbackProxies); return NO_ERROR; } status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback( const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback __unused, audio_io_handle_t audioIo, audio_port_handle_t portId) { ALOGV("%s audioIo %d portId %d", __func__, audioIo, portId); Mutex::Autolock _l(mLock); ssize_t ioIndex = mAudioDeviceCallbackProxies.indexOfKey(audioIo); if (ioIndex < 0) { auto it = mAudioDeviceCallbacks.find(audioIo); if (it == mAudioDeviceCallbacks.end()) { return INVALID_OPERATION; } AudioDeviceCallbackProxies callbackProxies = mAudioDeviceCallbackProxies.valueAt(ioIndex); size_t cbIndex; for (cbIndex = 0; cbIndex < callbackProxies.size(); cbIndex++) { sp<AudioDeviceCallback> cbk = callbackProxies[cbIndex]->callback(); if (cbk.get() == callback.unsafe_get()) { break; } } if (cbIndex == callbackProxies.size()) { if (it->second.erase(portId) == 0) { return INVALID_OPERATION; } callbackProxies.removeAt(cbIndex); if (callbackProxies.size() != 0) { mAudioDeviceCallbackProxies.replaceValueFor(audioIo, callbackProxies); } else { mAudioDeviceCallbackProxies.removeItem(audioIo); if (it->second.size() == 0) { mAudioDeviceCallbacks.erase(audioIo); } return NO_ERROR; } Loading Loading @@ -1271,13 +1252,14 @@ status_t AudioSystem::removeAudioVolumeGroupCallback(const sp<AudioVolumeGroupCa } status_t AudioSystem::addAudioDeviceCallback( const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo, audio_port_handle_t portId) { const sp<AudioFlingerClient> afc = getAudioFlingerClient(); if (afc == 0) { return NO_INIT; } status_t status = afc->addAudioDeviceCallback(callback, audioIo); status_t status = afc->addAudioDeviceCallback(callback, audioIo, portId); if (status == NO_ERROR) { const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af != 0) { Loading @@ -1288,13 +1270,14 @@ status_t AudioSystem::addAudioDeviceCallback( } status_t AudioSystem::removeAudioDeviceCallback( const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo, audio_port_handle_t portId) { const sp<AudioFlingerClient> afc = getAudioFlingerClient(); if (afc == 0) { return NO_INIT; } return afc->removeAudioDeviceCallback(callback, audioIo); return afc->removeAudioDeviceCallback(callback, audioIo, portId); } audio_port_handle_t AudioSystem::getDeviceIdForIo(audio_io_handle_t audioIo) Loading media/libaudioclient/AudioTrack.cpp +11 −9 Original line number Diff line number Diff line Loading @@ -309,7 +309,7 @@ AudioTrack::~AudioTrack() } // 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(this, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId); } IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this); mAudioTrack.clear(); Loading Loading @@ -1495,7 +1495,6 @@ status_t AudioTrack::createTrack_l() mAfFrameCount = output.afFrameCount; mAfSampleRate = output.afSampleRate; mAfLatency = output.afLatencyMs; mPortId = output.portId; mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate; Loading Loading @@ -1543,14 +1542,15 @@ status_t AudioTrack::createTrack_l() mFlags = output.flags; //mOutput != output includes the case where mOutput == AUDIO_IO_HANDLE_NONE for first creation if (mDeviceCallback != 0 && mOutput != output.outputId) { if (mDeviceCallback != 0) { if (mOutput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId); } AudioSystem::addAudioDeviceCallback(this, output.outputId); AudioSystem::addAudioDeviceCallback(this, output.outputId, output.portId); callbackAdded = true; } mPortId = output.portId; // We retain a copy of the I/O handle, but don't own the reference mOutput = output.outputId; mRefreshRemaining = true; Loading Loading @@ -1615,7 +1615,7 @@ status_t AudioTrack::createTrack_l() exit: if (status != NO_ERROR && callbackAdded) { // note: mOutput is always valid is callbackAdded is true AudioSystem::removeAudioDeviceCallback(this, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId); } mStatus = status; Loading Loading @@ -2922,6 +2922,7 @@ uint32_t AudioTrack::getUnderrunFrames() const status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback) { if (callback == 0) { ALOGW("%s(%d): adding NULL callback!", __func__, mPortId); return BAD_VALUE; Loading @@ -2935,9 +2936,9 @@ status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCal if (mOutput != AUDIO_IO_HANDLE_NONE) { if (mDeviceCallback != 0) { ALOGW("%s(%d): callback already present!", __func__, mPortId); AudioSystem::removeAudioDeviceCallback(this, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId); } status = AudioSystem::addAudioDeviceCallback(this, mOutput); status = AudioSystem::addAudioDeviceCallback(this, mOutput, mPortId); } mDeviceCallback = callback; return status; Loading @@ -2957,7 +2958,7 @@ status_t AudioTrack::removeAudioDeviceCallback( } mDeviceCallback.clear(); if (mOutput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId); } return NO_ERROR; } Loading @@ -2979,6 +2980,7 @@ void AudioTrack::onAudioDeviceUpdate(audio_io_handle_t audioIo, mRoutedDeviceId = deviceId; } } if (callback.get() != nullptr) { callback->onAudioDeviceUpdate(mOutput, mRoutedDeviceId); } Loading media/libaudioclient/IAudioFlingerClient.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ public: data.writeInt64(ioDesc->mFrameCount); data.writeInt64(ioDesc->mFrameCountHAL); data.writeInt32(ioDesc->mLatency); data.writeInt32(ioDesc->mPortId); remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); } }; Loading @@ -76,6 +77,7 @@ status_t BnAudioFlingerClient::onTransact( ioDesc->mFrameCount = data.readInt64(); ioDesc->mFrameCountHAL = data.readInt64(); ioDesc->mLatency = data.readInt32(); ioDesc->mPortId = data.readInt32(); ioConfigChanged(event, ioDesc); return NO_ERROR; } break; Loading media/libaudioclient/include/media/AudioIoDescriptor.h +3 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ enum audio_io_config_event { AUDIO_INPUT_OPENED, AUDIO_INPUT_CLOSED, AUDIO_INPUT_CONFIG_CHANGED, AUDIO_CLIENT_STARTED, }; // audio input/output descriptor used to cache output configurations in client process to avoid Loading @@ -37,7 +38,7 @@ public: AudioIoDescriptor() : mIoHandle(AUDIO_IO_HANDLE_NONE), mSamplingRate(0), mFormat(AUDIO_FORMAT_DEFAULT), mChannelMask(AUDIO_CHANNEL_NONE), mFrameCount(0), mFrameCountHAL(0), mLatency(0) mFrameCount(0), mFrameCountHAL(0), mLatency(0), mPortId(AUDIO_PORT_HANDLE_NONE) { memset(&mPatch, 0, sizeof(struct audio_patch)); } Loading Loading @@ -66,6 +67,7 @@ public: size_t mFrameCount; size_t mFrameCountHAL; uint32_t mLatency; // only valid for output audio_port_handle_t mPortId; // valid for event AUDIO_CLIENT_STARTED }; Loading Loading
media/libaudioclient/AudioRecord.cpp +10 −10 Original line number Diff line number Diff line Loading @@ -177,7 +177,7 @@ AudioRecord::~AudioRecord() } // 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(this, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId); } IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); mAudioRecord.clear(); Loading Loading @@ -790,14 +790,13 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String mAudioRecord = record; mCblkMemory = output.cblk; mBufferMemory = output.buffers; mPortId = output.portId; IPCThreadState::self()->flushCommands(); mCblk = cblk; // note that output.frameCount is the (possibly revised) value of mReqFrameCount if (output.frameCount < mReqFrameCount || (mReqFrameCount == 0 && output.frameCount == 0)) { ALOGW("%s(%d): Requested frameCount %zu but received frameCount %zu", __func__, mPortId, __func__, output.portId, mReqFrameCount, output.frameCount); } Loading @@ -805,19 +804,20 @@ status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String // The computation is done on server side. if (mNotificationFramesReq > 0 && output.notificationFrameCount != mNotificationFramesReq) { ALOGW("%s(%d): Server adjusted notificationFrames from %u to %zu for frameCount %zu", __func__, mPortId, __func__, output.portId, mNotificationFramesReq, output.notificationFrameCount, output.frameCount); } mNotificationFramesAct = (uint32_t)output.notificationFrameCount; //mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation if (mDeviceCallback != 0 && mInput != output.inputId) { if (mDeviceCallback != 0) { if (mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId); } AudioSystem::addAudioDeviceCallback(this, output.inputId); AudioSystem::addAudioDeviceCallback(this, output.inputId, output.portId); } mPortId = output.portId; // We retain a copy of the I/O handle, but don't own the reference mInput = output.inputId; mRefreshRemaining = true; Loading Loading @@ -1332,9 +1332,9 @@ status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCa if (mInput != AUDIO_IO_HANDLE_NONE) { if (mDeviceCallback != 0) { ALOGW("%s(%d): callback already present!", __func__, mPortId); AudioSystem::removeAudioDeviceCallback(this, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId); } status = AudioSystem::addAudioDeviceCallback(this, mInput); status = AudioSystem::addAudioDeviceCallback(this, mInput, mPortId); } mDeviceCallback = callback; return status; Loading @@ -1354,7 +1354,7 @@ status_t AudioRecord::removeAudioDeviceCallback( } mDeviceCallback.clear(); if (mInput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mInput); AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId); } return NO_ERROR; } Loading
media/libaudioclient/AudioSystem.cpp +57 −74 Original line number Diff line number Diff line Loading @@ -523,12 +523,10 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even if (ioDesc == 0 || ioDesc->mIoHandle == AUDIO_IO_HANDLE_NONE) return; audio_port_handle_t deviceId = AUDIO_PORT_HANDLE_NONE; Vector<sp<AudioDeviceCallback>> callbacksToCall; std::vector<sp<AudioDeviceCallback>> callbacksToCall; { Mutex::Autolock _l(mLock); bool deviceValidOrChanged = false; bool sendCallbacks = false; ssize_t ioIndex = -1; auto callbacks = std::map<audio_port_handle_t, wp<AudioDeviceCallback>>(); switch (event) { case AUDIO_OUTPUT_OPENED: Loading @@ -546,17 +544,11 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even if (ioDesc->getDeviceId() != AUDIO_PORT_HANDLE_NONE) { deviceId = ioDesc->getDeviceId(); if (event == AUDIO_OUTPUT_OPENED || event == AUDIO_INPUT_OPENED) { ioIndex = mAudioDeviceCallbackProxies.indexOfKey(ioDesc->mIoHandle); if (ioIndex >= 0) { sendCallbacks = true; deviceValidOrChanged = true; auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle); if (it != mAudioDeviceCallbacks.end()) { callbacks = it->second; } } if (event == AUDIO_OUTPUT_REGISTERED || event == AUDIO_INPUT_REGISTERED) { ioIndex = mAudioDeviceCallbackProxies.indexOfKey(ioDesc->mIoHandle); sendCallbacks = (ioIndex >= 0) && !mAudioDeviceCallbackProxies.valueAt(ioIndex).notifiedOnce(); } } ALOGV("ioConfigChanged() new %s %s %d samplingRate %u, format %#x channel mask %#x " "frameCount %zu deviceId %d", Loading @@ -578,7 +570,7 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even event == AUDIO_OUTPUT_CLOSED ? "output" : "input", ioDesc->mIoHandle); mIoDescriptors.removeItem(ioDesc->mIoHandle); mAudioDeviceCallbackProxies.removeItem(ioDesc->mIoHandle); mAudioDeviceCallbacks.erase(ioDesc->mIoHandle); } break; case AUDIO_OUTPUT_CONFIG_CHANGED: Loading @@ -593,10 +585,11 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even mIoDescriptors.replaceValueFor(ioDesc->mIoHandle, ioDesc); if (deviceId != ioDesc->getDeviceId()) { deviceValidOrChanged = true; deviceId = ioDesc->getDeviceId(); ioIndex = mAudioDeviceCallbackProxies.indexOfKey(ioDesc->mIoHandle); sendCallbacks = ioIndex >= 0; auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle); if (it != mAudioDeviceCallbacks.end()) { callbacks = it->second; } } ALOGV("ioConfigChanged() new config for %s %d samplingRate %u, format %#x " "channel mask %#x frameCount %zu frameCountHAL %zu deviceId %d", Loading @@ -606,35 +599,40 @@ void AudioSystem::AudioFlingerClient::ioConfigChanged(audio_io_config_event even ioDesc->getDeviceId()); } break; case AUDIO_CLIENT_STARTED: { sp<AudioIoDescriptor> oldDesc = getIoDescriptor_l(ioDesc->mIoHandle); if (oldDesc == 0) { ALOGW("ioConfigChanged() start client on unknown io! %d", ioDesc->mIoHandle); break; } // sendCallbacks true => ioDesc->mIoHandle and deviceId are valid if (sendCallbacks) { AudioDeviceCallbackProxies &callbackProxies = mAudioDeviceCallbackProxies.editValueAt(ioIndex); for (size_t i = 0; i < callbackProxies.size(); ) { sp<AudioDeviceCallback> callback = callbackProxies[i]->callback(); if (callback.get() != nullptr) { // Call the callback only if the device actually changed, the input or output // was opened or closed or the client was newly registered and the callback // was never called if (!callbackProxies[i]->notifiedOnce() || deviceValidOrChanged) { callbacksToCall.add(callback); callbackProxies[i]->setNotifiedOnce(); } i++; } else { callbackProxies.removeAt(i); ALOGV("ioConfigChanged() AUDIO_CLIENT_STARTED io %d port %d num callbacks %zu", ioDesc->mIoHandle, ioDesc->mPortId, mAudioDeviceCallbacks.size()); oldDesc->mPatch = ioDesc->mPatch; auto it = mAudioDeviceCallbacks.find(ioDesc->mIoHandle); if (it != mAudioDeviceCallbacks.end()) { auto cbks = it->second; auto it2 = cbks.find(ioDesc->mPortId); if (it2 != cbks.end()) { callbacks.emplace(ioDesc->mPortId, it2->second); deviceId = oldDesc->getDeviceId(); } } callbackProxies.setNotifiedOnce(); } break; } for (auto wpCbk : callbacks) { sp<AudioDeviceCallback> spCbk = wpCbk.second.promote(); if (spCbk != nullptr) { callbacksToCall.push_back(spCbk); } } } // Callbacks must be called without mLock held. May lead to dead lock if calling for // example getRoutedDevice that updates the device and tries to acquire mLock. for (size_t i = 0; i < callbacksToCall.size(); i++) { callbacksToCall[i]->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId); for (auto cb : callbacksToCall) { // If callbacksToCall is not empty, it implies ioDesc->mIoHandle and deviceId are valid cb->onAudioDeviceUpdate(ioDesc->mIoHandle, deviceId); } } Loading Loading @@ -687,51 +685,34 @@ sp<AudioIoDescriptor> AudioSystem::AudioFlingerClient::getIoDescriptor(audio_io_ } status_t AudioSystem::AudioFlingerClient::addAudioDeviceCallback( const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo, audio_port_handle_t portId) { ALOGV("%s audioIo %d portId %d", __func__, audioIo, portId); Mutex::Autolock _l(mLock); AudioDeviceCallbackProxies callbackProxies; ssize_t ioIndex = mAudioDeviceCallbackProxies.indexOfKey(audioIo); if (ioIndex >= 0) { callbackProxies = mAudioDeviceCallbackProxies.valueAt(ioIndex); } for (size_t cbIndex = 0; cbIndex < callbackProxies.size(); cbIndex++) { sp<AudioDeviceCallback> cbk = callbackProxies[cbIndex]->callback(); if (cbk.get() == callback.unsafe_get()) { auto& callbacks = mAudioDeviceCallbacks.emplace(audioIo, std::map<audio_port_handle_t, wp<AudioDeviceCallback>>()).first->second; auto result = callbacks.try_emplace(portId, callback); if (!result.second) { return INVALID_OPERATION; } } callbackProxies.add(new AudioDeviceCallbackProxy(callback)); callbackProxies.resetNotifiedOnce(); mAudioDeviceCallbackProxies.replaceValueFor(audioIo, callbackProxies); return NO_ERROR; } status_t AudioSystem::AudioFlingerClient::removeAudioDeviceCallback( const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback __unused, audio_io_handle_t audioIo, audio_port_handle_t portId) { ALOGV("%s audioIo %d portId %d", __func__, audioIo, portId); Mutex::Autolock _l(mLock); ssize_t ioIndex = mAudioDeviceCallbackProxies.indexOfKey(audioIo); if (ioIndex < 0) { auto it = mAudioDeviceCallbacks.find(audioIo); if (it == mAudioDeviceCallbacks.end()) { return INVALID_OPERATION; } AudioDeviceCallbackProxies callbackProxies = mAudioDeviceCallbackProxies.valueAt(ioIndex); size_t cbIndex; for (cbIndex = 0; cbIndex < callbackProxies.size(); cbIndex++) { sp<AudioDeviceCallback> cbk = callbackProxies[cbIndex]->callback(); if (cbk.get() == callback.unsafe_get()) { break; } } if (cbIndex == callbackProxies.size()) { if (it->second.erase(portId) == 0) { return INVALID_OPERATION; } callbackProxies.removeAt(cbIndex); if (callbackProxies.size() != 0) { mAudioDeviceCallbackProxies.replaceValueFor(audioIo, callbackProxies); } else { mAudioDeviceCallbackProxies.removeItem(audioIo); if (it->second.size() == 0) { mAudioDeviceCallbacks.erase(audioIo); } return NO_ERROR; } Loading Loading @@ -1271,13 +1252,14 @@ status_t AudioSystem::removeAudioVolumeGroupCallback(const sp<AudioVolumeGroupCa } status_t AudioSystem::addAudioDeviceCallback( const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo, audio_port_handle_t portId) { const sp<AudioFlingerClient> afc = getAudioFlingerClient(); if (afc == 0) { return NO_INIT; } status_t status = afc->addAudioDeviceCallback(callback, audioIo); status_t status = afc->addAudioDeviceCallback(callback, audioIo, portId); if (status == NO_ERROR) { const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); if (af != 0) { Loading @@ -1288,13 +1270,14 @@ status_t AudioSystem::addAudioDeviceCallback( } status_t AudioSystem::removeAudioDeviceCallback( const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo) const wp<AudioDeviceCallback>& callback, audio_io_handle_t audioIo, audio_port_handle_t portId) { const sp<AudioFlingerClient> afc = getAudioFlingerClient(); if (afc == 0) { return NO_INIT; } return afc->removeAudioDeviceCallback(callback, audioIo); return afc->removeAudioDeviceCallback(callback, audioIo, portId); } audio_port_handle_t AudioSystem::getDeviceIdForIo(audio_io_handle_t audioIo) Loading
media/libaudioclient/AudioTrack.cpp +11 −9 Original line number Diff line number Diff line Loading @@ -309,7 +309,7 @@ AudioTrack::~AudioTrack() } // 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(this, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId); } IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this); mAudioTrack.clear(); Loading Loading @@ -1495,7 +1495,6 @@ status_t AudioTrack::createTrack_l() mAfFrameCount = output.afFrameCount; mAfSampleRate = output.afSampleRate; mAfLatency = output.afLatencyMs; mPortId = output.portId; mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate; Loading Loading @@ -1543,14 +1542,15 @@ status_t AudioTrack::createTrack_l() mFlags = output.flags; //mOutput != output includes the case where mOutput == AUDIO_IO_HANDLE_NONE for first creation if (mDeviceCallback != 0 && mOutput != output.outputId) { if (mDeviceCallback != 0) { if (mOutput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId); } AudioSystem::addAudioDeviceCallback(this, output.outputId); AudioSystem::addAudioDeviceCallback(this, output.outputId, output.portId); callbackAdded = true; } mPortId = output.portId; // We retain a copy of the I/O handle, but don't own the reference mOutput = output.outputId; mRefreshRemaining = true; Loading Loading @@ -1615,7 +1615,7 @@ status_t AudioTrack::createTrack_l() exit: if (status != NO_ERROR && callbackAdded) { // note: mOutput is always valid is callbackAdded is true AudioSystem::removeAudioDeviceCallback(this, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId); } mStatus = status; Loading Loading @@ -2922,6 +2922,7 @@ uint32_t AudioTrack::getUnderrunFrames() const status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback) { if (callback == 0) { ALOGW("%s(%d): adding NULL callback!", __func__, mPortId); return BAD_VALUE; Loading @@ -2935,9 +2936,9 @@ status_t AudioTrack::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCal if (mOutput != AUDIO_IO_HANDLE_NONE) { if (mDeviceCallback != 0) { ALOGW("%s(%d): callback already present!", __func__, mPortId); AudioSystem::removeAudioDeviceCallback(this, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId); } status = AudioSystem::addAudioDeviceCallback(this, mOutput); status = AudioSystem::addAudioDeviceCallback(this, mOutput, mPortId); } mDeviceCallback = callback; return status; Loading @@ -2957,7 +2958,7 @@ status_t AudioTrack::removeAudioDeviceCallback( } mDeviceCallback.clear(); if (mOutput != AUDIO_IO_HANDLE_NONE) { AudioSystem::removeAudioDeviceCallback(this, mOutput); AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId); } return NO_ERROR; } Loading @@ -2979,6 +2980,7 @@ void AudioTrack::onAudioDeviceUpdate(audio_io_handle_t audioIo, mRoutedDeviceId = deviceId; } } if (callback.get() != nullptr) { callback->onAudioDeviceUpdate(mOutput, mRoutedDeviceId); } Loading
media/libaudioclient/IAudioFlingerClient.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ public: data.writeInt64(ioDesc->mFrameCount); data.writeInt64(ioDesc->mFrameCountHAL); data.writeInt32(ioDesc->mLatency); data.writeInt32(ioDesc->mPortId); remote()->transact(IO_CONFIG_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); } }; Loading @@ -76,6 +77,7 @@ status_t BnAudioFlingerClient::onTransact( ioDesc->mFrameCount = data.readInt64(); ioDesc->mFrameCountHAL = data.readInt64(); ioDesc->mLatency = data.readInt32(); ioDesc->mPortId = data.readInt32(); ioConfigChanged(event, ioDesc); return NO_ERROR; } break; Loading
media/libaudioclient/include/media/AudioIoDescriptor.h +3 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ enum audio_io_config_event { AUDIO_INPUT_OPENED, AUDIO_INPUT_CLOSED, AUDIO_INPUT_CONFIG_CHANGED, AUDIO_CLIENT_STARTED, }; // audio input/output descriptor used to cache output configurations in client process to avoid Loading @@ -37,7 +38,7 @@ public: AudioIoDescriptor() : mIoHandle(AUDIO_IO_HANDLE_NONE), mSamplingRate(0), mFormat(AUDIO_FORMAT_DEFAULT), mChannelMask(AUDIO_CHANNEL_NONE), mFrameCount(0), mFrameCountHAL(0), mLatency(0) mFrameCount(0), mFrameCountHAL(0), mLatency(0), mPortId(AUDIO_PORT_HANDLE_NONE) { memset(&mPatch, 0, sizeof(struct audio_patch)); } Loading Loading @@ -66,6 +67,7 @@ public: size_t mFrameCount; size_t mFrameCountHAL; uint32_t mLatency; // only valid for output audio_port_handle_t mPortId; // valid for event AUDIO_CLIENT_STARTED }; Loading