From 28b3b278f06067ef7167cf0ffa56121ad9d3768a Mon Sep 17 00:00:00 2001 From: Christian Linke Date: Wed, 4 Nov 2015 13:55:55 +0000 Subject: * Bug fix 392. Some improvements regarding failed transactions in the router. Signed-off-by: Christian Linke --- AudioManagerDaemon/include/CAmControlReceiver.h | 2 +- AudioManagerDaemon/include/CAmRoutingSender.h | 4 +- AudioManagerDaemon/src/CAmControlReceiver.cpp | 13 +- AudioManagerDaemon/src/CAmRoutingReceiver.cpp | 208 +++++++++++++++------ AudioManagerDaemon/src/CAmRoutingSender.cpp | 142 +++++++++++--- .../CAmControlInterfaceTest.cpp | 68 ++++++- AudioManagerDaemon/test/MockIAmRoutingSend.h | 3 + include/IAmControl.h | 7 +- include/IAmRouting.h | 7 +- include/audiomanagertypes.h | 10 +- 10 files changed, 376 insertions(+), 88 deletions(-) diff --git a/AudioManagerDaemon/include/CAmControlReceiver.h b/AudioManagerDaemon/include/CAmControlReceiver.h index 88ba507..3f39189 100644 --- a/AudioManagerDaemon/include/CAmControlReceiver.h +++ b/AudioManagerDaemon/include/CAmControlReceiver.h @@ -42,7 +42,6 @@ class CAmNodeStateCommunicator; class CAmControlReceiver: public IAmControlReceive { public: - CAmControlReceiver(IAmDatabaseHandler *iDatabaseHandler, CAmRoutingSender *iRoutingSender, CAmCommandSender *iCommandSender, CAmSocketHandler *iSocketHandler, CAmRouter* iRouter, CAmNodeStateCommunicator* iNodeStateCommunicator); CAmControlReceiver(IAmDatabaseHandler *iDatabaseHandler, CAmRoutingSender *iRoutingSender, CAmCommandSender *iCommandSender, CAmSocketHandler *iSocketHandler, CAmRouter* iRouter); ~CAmControlReceiver(); am_Error_e getRoute(const bool onlyfree, const am_sourceID_t sourceID, const am_sinkID_t sinkID, std::vector& returnList); @@ -141,6 +140,7 @@ public: am_Error_e getSinkSoundPropertyValue(const am_sinkID_t sinkID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const; am_Error_e getMainSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomMainSoundPropertyType_t propertyType, int16_t& value) const; am_Error_e getSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const; + am_Error_e resyncConnectionState(const am_domainID_t domainID, std::vector& listOfExistingConnections); private: IAmDatabaseHandler* mDatabaseHandler; //!< pointer tto the databasehandler diff --git a/AudioManagerDaemon/include/CAmRoutingSender.h b/AudioManagerDaemon/include/CAmRoutingSender.h index 532809a..4a23428 100644 --- a/AudioManagerDaemon/include/CAmRoutingSender.h +++ b/AudioManagerDaemon/include/CAmRoutingSender.h @@ -77,6 +77,7 @@ public: am_Error_e asyncSetVolumes(am_Handle_s& handle, const std::vector& listVolumes); am_Error_e asyncSetSinkNotificationConfiguration(am_Handle_s& handle, const am_sinkID_t sinkID, const am_NotificationConfiguration_s& notificationConfiguration); am_Error_e asyncSetSourceNotificationConfiguration(am_Handle_s& handle, const am_sourceID_t sourceID, const am_NotificationConfiguration_s& notificationConfiguration); + am_Error_e resyncConnectionState(const am_domainID_t domainID, std::vector& listOfExistingConnections); struct InterfaceNamePairs //!< is used to pair interfaces with busnames { @@ -109,7 +110,8 @@ public: }; - am_handleData_c returnHandleData(const am_Handle_s handle) const; //!< returns the handle data associated with a handle + am_Error_e returnHandleData(const am_Handle_s handle,CAmRoutingSender::am_handleData_c& handleData) const; //!< returns the handle data associated with a handle + am_Error_e returnHandleDataAndRemove(const am_Handle_s handle,CAmRoutingSender::am_handleData_c& handleData); //!< returns the handle data associated with a handle and removes the handle #ifdef UNIT_TEST //this is needed to test RoutingSender friend class IAmRoutingBackdoor; diff --git a/AudioManagerDaemon/src/CAmControlReceiver.cpp b/AudioManagerDaemon/src/CAmControlReceiver.cpp index 198109d..c1c161e 100644 --- a/AudioManagerDaemon/src/CAmControlReceiver.cpp +++ b/AudioManagerDaemon/src/CAmControlReceiver.cpp @@ -71,7 +71,12 @@ am_Error_e CAmControlReceiver::connect(am_Handle_s & handle, am_connectionID_t & tempConnection.delay=-1; mDatabaseHandler->enterConnectionDB(tempConnection, connectionID); - return (mRoutingSender->asyncConnect(handle, connectionID, sourceID, sinkID, format)); + am_Error_e syncError(mRoutingSender->asyncConnect(handle, connectionID, sourceID, sinkID, format)); + if (syncError) + { + mDatabaseHandler->removeConnection(connectionID); + } + return(syncError); } am_Error_e CAmControlReceiver::disconnect(am_Handle_s & handle, const am_connectionID_t connectionID) @@ -591,5 +596,11 @@ am_Error_e CAmControlReceiver::getSourceSoundPropertyValue(const am_sourceID_t s return (mDatabaseHandler->getSourceSoundPropertyValue(sourceID,propertyType,value)); } +am_Error_e CAmControlReceiver::resyncConnectionState(const am_domainID_t domainID,std::vector& listOfExistingConnections) +{ + logInfo("CAmControlReceiver::resyncConnectionState was called, domainID", domainID); + return (mRoutingSender->resyncConnectionState(domainID,listOfExistingConnections)); +} + } diff --git a/AudioManagerDaemon/src/CAmRoutingReceiver.cpp b/AudioManagerDaemon/src/CAmRoutingReceiver.cpp index 4628136..1c20d5c 100644 --- a/AudioManagerDaemon/src/CAmRoutingReceiver.cpp +++ b/AudioManagerDaemon/src/CAmRoutingReceiver.cpp @@ -81,131 +81,193 @@ CAmRoutingReceiver::~CAmRoutingReceiver() void CAmRoutingReceiver::ackConnect(const am_Handle_s handle, const am_connectionID_t connectionID, const am_Error_e error) { mpRoutingSender->removeHandle(handle); - if (error == E_OK) + if (error == am_Error_e::E_OK) { mpDatabaseHandler->changeConnectionFinal(connectionID); } else { mpDatabaseHandler->removeConnection(connectionID); + mpRoutingSender->removeConnectionLookup(connectionID); } mpControlSender->cbAckConnect(handle, error); } void CAmRoutingReceiver::ackDisconnect(const am_Handle_s handle, const am_connectionID_t connectionID, const am_Error_e error) { + + //so we will remove the connection anyway no matter what is answered mpRoutingSender->removeHandle(handle); - if (error == E_OK) - { - mpDatabaseHandler->removeConnection(connectionID); - if (mpRoutingSender->removeConnectionLookup(connectionID)!=E_OK) - { - logError("CAmRoutingReceiver::ackDisconnect could not remove connectionId from lookup"); - } - } + mpDatabaseHandler->removeConnection(connectionID); + mpRoutingSender->removeConnectionLookup(connectionID); mpControlSender->cbAckDisconnect(handle, error); } void CAmRoutingReceiver::ackSetSinkVolumeChange(const am_Handle_s handle, const am_volume_t volume, const am_Error_e error) { - CAmRoutingSender::am_handleData_c handleData = mpRoutingSender->returnHandleData(handle); - if (error == E_OK && handleData.sinkID != 0) + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) { - //todo: check if volume in handleData is same than volume. React to it. - mpDatabaseHandler->changeSinkVolume(handleData.sinkID, volume); + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if (error== am_Error_e::E_OK || am_Error_e::E_ABORTED) + { + mpDatabaseHandler->changeSinkVolume(handleData.sinkID, volume); + } + + if(error == am_Error_e::E_OK || handleData.volume!=volume) + { + logError("ackSetSinkVolumeChange volumes do not match, requested volume",handleData.volume,"returned volume",volume); } - mpRoutingSender->removeHandle(handle); mpControlSender->cbAckSetSinkVolumeChange(handle, volume, error); } void CAmRoutingReceiver::ackSetSourceVolumeChange(const am_Handle_s handle, const am_volume_t volume, const am_Error_e error) { - CAmRoutingSender::am_handleData_c handleData = mpRoutingSender->returnHandleData(handle); - if (error == E_OK && handleData.sourceID != 0) + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) { - //todo: check if volume in handleData is same than volume. React to it. - mpDatabaseHandler->changeSourceVolume(handleData.sourceID, volume); + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if (error== am_Error_e::E_OK || am_Error_e::E_ABORTED) + { + mpDatabaseHandler->changeSourceVolume(handleData.sourceID, volume); + } + + if(error == E_OK || handleData.volume!=volume) + { + logError("ackSetSourceVolumeChange volumes do not match, requested volume",handleData.volume,"returned volume",volume); } - mpRoutingSender->removeHandle(handle); mpControlSender->cbAckSetSourceVolumeChange(handle, volume, error); } void CAmRoutingReceiver::ackSetSourceState(const am_Handle_s handle, const am_Error_e error) { - CAmRoutingSender::am_handleData_c handleData = mpRoutingSender->returnHandleData(handle); - if (error == E_OK && handleData.sourceID != 0) + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) { - //todo: check if volume in handleData is same than volume. React to it. - mpDatabaseHandler->changeSourceState(handleData.sourceID, handleData.sourceState); + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; } - mpRoutingSender->removeHandle(handle); + + //no error, so we can write the change into the database; + if (error == am_Error_e::E_OK) + { + mpDatabaseHandler->changeSourceState(handleData.sourceID, handleData.sourceState); + } + mpControlSender->cbAckSetSourceState(handle, error); } void CAmRoutingReceiver::ackSetSinkSoundProperty(const am_Handle_s handle, const am_Error_e error) { - CAmRoutingSender::am_handleData_c handleData = mpRoutingSender->returnHandleData(handle); - if (error == E_OK && handleData.sinkID != 0) + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if (error==am_Error_e::E_OK) { mpDatabaseHandler->changeSinkSoundPropertyDB(handleData.soundPropery, handleData.sinkID); } - mpRoutingSender->removeHandle(handle); + mpControlSender->cbAckSetSinkSoundProperty(handle, error); } void am::CAmRoutingReceiver::ackSetSinkSoundProperties(const am_Handle_s handle, const am_Error_e error) { - CAmRoutingSender::am_handleData_c handleData = mpRoutingSender->returnHandleData(handle); - if (error == E_OK && handleData.sinkID != 0) + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if (error==am_Error_e::E_OK) { std::vector::const_iterator it = handleData.soundProperties->begin(); for (; it != handleData.soundProperties->end(); ++it) { mpDatabaseHandler->changeSinkSoundPropertyDB(*it, handleData.sinkID); } - delete handleData.soundProperties; } - mpRoutingSender->removeHandle(handle); + + try + { + delete handleData.soundProperties; + } + catch(...) + { + logError("exception while deleting handleData while ackSetSinkSoundProperties"); + } mpControlSender->cbAckSetSinkSoundProperties(handle, error); } void CAmRoutingReceiver::ackSetSourceSoundProperty(const am_Handle_s handle, const am_Error_e error) { - CAmRoutingSender::am_handleData_c handleData = mpRoutingSender->returnHandleData(handle); - if (error == E_OK && handleData.sourceID != 0) + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if(error==am_Error_e::E_OK) { mpDatabaseHandler->changeSourceSoundPropertyDB(handleData.soundPropery, handleData.sourceID); } - mpRoutingSender->removeHandle(handle); mpControlSender->cbAckSetSourceSoundProperty(handle, error); } void am::CAmRoutingReceiver::ackSetSourceSoundProperties(const am_Handle_s handle, const am_Error_e error) { - CAmRoutingSender::am_handleData_c handleData = mpRoutingSender->returnHandleData(handle); - if (error == E_OK && handleData.sourceID != 0) + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if(error==am_Error_e::E_OK) { std::vector::const_iterator it = handleData.soundProperties->begin(); for (; it != handleData.soundProperties->end(); ++it) { mpDatabaseHandler->changeSourceSoundPropertyDB(*it, handleData.sourceID); } - delete handleData.soundProperties; } - mpRoutingSender->removeHandle(handle); + + try + { + delete handleData.soundProperties; + } + catch(...) + { + logError("exception while deleting handleData while ackSetSourceSoundProperties"); + } mpControlSender->cbAckSetSourceSoundProperties(handle, error); } void CAmRoutingReceiver::ackCrossFading(const am_Handle_s handle, const am_HotSink_e hotSink, const am_Error_e error) { - CAmRoutingSender::am_handleData_c handleData = mpRoutingSender->returnHandleData(handle); - if (error == E_OK && handleData.crossfaderID != 0) + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if(error==am_Error_e::E_OK) { - //todo: check if volume in handleData is same than volume. React to it. mpDatabaseHandler->changeCrossFaderHotSink(handleData.crossfaderID, hotSink); } - mpRoutingSender->removeHandle(handle); mpControlSender->cbAckCrossFade(handle, hotSink, error); } @@ -404,25 +466,50 @@ void am::CAmRoutingReceiver::waitOnStartup(bool startup) void CAmRoutingReceiver::ackSinkNotificationConfiguration(const am_Handle_s handle, const am_Error_e error) { - CAmRoutingSender::am_handleData_c handleData = mpRoutingSender->returnHandleData(handle); - if (error == E_OK && handleData.sinkID != 0) + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if(error==am_Error_e::E_OK) { mpDatabaseHandler->changeSinkNotificationConfigurationDB(handleData.sinkID,*handleData.notificationConfiguration); - delete handleData.notificationConfiguration; } - mpRoutingSender->removeHandle(handle); + + try + { + delete handleData.notificationConfiguration; + } + catch(...) + { + logError("exception while deleting handleData while ackSinkNotificationConfiguration"); + } mpControlSender->cbAckSetSinkNotificationConfiguration(handle,error); } void CAmRoutingReceiver::ackSourceNotificationConfiguration(const am_Handle_s handle, const am_Error_e error) { - CAmRoutingSender::am_handleData_c handleData = mpRoutingSender->returnHandleData(handle); - if (error == E_OK && handleData.sourceID != 0) + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if(error==am_Error_e::E_OK) { mpDatabaseHandler->changeSourceNotificationConfigurationDB(handleData.sourceID,*handleData.notificationConfiguration); - delete handleData.notificationConfiguration; } - mpRoutingSender->removeHandle(handle); + try + { + delete handleData.notificationConfiguration; + } + catch(...) + { + logError("exception while deleting handleData while ackSourceNotificationConfiguration"); + } mpControlSender->cbAckSetSourceNotificationConfiguration(handle,error); } @@ -448,8 +535,14 @@ am_Error_e CAmRoutingReceiver::updateSource(const am_sourceID_t sourceID, const void CAmRoutingReceiver::ackSetVolumes(const am_Handle_s handle, const std::vector& listvolumes, const am_Error_e error) { - CAmRoutingSender::am_handleData_c handleData = mpRoutingSender->returnHandleData(handle); - if (error == E_OK && handleData.volumeID.sink != 0) + CAmRoutingSender::am_handleData_c handleData; + if (mpRoutingSender->returnHandleDataAndRemove(handle,handleData)) + { + logError(__PRETTY_FUNCTION__,"Could not find handleData, handle: ",handle.handle); + return; + } + + if(error==am_Error_e::E_OK) { std::vector::const_iterator iterator (listvolumes.begin()); @@ -466,7 +559,16 @@ void CAmRoutingReceiver::ackSetVolumes(const am_Handle_s handle, const std::vect } } - mpRoutingSender->removeHandle(handle); + + try + { + delete handleData.listVolumes; + } + catch(...) + { + logError("exception while deleting handleData while ackSetVolumes"); + } + mpControlSender->cbAckSetVolume(handle,listvolumes,error); } diff --git a/AudioManagerDaemon/src/CAmRoutingSender.cpp b/AudioManagerDaemon/src/CAmRoutingSender.cpp index e419356..efd44e1 100644 --- a/AudioManagerDaemon/src/CAmRoutingSender.cpp +++ b/AudioManagerDaemon/src/CAmRoutingSender.cpp @@ -205,6 +205,7 @@ am_Error_e CAmRoutingSender::asyncAbort(const am_Handle_s& handle) iter = mMapHandleInterface.find(handle.handle); if (iter != mMapHandleInterface.end()) { + removeHandle(handle); return (iter->second->asyncAbort(handle)); } @@ -222,7 +223,15 @@ am_Error_e CAmRoutingSender::asyncConnect(am_Handle_s& handle, const am_connecti handle = createHandle(handleData, H_CONNECT); mMapConnectionInterface.insert(std::make_pair(connectionID, iter->second)); mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); - return (iter->second->asyncConnect(handle, connectionID, sourceID, sinkID, connectionFormat)); + am_Error_e syncError(iter->second->asyncConnect(handle, connectionID, sourceID, sinkID, connectionFormat)); + + if (syncError) + { + removeHandle(handle); + removeConnectionLookup(connectionID); + } + return(syncError); + } return (E_NON_EXISTENT); @@ -238,8 +247,12 @@ am_Error_e CAmRoutingSender::asyncDisconnect(am_Handle_s& handle, const am_conne handleData.connectionID = connectionID; handle = createHandle(handleData, H_DISCONNECT); mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); - am_Error_e returnVal = iter->second->asyncDisconnect(handle, connectionID); - return (returnVal); + am_Error_e syncError(iter->second->asyncDisconnect(handle, connectionID)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); } return (E_NON_EXISTENT); @@ -256,7 +269,12 @@ am_Error_e CAmRoutingSender::asyncSetSinkVolume(am_Handle_s& handle, const am_si handleData.volume = volume; handle = createHandle(handleData, H_SETSINKVOLUME); mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); - return (iter->second->asyncSetSinkVolume(handle, sinkID, volume, ramp, time)); + am_Error_e syncError(iter->second->asyncSetSinkVolume(handle, sinkID, volume, ramp, time)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); } return (E_NON_EXISTENT); } @@ -272,7 +290,12 @@ am_Error_e CAmRoutingSender::asyncSetSourceVolume(am_Handle_s& handle, const am_ handleData.volume = volume; handle = createHandle(handleData, H_SETSOURCEVOLUME); mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); - return (iter->second->asyncSetSourceVolume(handle, sourceID, volume, ramp, time)); + am_Error_e syncError(iter->second->asyncSetSourceVolume(handle, sourceID, volume, ramp, time)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); } return (E_NON_EXISTENT); } @@ -288,7 +311,12 @@ am_Error_e CAmRoutingSender::asyncSetSourceState(am_Handle_s& handle, const am_s handleData.sourceState = state; handle = createHandle(handleData, H_SETSOURCESTATE); mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); - return (iter->second->asyncSetSourceState(handle, sourceID, state)); + am_Error_e syncError(iter->second->asyncSetSourceState(handle, sourceID, state)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); } return (E_NON_EXISTENT); } @@ -304,7 +332,12 @@ am_Error_e CAmRoutingSender::asyncSetSinkSoundProperty(am_Handle_s& handle, cons handleData.soundPropery = soundProperty; handle = createHandle(handleData, H_SETSINKSOUNDPROPERTY); mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); - return (iter->second->asyncSetSinkSoundProperty(handle, sinkID, soundProperty)); + am_Error_e syncError(iter->second->asyncSetSinkSoundProperty(handle, sinkID, soundProperty)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); } return (E_NON_EXISTENT); } @@ -320,7 +353,12 @@ am_Error_e CAmRoutingSender::asyncSetSourceSoundProperty(am_Handle_s& handle, co handleData.soundPropery = soundProperty; handle = createHandle(handleData, H_SETSOURCESOUNDPROPERTY); mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); - return (iter->second->asyncSetSourceSoundProperty(handle, sourceID, soundProperty)); + am_Error_e syncError(iter->second->asyncSetSourceSoundProperty(handle, sourceID, soundProperty)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); } return (E_NON_EXISTENT); } @@ -336,7 +374,12 @@ am_Error_e CAmRoutingSender::asyncSetSourceSoundProperties(am_Handle_s& handle, handleData.soundProperties = new std::vector(listSoundProperties); handle = createHandle(handleData, H_SETSOURCESOUNDPROPERTIES); mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); - return (iter->second->asyncSetSourceSoundProperties(handle, sourceID, listSoundProperties)); + am_Error_e syncError(iter->second->asyncSetSourceSoundProperties(handle, sourceID, listSoundProperties)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); } return (E_NON_EXISTENT); } @@ -352,7 +395,13 @@ am_Error_e CAmRoutingSender::asyncSetSinkSoundProperties(am_Handle_s& handle, co handleData.soundProperties = new std::vector(listSoundProperties); handle = createHandle(handleData, H_SETSINKSOUNDPROPERTIES); mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); - return (iter->second->asyncSetSinkSoundProperties(handle, sinkID, listSoundProperties)); + am_Error_e syncError(iter->second->asyncSetSinkSoundProperties(handle, sinkID, listSoundProperties)); + if (syncError) + { + removeHandle(handle); + delete handleData.soundProperties; + } + return(syncError); } return (E_NON_EXISTENT); @@ -369,7 +418,12 @@ am_Error_e CAmRoutingSender::asyncCrossFade(am_Handle_s& handle, const am_crossf handleData.hotSink = hotSink; handle = createHandle(handleData, H_CROSSFADE); mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); - return (iter->second->asyncCrossFade(handle, crossfaderID, hotSink, rampType, time)); + am_Error_e syncError(iter->second->asyncCrossFade(handle, crossfaderID, hotSink, rampType, time)); + if (syncError) + { + removeHandle(handle); + } + return(syncError); } return (E_NON_EXISTENT); } @@ -535,7 +589,6 @@ am_Error_e CAmRoutingSender::removeHandle(const am_Handle_s& handle) { if (mlistActiveHandles.erase(handle)) { - logInfo(__PRETTY_FUNCTION__,handle.handle,handle.handleType); return (E_OK); } logError(__PRETTY_FUNCTION__,"Could not remove handle",handle.handle); @@ -578,25 +631,18 @@ am_Handle_s CAmRoutingSender::createHandle(const am_handleData_c& handleData, co * @param handle the handle * @return a class holding the handle data */ -CAmRoutingSender::am_handleData_c CAmRoutingSender::returnHandleData(const am_Handle_s handle) const +am_Error_e CAmRoutingSender::returnHandleData(const am_Handle_s handle,CAmRoutingSender::am_handleData_c& handleData) const { - HandlesMap::const_iterator it = mlistActiveHandles.begin(); it = mlistActiveHandles.find(handle); if (it!=mlistActiveHandles.end()) { - const am_handleData_c & result = it->second; - logInfo(__PRETTY_FUNCTION__, handle.handle, handle.handleType, - "connectionID", result.connectionID, - "sinkID", result.sinkID, - "sourceID",result.sourceID, - "sourceState", result.sourceState); - return result; + handleData = it->second; + return (am_Error_e::E_OK); } - am_handleData_c handleData; handleData.sinkID=0; logError(__PRETTY_FUNCTION__,"could not find handle data for handle",handle.handle,handle.handleType); - return (handleData); + return (am_Error_e::E_NON_EXISTENT); } void CAmRoutingSender::setRoutingReady() @@ -681,7 +727,14 @@ am_Error_e CAmRoutingSender::asyncSetVolumes(am_Handle_s& handle, const std::vec handle = createHandle(handleData, H_SETVOLUMES); mMapHandleInterface.insert(std::make_pair(+ handle.handle, pRoutingInterface)); - return (pRoutingInterface->asyncSetVolumes(handle, listVolumes)); + am_Error_e syncError(pRoutingInterface->asyncSetVolumes(handle, listVolumes)); + if (syncError) + { + removeHandle(handle); + delete handleData.listVolumes; + } + return(syncError); + } am_Error_e CAmRoutingSender::asyncSetSinkNotificationConfiguration(am_Handle_s& handle, const am_sinkID_t sinkID, const am_NotificationConfiguration_s& notificationConfiguration) @@ -695,7 +748,13 @@ am_Error_e CAmRoutingSender::asyncSetSinkNotificationConfiguration(am_Handle_s& handleData.notificationConfiguration = new am_NotificationConfiguration_s(notificationConfiguration); handle = createHandle(handleData, H_SETSINKNOTIFICATION); mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); - return (iter->second->asyncSetSinkNotificationConfiguration(handle, sinkID,notificationConfiguration)); + am_Error_e syncError(iter->second->asyncSetSinkNotificationConfiguration(handle, sinkID,notificationConfiguration)); + if (syncError) + { + removeHandle(handle); + delete handleData.notificationConfiguration; + } + return(syncError); } return (E_NON_EXISTENT); } @@ -711,7 +770,13 @@ am_Error_e CAmRoutingSender::asyncSetSourceNotificationConfiguration(am_Handle_s handleData.notificationConfiguration = new am_NotificationConfiguration_s(notificationConfiguration); handle = createHandle(handleData, H_SETSOURCENOTIFICATION); mMapHandleInterface.insert(std::make_pair(+ handle.handle, iter->second)); - return (iter->second->asyncSetSourceNotificationConfiguration(handle, sourceID,notificationConfiguration)); + am_Error_e syncError(iter->second->asyncSetSourceNotificationConfiguration(handle, sourceID,notificationConfiguration)); + if (syncError) + { + removeHandle(handle); + delete handleData.notificationConfiguration; + } + return(syncError); } return (E_NON_EXISTENT); } @@ -740,4 +805,29 @@ void CAmRoutingSender::getInterfaceVersion(std::string & version) const { version = RoutingVersion; } +am_Error_e CAmRoutingSender::resyncConnectionState(const am_domainID_t domainID,std::vector& listOfExistingConnections) +{ + DomainInterfaceMap::iterator iter = mMapDomainInterface.begin(); + iter = mMapDomainInterface.find(domainID); + if (iter != mMapDomainInterface.end()) + return (iter->second->resyncConnectionState(domainID, listOfExistingConnections)); + return (E_NON_EXISTENT); +} + +am_Error_e CAmRoutingSender::returnHandleDataAndRemove(const am_Handle_s handle,CAmRoutingSender::am_handleData_c& handleData) +{ + HandlesMap::const_iterator it = mlistActiveHandles.begin(); + it = mlistActiveHandles.find(handle); + if (it!=mlistActiveHandles.end()) + { + handleData = it->second; + mlistActiveHandles.erase(handle); + return (am_Error_e::E_OK); + } + handleData.sinkID=0; + logError(__PRETTY_FUNCTION__,"could not find handle data for handle",handle.handle,handle.handleType); + return (am_Error_e::E_NON_EXISTENT); + +} + } diff --git a/AudioManagerDaemon/test/AmControlInterfaceTest/CAmControlInterfaceTest.cpp b/AudioManagerDaemon/test/AmControlInterfaceTest/CAmControlInterfaceTest.cpp index ffc493a..9f58a5a 100644 --- a/AudioManagerDaemon/test/AmControlInterfaceTest/CAmControlInterfaceTest.cpp +++ b/AudioManagerDaemon/test/AmControlInterfaceTest/CAmControlInterfaceTest.cpp @@ -32,6 +32,17 @@ using namespace testing; DLT_DECLARE_CONTEXT(AudioManager) +ACTION(returnResyncConnection) +{ + std::vector listConnections; + am_Connection_s conn; + conn.sinkID=1; + conn.sourceID=1; + conn.connectionFormat=CF_GENIVI_ANALOG; + listConnections.push_back(conn); + arg1=listConnections; +} + CAmControlInterfaceTest::CAmControlInterfaceTest() : pSocketHandler(), // plistCommandPluginDirs(), // @@ -306,7 +317,7 @@ TEST_F(CAmControlInterfaceTest,ackDisconnectFailAndRetry) //then we fire the ack and expect a call on the controlInterface EXPECT_CALL(pMockControlInterface,cbAckDisconnect(_,E_NON_EXISTENT)).Times(1); - pRoutingReceiver.ackDisconnect(handle, connectionID, E_NON_EXISTENT); + pRoutingReceiver.ackDisconnect(handle, connectionID+1, E_NON_EXISTENT); //make sure the handle is gone ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); @@ -588,6 +599,61 @@ TEST_F(CAmControlInterfaceTest,crossFading) //todo: implement crossfading test } +TEST_F(CAmControlInterfaceTest,resyncConnectionsTest) +{ + am_Domain_s domain; + am_domainID_t domainID; + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + + //prepare the scene + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + + std::vector listConnections; + + EXPECT_CALL(pMockRoutingInterface,resyncConnectionState(domainID,_)).WillOnce(DoAll(returnResyncConnection(), Return(E_OK))); + ASSERT_EQ(am_Error_e::E_OK,pControlReceiver.resyncConnectionState(domainID,listConnections)); + ASSERT_EQ(listConnections[0].sinkID,1); + ASSERT_EQ(listConnections[0].sourceID,1); + ASSERT_EQ(listConnections[0].connectionFormat,CF_GENIVI_ANALOG); +} + +TEST_F(CAmControlInterfaceTest,ackConnectNotPossible) +{ + am_connectionID_t connectionID; + am_Sink_s sink; + am_sinkID_t sinkID; + am_Domain_s domain; + am_domainID_t domainID; + std::vector connectionList; + std::vector handlesList; + am_Handle_s handle; + pCF.createSink(sink); + pCF.createDomain(domain); + domain.name = "mock"; + domain.busname = "mock"; + sink.sinkID = 2; + sink.domainID = DYNAMIC_ID_BOUNDARY; + + //prepare the stage + ASSERT_EQ(E_OK, pDatabaseHandler.enterDomainDB(domain,domainID)); + ASSERT_EQ(E_OK, pDatabaseHandler.enterSinkDB(sink,sinkID)); + + //when asyncConnect is called, we expect a call on the routingInterface + EXPECT_CALL(pMockRoutingInterface,asyncConnect(_,1,2,2,CF_GENIVI_STEREO)).WillOnce(Return(E_COMMUNICATION)); + ASSERT_EQ(E_COMMUNICATION, pControlReceiver.connect(handle,connectionID,CF_GENIVI_STEREO,2,2)); + + //The list of handles shall be empty + ASSERT_EQ(E_OK, pControlReceiver.getListHandles(handlesList)); + ASSERT_TRUE(handlesList.empty()); + + + ASSERT_EQ(E_OK, pDatabaseHandler.getListConnections(connectionList)); + ASSERT_TRUE(connectionList.empty()); + +} + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/AudioManagerDaemon/test/MockIAmRoutingSend.h b/AudioManagerDaemon/test/MockIAmRoutingSend.h index e16235b..748e64e 100644 --- a/AudioManagerDaemon/test/MockIAmRoutingSend.h +++ b/AudioManagerDaemon/test/MockIAmRoutingSend.h @@ -71,6 +71,9 @@ class MockIAmRoutingSend : public IAmRoutingSend { am_Error_e(const am_Handle_s handle, const am_sinkID_t sinkID, const am_NotificationConfiguration_s& notificationConfiguration)); MOCK_METHOD3(asyncSetSourceNotificationConfiguration, am_Error_e(const am_Handle_s handle, const am_sourceID_t sourceID, const am_NotificationConfiguration_s& notificationConfiguration)); + MOCK_METHOD2(resyncConnectionState, + am_Error_e(const am_domainID_t domainID, std::vector& listOfExistingConnections)); + }; diff --git a/include/IAmControl.h b/include/IAmControl.h index 8220728..53526fe 100644 --- a/include/IAmControl.h +++ b/include/IAmControl.h @@ -32,7 +32,7 @@ class CAmSocketHandler; #include "audiomanagertypes.h" -#define ControlVersion "4.0" +#define ControlVersion "5.0" namespace am { /** @@ -639,6 +639,11 @@ public: * @return E_OK when successful, E_DATABASE on error */ virtual am_Error_e getSourceSoundPropertyValue(const am_sourceID_t sourceID, const am_CustomSoundPropertyType_t propertyType, int16_t& value) const =0; + /** + * Retrieves a list of all current active connections from a domain. This method + * is meant to be used if the audiomanager and a remote domain are out of sync. + */ + virtual am_Error_e resyncConnectionState(const am_domainID_t domainID, std::vector& listOfExistingConnections) =0; }; diff --git a/include/IAmRouting.h b/include/IAmRouting.h index 14f1146..1acaac6 100644 --- a/include/IAmRouting.h +++ b/include/IAmRouting.h @@ -35,7 +35,7 @@ class CAmSocketHandler; #include "audiomanagertypes.h" -#define RoutingVersion "4.0" +#define RoutingVersion "5.0" namespace am { /** @@ -482,6 +482,11 @@ public: * @return E_OK on success, E_UNKNOWN on error. */ virtual am_Error_e asyncSetSourceNotificationConfiguration(const am_Handle_s handle, const am_sourceID_t sourceID, const am_NotificationConfiguration_s& notificationConfiguration) =0; + /** + * Retrieves a list of all current active connections from a domain. This method + * is meant to be used if the audiomanager and a remote domain are out of sync. + */ + virtual am_Error_e resyncConnectionState(const am_domainID_t domainID, std::vector& listOfExistingConnections) =0; }; } diff --git a/include/audiomanagertypes.h b/include/audiomanagertypes.h index aeb802d..d60e2a3 100755 --- a/include/audiomanagertypes.h +++ b/include/audiomanagertypes.h @@ -20,8 +20,8 @@ * THIS CODE HAS BEEN GENERATED BY ENTERPRISE ARCHITECT GENIVI MODEL. * PLEASE CHANGE ONLY IN ENTERPRISE ARCHITECT AND GENERATE AGAIN. */ -#if !defined(EA_95D3C82A_0870_4fe0_A468_5AFF99D80A26__INCLUDED_) -#define EA_95D3C82A_0870_4fe0_A468_5AFF99D80A26__INCLUDED_ +#if !defined(EA_E0F066FD_E6D8_4ca9_84C3_D0C02AF09BF8__INCLUDED_) +#define EA_E0F066FD_E6D8_4ca9_84C3_D0C02AF09BF8__INCLUDED_ #include #include @@ -372,6 +372,10 @@ enum am_Error_e * capabilities of a source or a sink or gateway compatibilities for example */ E_WRONG_FORMAT = 10, + /** + * A communication error happened + */ + E_COMMUNICATION = 11, E_MAX }; @@ -1461,4 +1465,4 @@ public: }; } -#endif // !defined(EA_95D3C82A_0870_4fe0_A468_5AFF99D80A26__INCLUDED_) +#endif // !defined(EA_E0F066FD_E6D8_4ca9_84C3_D0C02AF09BF8__INCLUDED_) -- cgit v1.2.1