diff -r 000000000000 -r 4e1aa6a622a0 sensorservices/sensorserver/src/server/sensrvproxymanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensorservices/sensorserver/src/server/sensrvproxymanager.cpp Tue Feb 02 00:53:00 2010 +0200 @@ -0,0 +1,1482 @@ +/* +* Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Sensor server proxy manager +* +*/ + + +#include +#include "sensrvdefines.h" +#include "sensrvproxymanager.h" +#include "sensrvsession.h" +#include "sensrvserver.h" +#include "sensrvtrace.h" +#include "ssycontrol.h" +#include "sensrvtransactionqueue.h" +#include "sensrvmessage.h" +#include "sensrvclientserver.h" +#include "sensrvtransaction.h" +#include "sensrvtypes.h" +#include "sensrvprivatecrkeys.h" + +#ifdef __WINS__ +// Multiplier to avoid out of memory in emulator +const TInt KSensrvSsyMaxHeapWinsMultiplier = 2; +#endif // __WINS__ + + +// --------------------------------------------------------------------------- +// 2-phase constructor +// --------------------------------------------------------------------------- +// +CSensrvProxyManager* CSensrvProxyManager::NewL(CSensrvServer& aServer) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::CSensrvProxyManager()" ) ) ); + + CSensrvProxyManager* self = new( ELeave ) CSensrvProxyManager(aServer); + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::CSensrvProxyManager - return 0x%x" ), self ) ); + return self; + } + +// --------------------------------------------------------------------------- +// C++ constructor +// --------------------------------------------------------------------------- +// +CSensrvProxyManager::CSensrvProxyManager(CSensrvServer& aServer) + : iServer(aServer), + iTransactionTimeout(KSensrvDefaultTransactionTimeout), + iSsyStackSize(KSensrvDefaultSsyStackSize), + iSsyHeapMaxSize(KSensrvDefaultSsyHeapMaxSize), + iThreadTerminationGracePeriod(KSensrvSsyGracefulCleanupTime), + iSsyInactivityPeriod(KSensrvSsyInactivityPeriod), + iBufferSizeMultiplier(KSensrvDefaultDataRateMultiplier), + iTerminationPeriod(KSensrvDefaultTerminationPeriod) + { + // Nothing to do + } + +// --------------------------------------------------------------------------- +// 2nd phase of construction +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::ConstructL() + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ConstructL()" ) ) ); + + User::LeaveIfError(iServerThread.Open(iServerThread.Id())); + + iHeap = &User::Heap(); + + User::LeaveIfError(iProxyManagerMutex.CreateLocal()); + + // Get configurable settings + GetSettings(); + + iServerShutdown = CSensrvShutdown::NewL( *this ); + + iWaitQueueQueryChannels = CSensrvTransactionQueue::NewL(ETrue); + iWaitQueueOpenChannel = CSensrvTransactionQueue::NewL(ETrue); + + // Create ecom changelistener, which will make the initial check for plugins + iEcomChangeListener = CSensrvEcomChangeListener::NewL(*this); + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ConstructL - return" ) ) ); + } + + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +CSensrvProxyManager::~CSensrvProxyManager() + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::~CSensrvProxyManager()" ) ) ); + + if (iProxyCleaner) + { + iProxyCleaner->Cancel(); + delete iProxyCleaner; + } + + delete iEcomChangeListener; + + // Cleanup iProxyList + TInt count = iProxyList.Count(); + for(TInt i = 0; i < count; i++) + { + delete iProxyList[i]; + } + + iProxyList.Reset(); + + // Cleanup iWaitQueue + delete iWaitQueueQueryChannels; + delete iWaitQueueOpenChannel; + + iProxyManagerMutex.Close(); + + iServerThread.Close(); + + if (iShutdownMessage.Handle()) + { + iShutdownMessage.Complete(KErrCancel); + } + + if (iSsyImplInfoArray) + { + iSsyImplInfoArray->ResetAndDestroy(); + delete iSsyImplInfoArray; + } + + delete iServerShutdown; + + // iHeap not owned + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::~CSensrvProxyManager - return") ) ); + } + +// ----------------------------------------------------------------------------- +// Handles message according to message type +// ----------------------------------------------------------------------------- +// +void CSensrvProxyManager::DispatchMessage( CSensrvMessage& aMessage ) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::DispatchMessage(aMessage.Function(): %d), client SID: 0x%x" ), aMessage.Function(), aMessage.SecureId().iId ) ); + + // Check command code and call appropriate function + switch ( aMessage.Function() ) + { + case ESensrvSrvReqQueryChannels: + { + QueryChannels(aMessage); + break; + } + + case ESensrvSrvReqOpenChannel: + { + // Get channel ID from message + // No need to check error value, we already made sure the message function is correct + + TSensrvChannelId channelId(0); + aMessage.GetChannelId(channelId); + + // Determine which proxy handles this channel + CSensrvPluginProxy* proxy = GetProxyForChannel(channelId); + + if( proxy != NULL && + (proxy->PluginState() == CSensrvPluginProxy::EPluginStateUnloaded || + proxy->PluginState() == CSensrvPluginProxy::EPluginStateUninitialized ) ) + { + TRAPD(err, proxy->InitializePluginL()); + if ( err != KErrNone ) + { + // If proxy initialization fails, it means that proxy will not provide any channels. + // Since SSY thread has not been resumed yet (resume is the last thing in InitializeL), proxy + // can be safely deleted without risk for memory leak. + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::EcomChanged - ERROR: Proxy initialization failed, error %d" ), err) ); + TInt pos( iProxyList.Find( proxy ) ); + delete proxy; + proxy = NULL; + if ( pos >= 0 && pos < iProxyList.Count() ) + { + iProxyList.Remove(pos); + } + } + } + + // Dispatch the message for found proxy to be handled + if (proxy != NULL) + { + proxy->DispatchMessage(aMessage, channelId); // Transfer ownership of message + } + else + { + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::DispatchMessage - ERROR: Proxy not found" )) ); + // Complete with error + aMessage.Complete(KErrNotFound); + } + break; + } + + case ESensrvSrvReqCloseChannel: + case ESensrvSrvReqStartListening: + case ESensrvSrvReqStopListening: + case ESensrvSrvReqAsyncChannelData: + case ESensrvSrvReqGetProperty: + case ESensrvSrvReqSetProperty: + case ESensrvSrvReqAsyncPropertyData: + case ESensrvSrvReqStopPropertyListening: + case ESensrvSrvReqGetAllProperties: + case ESensrvSrvReqAddConditionSet: + case ESensrvSrvReqRemoveConditionSet: + case ESensrvSrvReqStartConditionListening: + case ESensrvSrvReqStopConditionListening: + case ESensrvSrvReqAsyncConditionMet: + { + // Get channel ID from message + // No need to check error value, we already made sure the message function is correct + TSensrvChannelId channelId(0); + aMessage.GetChannelId(channelId); + + // Determine which proxy handles this channel + CSensrvPluginProxy* proxy = GetProxyForChannel(channelId); + + // Dispatch the message for found proxy to be handled + if (proxy != NULL) + { + proxy->DispatchMessage(aMessage, channelId); // Transfer ownership of message + } + else + { + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::DispatchMessage - ERROR: Proxy not found" )) ); + // Complete with error + aMessage.Complete(KErrNotFound); + } + break; + } + + // Cannot identify the message + default: + { + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::DispatchMessage - ERROR: unknown command" )) ); + aMessage.Complete(KErrArgument); + break; + } + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::DispatchMessage - return" )) ); + } + + +// --------------------------------------------------------------------------- +// Generate new unique id. +// --------------------------------------------------------------------------- +// +TInt CSensrvProxyManager::GenerateUniqueId() + { + iProxyManagerMutex.Wait(); + + iIdCounter++; + + // Realistically, there will never be so many ids generated that the counter will roll over, but + // check just in case. No checking for duplicate ids, as chance of that happening is truly + // astronomical. + if (iIdCounter == KMaxTInt) + { + iIdCounter = 1; + } + + iProxyManagerMutex.Signal(); + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::GenerateUniqueId - generated new id: 0x%x" ), iIdCounter ) ); + + return iIdCounter; + } + +// --------------------------------------------------------------------------- +// Checks waitqueue and if there are queued transactions, +// checks if all proxies have constructed successfully. +// If so, starts executing queued transactions. +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::NotifyProxyInitialized() + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::NotifyProxyInitialized()") ) ); + + TInt count = iProxyList.Count(); + iAllProxiesInitialized = ETrue; + + for(TInt i=0; iIsInitialized()) + { + iAllProxiesInitialized = EFalse; + break; + } + } + + if (iAllProxiesInitialized) + { + HandleTransactionsQueryChannels(); + HandleTransactionsOpenChannel(); + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::NotifyProxyInitialized - All proxies not yet initialized") ) ); + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::NotifyProxyInitialized - return" )) ); + } + +// --------------------------------------------------------------------------- +// Duplicates source handle to destination handle. +// Source handle must be held by Server Main Thread +// --------------------------------------------------------------------------- +// +TInt CSensrvProxyManager::DuplicateMutexHandle(const RMutex& aSrc, RMutex& aDst) const + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::DuplicateMutexHandle(aSrc.Handle(): 0x%x, aDst.Handle(): 0x%x)"),aSrc.Handle(), aDst.Handle() ) ); + + aDst.SetHandle(aSrc.Handle()); + TInt err = aDst.Duplicate(iServerThread); + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::DuplicateMutexHandle - return %d" ), err) ); + + return err; + } + +// --------------------------------------------------------------------------- +// shuts down server gracefully +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::ShutdownServer(const RMessage2& aMessage) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ShutdownServer()") ) ); + + if (iShutdownMessage.Handle()) + { + // Already shutting down, complete + aMessage.Complete(KErrNone); + } + else + { + iShutdownMessage = aMessage; + ShutdownServer(); + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ShutdownServer - return" )) ); + } + +// --------------------------------------------------------------------------- +// shuts down server gracefully +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::ShutdownServer() + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ShutdownServer()") ) ); + + if (!iShutdown) + { + iShutdown = ETrue; + iShuttingDownCount = 0; + + // Cleanup proxies and solve amount of proxies to shutdown + TInt proxyCount = iProxyList.Count(); + for (TInt i = 0; i < proxyCount; i++) + { + // Set deletion flag to disable usage attempts if shutdown was requested by client. + // Othwerwise usage attempt is allowed to cancel shutdown. + if (iShutdownMessage.Handle()) + { + iProxyList[i]->SetDeletionFlag(); + } + + CSensrvPluginProxy::TPluginState pluginState = iProxyList[i]->PluginState(); + if (pluginState == CSensrvPluginProxy::EPluginStateLoaded || + pluginState == CSensrvPluginProxy::EPluginStateThreadInitializing || + pluginState == CSensrvPluginProxy::EPluginStateThreadInitialized) + { + iProxyList[i]->CleanupPlugin(); + iShuttingDownCount++; + } + else if (pluginState == CSensrvPluginProxy::EPluginStateUnloading) + { + // Plugin already unloading + iShuttingDownCount++; + } + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ShutdownServer - proxies to shutdown %d" ), + iShuttingDownCount ) ); + + // Shutdown right away, if no proxies to unload + if (!iShuttingDownCount) + { + SsyThreadTerminated(); + } + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ShutdownServer - Already shutting down" )) ); + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ShutdownServer - return" )) ); + } + +// --------------------------------------------------------------------------- +// Handles proxy thread termination +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::SsyThreadTerminated() + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::SsyThreadTerminated() shutdown status %d"), iShutdown ) ); + + if (iShutdown) + { + if (iShuttingDownCount > 0) + { + --iShuttingDownCount; + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::SsyThreadTerminated - proxies left %d "), iShuttingDownCount ) ); + } + else + { + iShuttingDownCount = 0; + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::SsyThreadTerminated - Proxies already shutdown") ) ); + } + + if (!iShuttingDownCount) + { + if (iShutdownMessage.Handle()) + { + iShutdownMessage.Complete(KErrNone); + } + if (CActiveScheduler::Current()) + { + CActiveScheduler::Stop(); + CActiveScheduler::Install(NULL); + } + } + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::SsyThreadTerminated - return" )) ); + } + +// --------------------------------------------------------------------------- +// Compares current implementation infos to new implementation infos +// and determines if new proxies need to be loaded or old ones deleted. +// --------------------------------------------------------------------------- +// +TBool CSensrvProxyManager::EcomChanged( RImplInfoPtrArray* aImplementationInfos ) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::EcomChanged()") ) ); + + TBool changes(EFalse); + TInt i(0); + TInt j(0); + TInt found(KErrNotFound); + TInt err(KErrNone); + TBool changeOk(ETrue); + + __ASSERT_ALWAYS(aImplementationInfos, User::Panic(KSensrvPanicCategory, ESensrvPanicNullImplInfos)); + + // If no array previously registered this is first registration. + if (!iSsyImplInfoArray) + { + // First registration should always have some plugins or it is considered an error, although + // there might be devices that do not have any sensors as default. Since we only trace the + // error, this is not a problem. + if (!aImplementationInfos->Count()) + { + ERROR_TRACE( ( _L("Sensor Server - CSensrvProxyManager::EcomChanged - Possible ERROR: No SSY plugins found. (This might be ok for some devices with no internal sensors)" ) ) ); + } + } + else + { + // If still loading initial plugins, do not allow new changes until initial loads have completed. + if (!iAllProxiesInitialized) + { + changeOk = EFalse; + } + } + + if (changeOk) + { + // Compare current implementation infos to new ones to find new plugins + for (i = 0; i < aImplementationInfos->Count(); i++) + { + found = KErrNotFound; + + // Skip comparisons on the first time when there is no array to compare + if (iSsyImplInfoArray) + { + for (j = 0; found == KErrNotFound && j < iSsyImplInfoArray->Count(); j++) + { + if ((*iSsyImplInfoArray)[j]->ImplementationUid() == (*aImplementationInfos)[i]->ImplementationUid()) + { + found = j; + } + } + } + + // Create and initialize new proxy + if (found == KErrNotFound) + { + changes = ETrue; + CSensrvPluginProxy* proxy = AddProxy((*aImplementationInfos)[i]->ImplementationUid()); + + if (proxy) + { + CImplementationInformation* implInfo = (*aImplementationInfos)[i]; + err = proxy->InitializeChannelData( *implInfo ); + if ( err != KErrNone ) + { + // If proxy initialization fails, it means that proxy will not provide any channels. + // Since SSY thread has not been resumed yet (resume is the last thing in InitializeL), proxy + // can be safely deleted without risk for memory leak. + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::EcomChanged - ERROR: Proxy initialization failed, error %d" ), err) ); + TInt pos( iProxyList.Find( proxy ) ); + delete proxy; + proxy = NULL; + if ( pos >= 0 && pos < iProxyList.Count() ) + { + iProxyList.Remove(pos); + } + } + // Note: New channels are notified to interested clients after they are registered. + } + } + } + + NotifyProxyInitialized(); + + // Skip the following comparisons entirely on the first time + if (iSsyImplInfoArray) + { + // Compare current implementation infos to new ones to find removed plugins + for (i = 0; i < iSsyImplInfoArray->Count(); i++) + { + found = KErrNotFound; + + for (j = 0; found == KErrNotFound && j < aImplementationInfos->Count(); j++) + { + if ((*iSsyImplInfoArray)[i]->ImplementationUid() == (*aImplementationInfos)[j]->ImplementationUid()) + { + found = j; + } + } + + // Delete obsolete proxy + if (found == KErrNotFound) + { + changes = ETrue; + + // Find proxy from proxy list + for (TInt z=0; found == KErrNotFound && z < iProxyList.Count(); z++) + { + if (iProxyList[z]->ImplementationUid() == (*iSsyImplInfoArray)[i]->ImplementationUid()) + { + // Mark proxy for deletion. + iProxyList[z]->SetDeletionFlag(); + + // Notify channel removal + for (TInt x = 0; x < iProxyList[z]->ChannelInfoList().Count(); x++) + { + NotifyChannelChange((iProxyList[z]->ChannelInfoList())[x], ESensrvChannelChangeTypeRemoved); + } + + // Clear any channels provided by proxy, so that it will not + // show up in further finds. + iProxyList[z]->ChannelInfoList().Reset(); + + // If plugin is not unloaded, it cannot be deleted without cleaning it up properly. + // Actual delete is done in ProxyCleanerCallback() in this case + if (iProxyList[z]->PluginState() == CSensrvPluginProxy::EPluginStateLoaded + || iProxyList[z]->PluginState() == CSensrvPluginProxy::EPluginStateThreadInitializing + || iProxyList[z]->PluginState() == CSensrvPluginProxy::EPluginStateThreadInitialized + || iProxyList[z]->PluginState() == CSensrvPluginProxy::EPluginStateUnloading) + { + // Cleanup plugin unless it is already unloading + if (iProxyList[z]->PluginState() != CSensrvPluginProxy::EPluginStateUnloading) + { + iProxyList[z]->CleanupPlugin(); + } + + if (!iProxyCleaner) + { + iProxyCleaner = CPeriodic::New(CActive::EPriorityStandard); + + if (iProxyCleaner) + { + iProxyCleaner->Start(TTimeIntervalMicroSeconds32( KSensrvEcomRescanTimerPeriod ), + TTimeIntervalMicroSeconds32( KSensrvEcomRescanTimerPeriod ), + TCallBack( ProxyCleanerCallback, this )); + } + else + { + // Since cleaner cannot be constructed, proxy is left alive. Since it is marked + // for deletion, it will be quite unusable, however. + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::EcomChanged - Unable to create proxy cleaner" ) ) ); + } + } + } + else + { + // Delete plugin outright, plugin is unloaded or uninitialized + delete iProxyList[z]; + iProxyList.Remove(z); + } + + found = z; + } + } + } + } + } + + // Update iSsyImplInfoArray + if (!iSsyImplInfoArray) + { + // First time always assign the array + iSsyImplInfoArray = aImplementationInfos; + } + else if (changes) + { + iSsyImplInfoArray->ResetAndDestroy(); + delete iSsyImplInfoArray; + iSsyImplInfoArray = aImplementationInfos; + } + else + { + // No changes, just destroy new infos + aImplementationInfos->ResetAndDestroy(); + delete aImplementationInfos; + } + + // If no proxies were successfully initialized, + // set initialized flag so that finds will not wait forever. + if (!iProxyList.Count()) + { + iAllProxiesInitialized = ETrue; + } + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::EcomChanged - return %d" ), changeOk) ); + + return changeOk; + } + +// --------------------------------------------------------------------------- +// Orders server to notify all interested client sessions. Notifications +// are not sent until all proxies have finished initializing to +// avoid notifications about initial plugin loads. +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::NotifyChannelChange(const TSensrvResourceChannelInfo& aChangedChannel, + TSensrvChannelChangeType aChangeType ) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::NotifyChannelChange(aChangedChannel.iChannelId: %d, aChangeType: %d)"), aChangedChannel.iChannelId, aChangeType ) ); + + if (iAllProxiesInitialized) + { + iServer.NotifyChannelChange(aChangedChannel, aChangeType); + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::NotifyChannelChange - return" )) ); + } + +// --------------------------------------------------------------------------- +// Cleans up everything related to terminated session. +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::SessionTerminated( CSensrvSession* aSession ) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::SessionTerminated(aSession: 0x%x)"),aSession ) ); + + // Cleanup any waiting transactions for this session + iWaitQueueQueryChannels->Remove(aSession); + iWaitQueueOpenChannel->Remove(aSession); + + if (iSessionCounter > 0) + { + iSessionCounter--; + } + else + { + iSessionCounter = 0; + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::SessionTerminated - Already no sessions") ) ); + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::SessionTerminated - Amount of sessions %d"), iSessionCounter ) ); + + if (!iSessionCounter) + { + // Shutdown server after timer since no more clients + iServerShutdown->Start(); + } + + // Call session cleanup on each proxy + TInt proxyCount = iProxyList.Count(); + for(TInt i = 0; i < proxyCount; i++) + { + iProxyList[i]->SessionTerminated(aSession); + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::SessionTerminated - return" )) ); + } + + +// --------------------------------------------------------------------------- +// Executes queued transactions. +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::HandleTransactionsQueryChannels() + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::HandleTransactionsQueryChannels()") ) ); + + if (iWaitQueueQueryChannels) + { + while (!iWaitQueueQueryChannels->IsEmpty()) + { + TInt err(KErrNone); + + CSensrvTransaction* transaction = iWaitQueueQueryChannels->First(); + + if (transaction->State() == CSensrvTransaction::ETransStateQueued) + { + // Read required channel information from message + TSensrvResourceChannelInfoPckgBuf pckg; + + __ASSERT_ALWAYS(transaction->Message(), User::Panic(KSensrvPanicCategory, ESensrvPanicNullMessage)); + + err = transaction->Message()->Read( KSensrvQueryChannelsQueryParametersSlot, pckg ); + if(err == KErrNone && transaction->Message()->Handle()) + { + TSensrvResourceChannelInfo queryInfo = pckg(); + const RMessage2& queryMessage(transaction->Message()->GetMessage()); + + if (LoadDynamicChannelSsysIfNeeded(queryInfo, queryMessage, EFalse)) + { + // Continue wait queue processing after the required SSYs are loaded + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::HandleTransactionsQueryChannels() - Waiting for SSYs to be loaded") ) ); + break; + } + + transaction->SetState(CSensrvTransaction::ETransStateExecuting); + + // Go through all proxies and add matches to return array. + RSensrvChannelInfoList matchingInfos; + TInt proxyCount = iProxyList.Count(); + for (TInt i = 0; i < proxyCount; ++i) + { + CSensrvPluginProxy* proxy = iProxyList[i]; + TInt channelCount = proxy->ChannelInfoList().Count(); + for (TInt j = 0; j < channelCount; ++j) + { + const TSensrvResourceChannelInfo& info(proxy->ChannelInfoList()[j]); + if (info.IsMatch(queryInfo, queryMessage)) + { + err = matchingInfos.Append(info); + if (err != KErrNone) + { + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::HandleTransactionsQueryChannels - ERROR: Append of matching info failed, error %d" ), err) ); + break; + } + } + } + } +#ifdef COMPONENT_TRACE_DEBUG + COMPONENT_TRACE( ( _L( "### Found channels:" )) ); + TraceChannelInfoList(matchingInfos); +#endif + if (err == KErrNone) + { + // Write found infos to message + err = transaction->SetMessageData(&matchingInfos); + } + + matchingInfos.Reset(); + } + else + { + transaction->SetState(CSensrvTransaction::ETransStateExecuting); + } + + if (err != KErrNone) + { + transaction->SetErrorCode(err); + } + + // Complete transaction + iWaitQueueQueryChannels->Remove(transaction, CSensrvTransactionQueue::ERemovalTypeComplete); + transaction = NULL; + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::HandleTransactionsQueryChannels - Transaction already executing, do nothing." )) ); + } + } // end while + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::HandleTransactionsQueryChannels - return" )) ); + } + +// --------------------------------------------------------------------------- +// Executes queued transactions. +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::HandleTransactionsOpenChannel() + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::HandleTransactions()") ) ); + + if (iWaitQueueOpenChannel) + { + while (!iWaitQueueOpenChannel->IsEmpty()) + { + TInt err(KErrNone); + + CSensrvTransaction* transaction = iWaitQueueOpenChannel->First(); + + if (transaction->State() == CSensrvTransaction::ETransStateQueued) + { + transaction->SetState(CSensrvTransaction::ETransStateExecuting); + + __ASSERT_ALWAYS(transaction->Message(), User::Panic(KSensrvPanicCategory, ESensrvPanicNullMessage)); + + // Get channel ID from message + // No need to check error value, we already made sure the message function is correct + TSensrvChannelId channelId(0); + err = transaction->Message()->GetChannelId(channelId); + + if(err == KErrNone) + { + + // Determine which proxy handles this channel + CSensrvPluginProxy* proxy = GetProxyForChannel(channelId); + + if( proxy != NULL && + ( proxy->PluginState() == CSensrvPluginProxy::EPluginStateUnloaded || + proxy->PluginState() == CSensrvPluginProxy::EPluginStateUninitialized ) ) + { + TRAPD(err, proxy->InitializePluginL()); + if ( err != KErrNone ) + { + // If proxy initialization fails, it means that proxy will not provide any channels. + // Since SSY thread has not been resumed yet (resume is the last thing in InitializeL), proxy + // can be safely deleted without risk for memory leak. + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::EcomChanged - ERROR: Proxy initialization failed, error %d" ), err) ); + TInt pos( iProxyList.Find( proxy ) ); + delete proxy; + proxy = NULL; + if ( pos >= 0 && pos < iProxyList.Count() ) + { + iProxyList.Remove(pos); + } + } + } + + // Dispatch the message for found proxy to be handled + if (proxy != NULL) + { + proxy->DispatchMessage(*transaction->Message(), channelId); // Transfer ownership of message + } + } + else + { + transaction->SetErrorCode(err); + } + // Complete transaction + iWaitQueueOpenChannel->Remove(transaction, CSensrvTransactionQueue::ERemovalTypeComplete); + transaction = NULL; + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::HandleTransactions - Transaction already executing, do nothing." )) ); + } + } // end while + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::HandleTransactions - return" )) ); + } + +// --------------------------------------------------------------------------- +// Checks all channels provided by proxies and returns information matching +// the query parameters. +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::QueryChannels(CSensrvMessage& aMessage) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::QueryChannels(aMessage: 0x%x, )" ), &aMessage ) ); + + // Create transaction + CSensrvTransaction* queryTransaction = NULL; + TRAPD(err, queryTransaction = CSensrvTransaction::NewL( + &aMessage, + NULL, + NULL, + CSensrvTransaction::ETransTypeClientQueryChannels)); + + if (err == KErrNone) + { + // queue transaction + queryTransaction->SetState(CSensrvTransaction::ETransStateQueued); + + err = iWaitQueueQueryChannels->Add(queryTransaction); + + if (err == KErrNone) + { + // Execute transaction if all proxies initialized + if (iAllProxiesInitialized) + { + HandleTransactionsQueryChannels(); + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::QueryChannels - All proxies not yet initialized") ) ); + } + } + else + { + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::QueryChannels - ERROR: Transaction adding to queue failed" )) ); + } + } + else + { + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::QueryChannels - ERROR: Transaction creation failed" )) ); + } + + // Handle error + if (err != KErrNone) + { + if(queryTransaction) + { + queryTransaction->SetErrorCode(err); + queryTransaction->Complete(); + delete queryTransaction; + queryTransaction = NULL; + } + else + { + // Do nothing, message gets deleted and completed with KErrGeneral on transaction desctructor. + } + } + + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::QueryChannels - return" )) ); + } + +// --------------------------------------------------------------------------- +// Checks all channels provided by proxies and returns information matching +// the query parameters. +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::OpenChannel(CSensrvMessage& aMessage) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::QueryChannels(aMessage: 0x%x, )" ), &aMessage ) ); + + // Create transaction + CSensrvTransaction* queryTransaction = NULL; + TRAPD(err, queryTransaction = CSensrvTransaction::NewL( + &aMessage, + NULL, + NULL, + CSensrvTransaction::ETransTypeOpenChannel)); + + if (err == KErrNone) + { + // queue transaction + queryTransaction->SetState(CSensrvTransaction::ETransStateQueued); + + err = iWaitQueueOpenChannel->Add(queryTransaction); + + if (err == KErrNone) + { + // Execute transaction if all proxies initialized + if (iAllProxiesInitialized) + { + HandleTransactionsOpenChannel(); + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::QueryChannels - All proxies not yet initialized") ) ); + } + } + else + { + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::QueryChannels - ERROR: Transaction adding to queue failed" )) ); + } + } + else + { + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::QueryChannels - ERROR: Transaction creation failed" )) ); + } + + // Handle error + if (err != KErrNone) + { + if(queryTransaction) + { + queryTransaction->SetErrorCode(err); + queryTransaction->Complete(); + delete queryTransaction; + queryTransaction = NULL; + } + else + { + // Do nothing, message gets deleted and completed with KErrGeneral on transaction desctructor. + } + } + + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::QueryChannels - return" )) ); + } + +// --------------------------------------------------------------------------- +// Gets the proxy that handles the specified channel. +// NULL is returned if channel is not found. +// --------------------------------------------------------------------------- +// +CSensrvPluginProxy* CSensrvProxyManager::GetProxyForChannel(TSensrvChannelId aChannelId) const + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::GetProxyForChannel(aChannelId: %d)" ), aChannelId ) ); + + CSensrvPluginProxy* returnProxy = NULL; + + TInt proxyCount = iProxyList.Count(); + for(TInt i = 0; !returnProxy && i < proxyCount; i++) + { + if (iProxyList[i]->IsChannelSupported(aChannelId)) + { + returnProxy = iProxyList[i]; + } + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::GetProxyForChannel - return 0x%x" ), returnProxy) ); + + return returnProxy; + } + +// --------------------------------------------------------------------------- +// Fetches configurable settings from cenrep +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::GetSettings() + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetSettings()" ) ) ); + + TInt err(KErrNone); + + // Open settings repository and get necessary values + CRepository* repository = NULL; + TRAP( err, repository = CRepository::NewL(KCRUidSensorServerSettings) ); + + if ( err == KErrNone ) + { + TInt value(0); + err = repository->Get(KSensrvTransactionTimeoutKey, value); + if ( err == KErrNone ) + { + if ( value > 0 ) + { + iTransactionTimeout = value*KSecondsToMicros; + } + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - KSensrvTransactionTimeoutKey value getting failed: %d, using default value." ), err) ); + } + + err = repository->Get(KSensrvSsyThreadStackSizeKey, value); + if ( err == KErrNone ) + { + if ( value > 0 ) + { + iSsyStackSize = value; + } + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - KSensrvSsyThreadStackSizeKey value getting failed: %d, using default value." ), err) ); + } + + err = repository->Get(KSensrvSsyThreadHeapMaxSizeKey, value); + if ( err == KErrNone ) + { +#ifdef __WINS__ + value *= KSensrvSsyMaxHeapWinsMultiplier; +#endif // __WINS__ + if ( value < KSensrvSsyHeapInitialSize ) + { + iSsyHeapMaxSize = KSensrvSsyHeapInitialSize; + } + else if (value > 0) + { + iSsyHeapMaxSize = value; + } + else + { + // Do nothing, default is used + } + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - KSensrvSsyThreadHeapMaxSizeKey value getting failed: %d, using default value." ), err) ); + } + + err = repository->Get(KSensrvThreadTerminationPeriodKey, value); + if ( err == KErrNone ) + { + if ( value > 0 ) + { + iThreadTerminationGracePeriod = value*KSecondsToMicros; + } + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - KSensrvThreadTerminationPeriodKey value getting failed: %d, using default value." ), err) ); + } + + err = repository->Get(KSensrvSsyInactivityPeriodKey, value); + if ( err == KErrNone ) + { + if ( value > 0 ) + { + iSsyInactivityPeriod = value*KSecondsToMicros; + } + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - KSensrvSsyInactivityPeriodKey value getting failed: %d, using default value." ), err) ); + } + + err = repository->Get(KSensrvBufferSizeMultiplierKey, value); + if ( err == KErrNone ) + { + if ( value > 0 ) + { + iBufferSizeMultiplier = value; + } + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - KSensrvBufferSizeMultiplierKey value getting failed: %d, using default value." ), err) ); + } + err = repository->Get(KSensrvTerminationPeriodKey, value); + if ( err == KErrNone ) + { + if ( value >= 0 ) + { + iTerminationPeriod = value*KSecondsToMicros; + } + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - KSensrvTerminationPeriodKey value getting failed: %d, using default value." ), err) ); + } + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - Settings repository opening failed: %d" ), err) ); + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - iTransactionTimeout: %d" ), iTransactionTimeout.Int()) ); + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - iSsyStackSize: %d" ), iSsyStackSize) ); + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - iSsyHeapMaxSize: %d" ), iSsyHeapMaxSize) ); + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - iThreadTerminationGracePeriod: %d" ), iThreadTerminationGracePeriod.Int()) ); + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - iSsyInactivityPeriod: %d" ), iSsyInactivityPeriod.Int()) ); + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvServer::GetSettings - iBufferSizeMultiplier: %d" ), iBufferSizeMultiplier) ); + + // Cleanup repository + delete repository; + repository = NULL; + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetSettings - return" ) ) ); + } + +// --------------------------------------------------------------------------- +// Create new proxy and add it to proxy list +// --------------------------------------------------------------------------- +// +CSensrvPluginProxy* CSensrvProxyManager::AddProxy(const TUid& aProxyUid) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::AddProxy(0x%x)" ), aProxyUid.iUid ) ); + + // Create proxy + TInt err(KErrNone); + CSensrvPluginProxy* proxy = NULL; + TRAP(err, proxy = CSensrvPluginProxy::NewL(*this,aProxyUid)); + + if ( err != KErrNone ) + { + // Error loading a plugin is not critical, it just means + // that channels provided by plugin are unavailable. + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::AddProxy - ERROR: creating proxy failed, implementationUid: 0x%x, error: %d" ), aProxyUid.iUid , err ) ); + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::AddProxy - Proxy for implementation 0x%x created successfully." ), aProxyUid.iUid ) ); + + // Add proxy to list + err = iProxyList.Append(proxy); + if ( err != KErrNone ) + { + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::AddProxy - ERROR: Saving plugin info failed, implementationUid: 0x%x, error %d" ), aProxyUid.iUid , err) ); + delete proxy; + proxy = NULL; + } + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::AddProxy - return 0x%x" ), proxy ) ); + + return proxy; + } + +// --------------------------------------------------------------------------- +// CSensrvProxyManager::ProxyCleanerCallback +// --------------------------------------------------------------------------- +// +TInt CSensrvProxyManager::ProxyCleanerCallback( TAny* aObject ) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ProxyCleanerCallback(this)" ) ) ); + + __ASSERT_ALWAYS(aObject, User::Panic(KSensrvPanicCategory, ESensrvPanicNullCallback)); + + CSensrvProxyManager* manager = reinterpret_cast( aObject ); + TBool noMore(ETrue); + + for (TInt z = manager->iProxyList.Count() - 1; z >= 0; z--) + { + if (manager->iProxyList[z]->IsMarkedForDeletion()) + { + if (manager->iProxyList[z]->PluginState() == CSensrvPluginProxy::EPluginStateLoaded + || manager->iProxyList[z]->PluginState() == CSensrvPluginProxy::EPluginStateThreadInitializing + || manager->iProxyList[z]->PluginState() == CSensrvPluginProxy::EPluginStateThreadInitialized + || manager->iProxyList[z]->PluginState() == CSensrvPluginProxy::EPluginStateUnloading) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ProxyCleanerCallback - Proxy still not unloaded, try deletion again later" ) ) ); + noMore = EFalse; + } + else + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ProxyCleanerCallback - Proxy unloaded, deleting..." ) ) ); + delete manager->iProxyList[z]; + manager->iProxyList.Remove(z); + } + } + } + + // Delete iProxyCleaner if no more + if (noMore) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ProxyCleanerCallback - No more proxies to unload, deleting cleaner..." ) ) ); + delete manager->iProxyCleaner; + manager->iProxyCleaner = NULL; + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::ProxyCleanerCallback - return " ) ) ); + + return KErrNone; + } + +#ifdef COMPONENT_TRACE_DEBUG +// --------------------------------------------------------------------------- +// Traces channel info list contents +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::TraceChannelInfoList(const RSensrvResourceChannelInfoList& aInfoList) + { + // Debug found channels + if (aInfoList.Count()) + { + for(TInt z = 0; z < aInfoList.Count(); z++) + { + // Convert location and vendorID from 8bit to 16 bit for proper printing + TInt len = aInfoList[z].iVendorId.Length(); + HBufC16* vidBuf16 = HBufC16::New(len); + if( vidBuf16 ) + { + vidBuf16->Des().Copy(aInfoList[z].iVendorId); + } + + len = aInfoList[z].iLocation.Length(); + HBufC16* locBuf16 = HBufC16::New(len); + if( locBuf16 ) + { + locBuf16->Des().Copy(aInfoList[z].iLocation); + } + COMPONENT_TRACE( ( _L( "### Info %d: iChannelId: %d, iContextType: 0x%x, iQuantity: 0x%x, iChannelType: 0x%x, iLocation: \"%S\", iVendorId: \"%S\", iDataItemSize: %d " ), + z, + aInfoList[z].iChannelId, + aInfoList[z].iContextType, + aInfoList[z].iQuantity, + aInfoList[z].iChannelType, + locBuf16 ? locBuf16 : &KSensrvNullString, + vidBuf16 ? vidBuf16 : &KSensrvNullString, + aInfoList[z].iDataItemSize) ); + if( locBuf16 ) + delete locBuf16; + if( vidBuf16 ) + delete vidBuf16; + } + } + else + { + COMPONENT_TRACE( ( _L( "### List is empty." ) )); + } + } + +// --------------------------------------------------------------------------- +// Traces channel info list contents +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::TraceChannelInfoList(const RSensrvChannelInfoList& aInfoList) + { + // Debug found channels + if (aInfoList.Count()) + { + for(TInt z = 0; z < aInfoList.Count(); z++) + { + // Convert location and vendorID from 8bit to 16 bit for proper printing + TInt len = aInfoList[z].iVendorId.Length(); + HBufC16* vidBuf16 = HBufC16::New(len); + if( vidBuf16 ) + { + vidBuf16->Des().Copy(aInfoList[z].iVendorId); + } + + len = aInfoList[z].iLocation.Length(); + HBufC16* locBuf16 = HBufC16::New(len); + if( locBuf16 ) + { + locBuf16->Des().Copy(aInfoList[z].iLocation); + } + + COMPONENT_TRACE( ( _L( "### Info %d: iChannelId: %d, iContextType: 0x%x, iQuantity: 0x%x, iChannelType: 0x%x, iLocation: \"%S\", iVendorId: \"%S\", iDataItemSize: %d " ), + z, + aInfoList[z].iChannelId, + aInfoList[z].iContextType, + aInfoList[z].iQuantity, + aInfoList[z].iChannelType, + locBuf16 ? locBuf16 : &KSensrvNullString, + vidBuf16 ? vidBuf16 : &KSensrvNullString, + aInfoList[z].iDataItemSize) ); + if( locBuf16 ) + delete locBuf16; + if( vidBuf16 ) + delete vidBuf16; + + } + } + else + { + COMPONENT_TRACE( ( _L( "### List is empty." ) )); + } + } +#endif + +// --------------------------------------------------------------------------- +// Cleanup item implementation for plugin initialization +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::AddSession() + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::AddSession" ) ) ); + + if ( iServerShutdown->IsActive( ) ) + { + iServerShutdown->Cancel(); + } + iSessionCounter++; + + // Cancel shutdown if it was not requested by client + if ( !iShutdownMessage.Handle() ) + { + iShutdown = EFalse; + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::AddSession sessions: %d - return" ), iSessionCounter ) ); + } + +// --------------------------------------------------------------------------- +// Loads the dynamic channel SSYs that matches to given query if not loaded +// --------------------------------------------------------------------------- +// +TBool CSensrvProxyManager::LoadDynamicChannelSsysIfNeeded(const TSensrvResourceChannelInfo& aQueryInfo, + const RMessage2& aQueryMessage, + TBool aAddChannelChangeListener) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::LoadDynamicChannelSsysIfNeeded" ) ) ); + TBool ssyLoadPending = EFalse; + TInt proxyCount = iProxyList.Count(); + for (TInt i = 0; i < proxyCount; ++i) + { + CSensrvPluginProxy* proxy = iProxyList[i]; + TInt channelCount = proxy->DynamicChannelInfoList().Count(); + for (TInt j = 0; j < channelCount; ++j) + { + if (proxy->DynamicChannelInfoList()[j].IsMatch(aQueryInfo, aQueryMessage)) + { + CSensrvPluginProxy::TPluginState pluginState = proxy->PluginState(); + if (pluginState == CSensrvPluginProxy::EPluginStateUninitialized || + pluginState == CSensrvPluginProxy::EPluginStateUnloaded || + pluginState == CSensrvPluginProxy::EPluginStateUnloading) + { + if (!proxy->PreviousSsyLoadFailed()) // If loading failed earlier, ignore new attempt to avoid query deadlocks + { + TRAPD(err, proxy->InitializePluginL()); + if (err == KErrNone) + { + ssyLoadPending = ETrue; + } + else + { + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::LoadDynamicChannelSsysIfNeeded - ERROR: SSY 0x%x initialization failed, error %d" ), + proxy->ImplementationUid().iUid, err ) ); + } + } + else + { + ERROR_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::LoadDynamicChannelSsysIfNeeded - Ignoring SSY 0x%x initialization" ), + proxy->ImplementationUid().iUid ) ); + } + } + else if (pluginState == CSensrvPluginProxy::EPluginStateThreadInitializing) + { + ssyLoadPending = ETrue; + } + if (aAddChannelChangeListener) + { + proxy->AddChannelChangeListener(); + } + break; // Move on to next proxy + } + } + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::LoadDynamicChannelSsysIfNeeded - return %d" ), ssyLoadPending ) ); + return ssyLoadPending; + } + +// --------------------------------------------------------------------------- +// Removes channel change listener from the matching dynamic channel SSYs to allow unloading +// --------------------------------------------------------------------------- +// +void CSensrvProxyManager::RemoveChannelChangeListenerFromDynamicChannelSsys(const TSensrvResourceChannelInfo& aQueryInfo, + const RMessage2& aQueryMessage) + { + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::RemoveChannelChangeListenerFromDynamicChannelSsys" ) ) ); + + TInt proxyCount = iProxyList.Count(); + for(TInt i = 0; i < proxyCount; ++i) + { + CSensrvPluginProxy* proxy = iProxyList[i]; + TInt channelCount = proxy->DynamicChannelInfoList().Count(); + for(TInt j = 0; j < channelCount; ++j) + { + if (proxy->DynamicChannelInfoList()[j].IsMatch(aQueryInfo, aQueryMessage)) + { + proxy->RemoveChannelChangeListener(); + break; // Move on to next proxy + } + } + } + + COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvProxyManager::RemoveChannelChangeListenerFromDynamicChannelSsys - return" ) ) ); + } + +// End of file