--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sensorservices/sensorserver/src/server/sensrvchannel.cpp Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,2334 @@
+/*
+* 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 channel implementation
+*
+*/
+
+
+
+#include <centralrepository.h>
+#include "sensrvdefines.h"
+#include "senserverchannel.h"
+#include "sensrvchannelbuffer.h"
+#include "sensrvtransaction.h"
+#include "sensrvclientserver.h"
+#include "sensrvpluginproxy.h"
+#include "sensrvtransactionqueue.h"
+#include "sensrvssymediator.h"
+#include "sensrvsession.h"
+#include "sensrvchannellistener.h"
+#include "sensrvservermediator.h"
+#include "sensrvtransactionmonitor.h"
+#include "sensrvproxymanager.h"
+#include "sensrvpropertyqueue.h"
+#include "sensrvconditionevaluator.h"
+#include "sensrvprivatecrkeys.h"
+
+// ---------------------------------------------------------------------------
+// 2-phase constructor
+// ---------------------------------------------------------------------------
+//
+CSensrvChannel* CSensrvChannel::NewL( const TSensrvResourceChannelInfo& aInfo,
+ CSensrvPluginProxy& aProxy )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::NewL(aInfo.iChannelId: %d, aProxy: 0x%x)" ), aInfo.iChannelId, aProxy.ImplementationUid().iUid ) );
+
+ CSensrvChannel* self = new( ELeave ) CSensrvChannel( aInfo, aProxy );
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::NewL - return 0x%x" ), self ) );
+
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// C++ constructor
+// ---------------------------------------------------------------------------
+//
+CSensrvChannel::CSensrvChannel( const TSensrvChannelInfo& aInfo,
+ CSensrvPluginProxy& aProxy )
+ : iId( aInfo.iChannelId ),
+ iState( EChannelStateClosed ),
+ iProxy( aProxy ),
+ iChannelInfo( aInfo ),
+ iHighestListenerPriority( KMinTInt )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::CSensrvChannel()" ) ) );
+
+ // Nothing to do
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::CSensrvChannel - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// 2nd phase of construction
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::ConstructL()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ConstructL()" ) ) );
+
+ iChannelQueue = CSensrvTransactionQueue::NewL( ETrue );
+
+ iChannelInfo.iChannelGroup = TSensrvResourceChannelInfo::ESensrvChannelGroupNotSolved;
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ConstructL - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CSensrvChannel::~CSensrvChannel()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::~CSensrvChannel()" ) ) );
+
+ TInt count( iListenerList.Count() );
+ for ( TInt i=0; i < count; i++ )
+ {
+ delete iListenerList[ i ];
+ }
+
+ iListenerList.Reset();
+
+ // Remove the first transactions in channel queue from mediator queues and
+ // transaction monitor, too. Rest of the queued transactions cannot be
+ // queued anywhere else, so no need to check them.
+ CSensrvTransaction* firstTransaction = NULL;
+ if ( iChannelQueue )
+ {
+ firstTransaction = iChannelQueue->First();
+ }
+
+ if ( iProxy.ServerMediator() )
+ {
+ iProxy.ServerMediator()->RemoveSingleTransaction( firstTransaction );
+ }
+ if ( iProxy.SsyMediator() )
+ {
+ iProxy.SsyMediator()->RemoveSingleTransaction( firstTransaction );
+ }
+ if ( iProxy.TransactionMonitor() )
+ {
+ iProxy.TransactionMonitor()->RemoveTransaction( firstTransaction );
+ }
+
+ delete iChannelQueue;
+ delete iChannelBuffer;
+ delete iDataAvailableTransaction;
+ delete iForceBufferFilledTransaction;
+ delete iForceChannelCloseTransaction;
+ delete iPropertyChangedTransaction;
+ delete iConditionEvaluator;
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::~CSensrvChannel - return" ) ) );
+ }
+
+
+// -----------------------------------------------------------------------------
+// Handles message according to message type
+// -----------------------------------------------------------------------------
+//
+void CSensrvChannel::DispatchMessage( CSensrvMessage& aMessage )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::DispatchMessage(aMessage.Function(): %d)" ), aMessage.Function() ) );
+
+ TInt err( KErrNone );
+ CSensrvTransaction* transaction = NULL;
+ CSensrvTransaction::TSensrvTransactionType transType( CSensrvTransaction::ETransTypeNone );
+
+ // Check command code and call appropriate function
+ switch ( aMessage.Function() )
+ {
+ case ESensrvSrvReqOpenChannel:
+ {
+ transType = CSensrvTransaction::ETransTypeOpenChannel ;
+ break;
+ }
+
+ case ESensrvSrvReqCloseChannel:
+ {
+ transType = CSensrvTransaction::ETransTypeCloseChannel ;
+ break;
+ }
+
+ case ESensrvSrvReqStartListening:
+ {
+ transType = CSensrvTransaction::ETransTypeStartListening ;
+ break;
+ }
+
+ case ESensrvSrvReqStopListening:
+ {
+ transType = CSensrvTransaction::ETransTypeStopListening ;
+ break;
+ }
+
+ case ESensrvSrvReqAsyncChannelData:
+ case ESensrvSrvReqAsyncPropertyData:
+ case ESensrvSrvReqStopPropertyListening:
+ case ESensrvSrvReqAddConditionSet:
+ case ESensrvSrvReqRemoveConditionSet:
+ case ESensrvSrvReqAsyncConditionMet:
+ {
+ // Get correct listener and pass message there
+ CSensrvChannelListener* listener = GetListener( aMessage.Session() );
+
+ if ( listener )
+ {
+ listener->DispatchMessage( aMessage );
+ }
+ else
+ {
+ err = KErrNotFound;
+ aMessage.Complete( err );
+ }
+
+ break;
+ }
+
+ case ESensrvSrvReqGetProperty:
+ {
+ transType = CSensrvTransaction::ETransTypeGetProperty ;
+ break;
+ }
+
+ case ESensrvSrvReqSetProperty:
+ {
+ transType = CSensrvTransaction::ETransTypeSetProperty ;
+ break;
+ }
+
+ case ESensrvSrvReqGetAllProperties:
+ {
+ transType = CSensrvTransaction::ETransTypeGetAllProperties ;
+ break;
+ }
+
+ case ESensrvSrvReqStartConditionListening:
+ {
+ transType = CSensrvTransaction::ETransTypeStartConditionListening ;
+ break;
+ }
+
+ case ESensrvSrvReqStopConditionListening:
+ {
+ transType = CSensrvTransaction::ETransTypeStopConditionListening ;
+ break;
+ }
+
+ // Cannot identify the message
+ default:
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::DispatchMessage - ERROR: unknown command" )) );
+ aMessage.Complete( KErrArgument );
+ break;
+ }
+ }
+ //Construct Transaction
+ if( transType != CSensrvTransaction::ETransTypeNone )
+ {
+ TRAP( err, transaction = CSensrvTransaction::NewL(
+ &aMessage,
+ &iProxy,
+ this,
+ transType) );
+
+ // Queue transaction
+ if ( transaction && err == KErrNone )
+ {
+ transaction->SetState( CSensrvTransaction::ETransStateQueued );
+ err = iChannelQueue->Add( transaction );
+ }
+ }
+ // Handle error
+ if ( err != KErrNone )
+ {
+ if ( transaction )
+ {
+ transaction->SetErrorCode( err );
+ transaction->Complete();
+ delete transaction;
+ transaction = NULL;
+ }
+ else
+ {
+ // Do nothing, message gets deleted and completed with error
+ // on transaction cleanup in cases where transaction creation failed.
+ }
+ }
+ else
+ {
+ HandleNextTransaction();
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::DispatchMessage - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Channel opened by SSY, check that providers are correctly set and
+// complete the transaction.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::ChannelOpened(TInt aErrorCode,
+ MSsyChannelDataProvider* aDataProvider,
+ MSsyPropertyProvider* aSensorPropertyProvider)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ChannelOpened(aErrorCode: %d)" ), aErrorCode ) );
+
+ TInt err( aErrorCode );
+ TInt propErr( KErrNone );
+
+ // If no error, set state to open, if not supported, need to solve dependent channels later
+ if ( err == KErrNone || err == KErrNotSupported )
+ {
+ __ASSERT_ALWAYS( aDataProvider && aSensorPropertyProvider,
+ User::Panic( KSensrvPanicCategory, ESensrvPanicNullProvider ) );
+ iDataProvider = aDataProvider;
+ iPropertyProvider = aSensorPropertyProvider;
+
+ // Get data rate for determining maximum buffering count
+ TSensrvProperty property( KSensrvPropIdDataRate, KSensrvItemIndexNone, 0 );
+ TRAP(propErr, iPropertyProvider->GetPropertyL( iId, property ) );
+
+ if ( propErr == KErrNone )
+ {
+ TInt maxRate( 0 );
+
+ if ( ESensrvArrayPropertyInfo == property.GetArrayIndex() )
+ {
+ //Array property
+ TInt maxValueIndex( 0 );
+ property.GetMaxValue( maxValueIndex );
+ property.SetItemIndex( KSensrvItemIndexNone ); //Initialize
+ property.SetArrayIndex( maxValueIndex ); //Set array index for filter criteria
+
+ TRAP( propErr, iPropertyProvider->GetPropertyL( iId, property ) );
+ property.GetValue( maxRate );
+ }
+ else
+ {
+ property.GetMaxValue( maxRate );
+ }
+
+ if ( propErr == KErrNone )
+ {
+ iMaxBufferingCount = iProxy.ProxyManager().BufferSizeMultiplier()
+ * maxRate
+ / KSensrvDataBufferLengthMultiplier;
+
+ // Very small buffers still need buffering count of at least one
+ if ( iMaxBufferingCount < KSensrvMinimumBufferingCount )
+ {
+ iMaxBufferingCount = KSensrvMinimumBufferingCount;
+ }
+ }
+ else
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::ChannelOpened - ERROR: Unable to get maximum data rate from array, using default buffer max size. Error: %d" ), propErr ) );
+ iMaxBufferingCount = KSensrvDefaultMaxBufferingCount;
+ }
+ }
+ else
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::ChannelOpened - ERROR: Unable to get maximum data rate, using default buffer max size. Error: %d" ), propErr ) );
+ iMaxBufferingCount = KSensrvDefaultMaxBufferingCount;
+ }
+
+ iState = EChannelStateOpen;
+ }
+
+ CSensrvTransaction* transaction = iChannelQueue->First();
+
+ // Unexpected callbacks from SSY mean that executing transaction has been cleaned,
+ // so we should not set the error code or notify server mediator
+ if ( transaction
+ && transaction->Type() == CSensrvTransaction::ETransTypeOpenChannel
+ && transaction->State() == CSensrvTransaction::ETransStateHandledAtSsy )
+ {
+ if ( err != KErrNone && err != KErrNotSupported )
+ {
+ transaction->SetErrorCode( err );
+ }
+
+ // Notify server thread that transaction is complete
+ // Error can be ignored, since we are at SSY thread
+ iProxy.ServerMediator()->Notify( transaction );
+ }
+ else
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ChannelOpened - Transaction cleaned already" ) ) );
+ }
+
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ChannelOpened - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Channel closed by SSY. Cleanup channel and complete the transaction.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::ChannelClosed()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ChannelClosed()" ) ) );
+
+ iState = EChannelStateClosed;
+
+ CSensrvTransaction* transaction = iChannelQueue->First();
+
+ // Unexpected callbacks from SSY mean transaction has been cleaned, so we should not
+ // notify server mediator
+ if ( transaction
+ && transaction->Type() == CSensrvTransaction::ETransTypeCloseChannel
+ && transaction->State() == CSensrvTransaction::ETransStateHandledAtSsy )
+ {
+ // Notify server thread that transaction is complete
+ // Error can be ignored, since we are at SSY thread
+ iProxy.ServerMediator()->Notify( transaction );
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ChannelClosed - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Availability has changed. Handle it.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::HandleAvailabilityChange( const TSensrvProperty& aProperty )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleAvailabilityChange()" ) ) );
+
+ TInt propValue;
+
+ aProperty.GetValue( propValue );
+
+ HandleAvailabilityChange( static_cast<TSensrvAvailability>( propValue ) );
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleAvailabilityChange - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Availability has changed. Handle it.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::HandleAvailabilityChange( const TSensrvAvailability& value )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleAvailabilityChange()" ) ) );
+
+ switch( value )
+ {
+ // Channel level transactions handled here
+ case ESensrvAvailabilityFalse:
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleAvailabilityChange - Availability changed to ESensrvAvailabilityFalse" ) ) );
+ SetChannelUnavailable();
+ break;
+
+ case ESensrvAvailabilityTrue:
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleAvailabilityChange - Availability changed to ESensrvAvailabilityTrue" ) ) );
+ SetChannelAvailable();
+ break;
+
+ default:
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleAvailabilityChange - Incorrect value received for Availability, Value ignored" ) ) );
+ break;
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleAvailabilityChange - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Availability has changed. Handle it.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::SetChannelAvailable( )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetChannelAvailable()" ) ) );
+ //start channel data
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetChannelAvailable - return" ) ) );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Availability has changed. Handle it.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::SetChannelUnavailable( )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetChannelUnavailable()" ) ) );
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetChannelUnavailable - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Property has changed. Store changed property to property queue.
+// ---------------------------------------------------------------------------
+//
+TBool CSensrvChannel::StoreChangedProperty( const TSensrvProperty& aProperty,
+ const CSensrvSession* aIgnoreSession )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::StoreChangedProperty(aProperty.GetPropertyId() 0x%x, aIgnoreSession: 0x%x)" ), aProperty.GetPropertyId(), aIgnoreSession ) );
+
+ TBool retval( EFalse );
+ TInt propertyId = aProperty.GetPropertyId();
+
+ if ( ( propertyId == KSensrvPropIdAvailability ) )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::StoreChangedProperty - server property changed: %d" ), propertyId ) );
+
+ HandleAvailabilityChange( aProperty );
+ }
+
+ TInt i( iListenerList.Count() );
+ TInt err( KErrNone );
+
+ for (i--; i >= 0; i--)
+ {
+ if ( &( iListenerList[ i ]->Session()) != aIgnoreSession )
+ {
+ err = iListenerList[ i ]->StoreChangedProperty( aProperty );
+
+ if ( err != KErrNone )
+ {
+ // Probably OOM. Not critical to lose property change notification.
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::StoreChangedProperty - ERROR: Error while adding property change to listener queue: %d" ), err ) );
+ }
+ else
+ {
+ retval = ETrue;
+ }
+ }
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::StoreChangedProperty - return: %d" ), retval ) );
+
+ return retval;
+ }
+
+// ---------------------------------------------------------------------------
+// Handles transaction finalization and completes transaction on channels's queue.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::CompleteTransaction( CSensrvTransaction* aTransaction )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::CompleteTransaction(aTransaction: 0x%x)" ), aTransaction ) );
+
+ __ASSERT_ALWAYS( aTransaction, User::Panic( KSensrvPanicCategory, ESensrvPanicNullTransaction ) );
+
+ TInt err = aTransaction->ErrorCode();
+
+ switch( aTransaction->Type() )
+ {
+ // Channel level transactions handled here
+ case CSensrvTransaction::ETransTypeOpenChannel:
+ {
+ // If opening failed at SSY, no need to create buffer
+ if ( iState != EChannelStateClosed )
+ {
+ if ( !iChannelBuffer )
+ {
+ TRAP( err, iChannelBuffer =
+ CSensrvChannelBuffer::NewL( iChannelInfo.iDataItemSize,
+ iMaxBufferingCount * KSensrvDataBufferLengthMultiplier ) )
+
+ if ( err == KErrNone)
+ {
+ // Write maximum buffering count and data item size to message
+ CSensrvTransaction::TChannelOpenMessageData data( iMaxBufferingCount, iChannelInfo.iDataItemSize );
+ err = aTransaction->SetMessageData( &data );
+ }
+ else
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::CompleteTransaction - ERROR: Buffer creation failed: %d" ), err ) );
+ }
+ }
+ }
+
+ if ( err == KErrNone )
+ {
+ // Update indicator values on open and notify changes to clients
+
+ HandleDependencyOnOpen();
+
+ HandleSetPropertySuccessIndOnCreateOrDelete();
+ }
+ else
+ {
+ // If there was error, delete the listener
+ aTransaction->SetErrorCode(err);
+ DeleteListener( aTransaction->Session() );
+ CloseIfNeeded();
+ }
+ }
+ break;
+
+ case CSensrvTransaction::ETransTypeCloseChannel:
+ {
+ // If an error occurred, channel was left open, so only delete buffer
+ // and condition evaluator if channel state is closed.
+ if ( iState == EChannelStateClosed )
+ {
+ delete iChannelBuffer;
+ iChannelBuffer = NULL;
+
+ delete iConditionEvaluator;
+ iConditionEvaluator = NULL;
+ }
+
+ // Client listener is already deleted successfully, so report ok to client
+ // even if there was an error.
+ aTransaction->SetErrorCode( KErrNone );
+ }
+ break;
+
+ case CSensrvTransaction::ETransTypeStartListening:
+ case CSensrvTransaction::ETransTypeStartConditionListening:
+ {
+ if ( err != KErrNone )
+ {
+ CSensrvChannelListener* listener = GetListener(aTransaction->Session());
+
+ // If error at SSY, stop listening
+ if ( listener )
+ {
+ CSensrvChannelListener::TSensrvChannelListenerState stopType =
+ aTransaction->Type() == CSensrvTransaction::ETransTypeStartListening ?
+ CSensrvChannelListener::EChannelListenerStateDataListening :
+ CSensrvChannelListener::EChannelListenerStateConditionListening;
+
+ // Stop listening that was started, but do not delete any
+ // added conditions, as client will expect them to be added if he retries.
+ listener->StopListening(stopType, EFalse);
+ }
+ else
+ {
+ // No listener found, we may have to close
+ CloseIfNeeded();
+ }
+ }
+ else
+ {
+ iState = EChannelStateListening;
+ }
+ }
+ break;
+
+ case CSensrvTransaction::ETransTypeStopListening:
+ case CSensrvTransaction::ETransTypeStopConditionListening:
+ {
+ if ( err != KErrNone )
+ {
+ // If an error occurred, assume channel was left active still.
+ // However, client listener state has already been set to not-active,
+ // so report ok to client.
+ aTransaction->SetErrorCode( KErrNone );
+ }
+ else
+ {
+ iState = EChannelStateOpen;
+ }
+ }
+ break;
+
+ case CSensrvTransaction::ETransTypeMediatorNewDataAvailable:
+ {
+ // Remove force transaction from monitor
+ if ( iForcingBufferFilled )
+ {
+ iForcingBufferFilled = EFalse;
+ iProxy.TransactionMonitor()->RemoveTransaction( iForceBufferFilledTransaction );
+ }
+
+ // Notify each listener that new data is available
+ TInt i( iListenerList.Count() );
+ for ( i--; i >= 0; i-- )
+ {
+ err = iListenerList[ i ]->NewDataAvailable();
+
+ // Delete any listeners who cannot handle new data, as most likely the message
+ // descriptors for writing are invalid.
+ if (err != KErrNone)
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::CompleteTransaction - ERROR: Error while handling new data in listener, deleting... (%d)" ), err ) );
+ delete iListenerList[ i ];
+ iListenerList.Remove( i );
+ CloseIfNeeded();
+ }
+ }
+ }
+ break;
+
+ case CSensrvTransaction::ETransTypeMediatorForceChannelClose:
+ {
+ // If channel is already closed, no need for this
+ if ( iState != EChannelStateClosed )
+ {
+ // First transaction requires special handling, if it is already executing.
+ CSensrvTransaction* first = iChannelQueue->First();
+ TBool closeNeeded( ETrue );
+
+ if ( first
+ && first->State() != CSensrvTransaction::ETransStateQueued
+ && first->Type() != CSensrvTransaction::ETransTypeCloseChannel )
+ {
+ // There is a non-close transaction executing, so
+ // remove the transaction from mediators
+ if ( iProxy.ServerMediator() )
+ {
+ iProxy.ServerMediator()->RemoveSingleTransaction( first );
+ }
+
+ if ( iProxy.SsyMediator() )
+ {
+ iProxy.SsyMediator()->RemoveSingleTransaction( first );
+ }
+ }
+ else if ( first
+ && first->State() != CSensrvTransaction::ETransStateQueued
+ && first->Type() == CSensrvTransaction::ETransTypeCloseChannel )
+ {
+ // The first executing transaction is already a close transaction,
+ // so it is not necessary to force close anymore.
+ closeNeeded = EFalse;
+ }
+ else
+ {
+ // No executing transaction, proceed with close
+ }
+
+ // Delete listeners and their transactions if close needed
+ if (closeNeeded)
+ {
+ TInt i(iListenerList.Count());
+ for ( i--; i >= 0; i-- )
+ {
+ iChannelQueue->Remove( &( iListenerList[ i ]->Session() ) );
+
+ delete iListenerList[ i ];
+ iListenerList.Remove( i );
+ }
+
+ // Insert new channel close to beginning of the queue
+ // (Queue might still have open channel transactions in it)
+ CSensrvTransaction* closeTransaction = NULL;
+ TRAP( err, closeTransaction = CSensrvTransaction::NewL(
+ NULL,
+ &iProxy,
+ this,
+ CSensrvTransaction::ETransTypeCloseChannel ) );
+
+ if ( (err==KErrNone) && closeTransaction )
+ {
+ closeTransaction->SetState( CSensrvTransaction::ETransStateQueued );
+ err = iChannelQueue->Add( closeTransaction, EFalse );
+
+ if ( err != KErrNone )
+ {
+ delete closeTransaction;
+ closeTransaction = NULL;
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::CompleteTransaction - ERROR: Unable to queue internal close transaction" ) ) );
+ }
+ else
+ {
+ HandleNextTransaction();
+ }
+ }
+ else
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::CompleteTransaction - ERROR: Unable to create internal close transaction" ) ) );
+ }
+ }
+ }
+ else
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::CompleteTransaction - Channel already closed when handling ETransTypeMediatorForceChannelClose." ) ) );
+ }
+ }
+ break;
+
+ case CSensrvTransaction::ETransTypeGetProperty:
+ {
+ //Data is already written in SSY mediator
+ }
+ break;
+
+ case CSensrvTransaction::ETransTypeGetAllProperties:
+ {
+ //Data is already written in SSY mediator
+ }
+ break;
+
+ case CSensrvTransaction::ETransTypeSetProperty:
+ {
+ // Since SSY won't be sending the property change notification to this channel,
+ // send notification to other clients than setter.
+ }
+ break;
+
+ case CSensrvTransaction::ETransTypeMediatorPropertyChanged:
+ {
+ // Update indicator values on property change and notify changes to clients
+ HandleSetPropertySuccessIndOnPropertyChange();
+
+ // Notify each listener that new data is available
+ TInt i( iListenerList.Count() );
+ for ( i--; i >= 0; i-- )
+ {
+ iListenerList[i]->HandleNextProperty();
+ }
+ }
+ break;
+
+ default:
+ // Unexpected transaction type, so we do not know what to do with it
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::CompleteTransaction - ERROR: Invalid transaction type" ) ) );
+ User::Panic(KSensrvPanicCategory, ESensrvPanicUnknownTransactionType);
+ break;
+ }
+
+ // Mediator transactions do not cause further handling
+ if ( !aTransaction->IsMediatorType() )
+ {
+ // Complete the transaction
+ iProxy.TransactionMonitor()->RemoveTransaction(aTransaction);
+ iChannelQueue->Remove(aTransaction, CSensrvTransactionQueue::ERemovalTypeComplete);
+
+ // Execute next transaction in queue, if any
+ HandleNextTransaction();
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::CompleteTransaction - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Cleans up everything related to terminated session.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::SessionTerminated( CSensrvSession* aSession )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::SessionTerminated(aSession: 0x%x)"),aSession ) );
+
+ // Cleanup any waiting transactions for this session
+ iChannelQueue->Remove(aSession);
+
+ // Delete listener for session if it exists
+ DeleteListener(aSession);
+
+ // Close channel if channel state, transactions and listeners are not correctly
+ // matched.
+ CloseIfNeeded();
+
+ // NOTE: Session termination for a session that has currently executing synchronous
+ // client/server message is _extremely_ unlikely and will probably never happen in real devices,
+ // Only plausable case that comes to mind is that client thread is paniced by some other server
+ // handling some asynchronous message for that client, while the client is waiting on
+ // synchronous SendReceive call to sensor server.
+
+ // However, just in case, handle the next transaction. If next transaction and removed transaction
+ // were both open channel or close channel transactions, the handling of next transaction might
+ // cause error at SSY, depending on timing and how SSY handles simultaneous open/close to the same
+ // channel. Preventing this from occuring in server code seems to be quite complex,
+ // so for a case this rare it is not cost effective.
+ HandleNextTransaction();
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::SessionTerminated - return" )) );
+ }
+
+// ---------------------------------------------------------------------------
+// Handles SSY notification failure.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::HandleSsyNotifyFailure()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleSsyNotifyFailure()" ) ) );
+
+ // Check queued transactions to determine if they are handled at SSY
+ CSensrvTransaction* transaction = iChannelQueue->First();
+
+ if ( transaction && transaction->State() == CSensrvTransaction::ETransStateNotifyFailed )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleSsyNotifyFailure - Notify failed transaction found" ) ) );
+ transaction->SetState( CSensrvTransaction::ETransStateHandledAtSsy );
+ CompleteTransaction( transaction );
+ }
+
+ // Also check new data available transaction
+ if ( iDataAvailableTransaction && iDataAvailableTransaction->State() == CSensrvTransaction::ETransStateNotifyFailed )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleSsyNotifyFailure - Notify failed for iDataAvailableTransaction" ) ) );
+ iDataAvailableTransaction->SetState( CSensrvTransaction::ETransStateHandledAtSsy );
+ CompleteTransaction( iDataAvailableTransaction );
+ }
+
+ // Also check force channel close transaction
+ if ( iForceChannelCloseTransaction && iForceChannelCloseTransaction->State() == CSensrvTransaction::ETransStateNotifyFailed )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleSsyNotifyFailure - Notify failed for iForceChannelCloseTransaction" ) ) );
+ iForceChannelCloseTransaction->SetState( CSensrvTransaction::ETransStateHandledAtSsy );
+ CompleteTransaction( iForceChannelCloseTransaction );
+ }
+
+ // Also check property change transaction
+ if ( iPropertyChangedTransaction && iPropertyChangedTransaction->State() == CSensrvTransaction::ETransStateNotifyFailed )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleSsyNotifyFailure - Notify failed for iPropertyChangedTransaction" ) ) );
+ iPropertyChangedTransaction->SetState( CSensrvTransaction::ETransStateHandledAtSsy );
+ CompleteTransaction( iPropertyChangedTransaction );
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleSsyNotifyFailure - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Forces buffer filled at SSY.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::ForceBufferFilled()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ForceBufferFilled()" ) ) );
+
+ // Notify SSY thread that buffer fill must be forced.
+ if (iForceBufferFilledTransaction)
+ {
+ if (iForcingBufferFilled)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ForceBufferFilled - Already forcing bufferfilled" ) ) );
+ }
+ else
+ {
+ TInt err = iProxy.SsyMediator()->Notify(iForceBufferFilledTransaction);
+
+ if (err == KErrNone)
+ {
+ iForcingBufferFilled = ETrue;
+ iProxy.TransactionMonitor()->AddTransaction(iForceBufferFilledTransaction);
+ }
+ else
+ {
+ // Just trace, it is not critical if notifying SSY mediator fails in this case.
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::ForceBufferFilled - ERROR: SSY mediator notify failed: %d" ), err ) );
+ }
+ }
+ }
+ else
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::ForceBufferFilled - ERROR: Buffer filled transaction NULL" ) ) );
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ForceBufferFilled - return. iForcingBufferFilled: %d" ), iForcingBufferFilled ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Recalculates buffering count to match lowest need of all buffers.
+//
+// Note: Even for one client it is necessary to recalculate buffering count,
+// as buffering period caused buffer fills combined with a client that
+// occasionally doesn't get data in timely manner will need recalculation
+// after such events.
+// Trying to optimize this to skip unnecessary recalculation is quite complex,
+// and probably not that much faster than just recalculating always
+// without extra checks.
+// ---------------------------------------------------------------------------
+//
+TInt CSensrvChannel::RecalculateBufferingCount()
+ {
+ TInt count(iListenerList.Count());
+
+ TInt previousLow(iMaxBufferingCount);
+
+ // Determine lowest remaining need of each listener.
+ TInt remainingCount(0);
+
+ if (count)
+ {
+ for (TInt i=0; previousLow > KSensrvMinimumBufferingCount && i < count; i++)
+ {
+ if ( iListenerList[i]->State() & CSensrvChannelListener::EChannelListenerStateConditionListening
+ || iListenerList[i]->State() & CSensrvChannelListener::EChannelListenerStateDataListening )
+ {
+ remainingCount = iListenerList[i]->RemainingBufferingCount();
+
+ if (remainingCount < previousLow)
+ {
+ previousLow = remainingCount;
+ }
+ }
+ }
+ }
+ else
+ {
+ // No listeners, so return zero count.
+ previousLow = 0;
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::RecalculateBufferingCount - No listeners" ) ) );
+ }
+
+ BUFFER_TRACE( (_L( "#### Recalculated buffering count: %d" ), previousLow) );
+
+ return previousLow;
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::GetAffectedClients
+//
+// Client is considered as "affected" if the channel is opened by the client.
+// When the channel is open, channel listener also exists.
+// Priorities are queried from ChannelListener.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::GetAffectedClients( RArray<TInt>& aAffectedClients,
+ TSecureId aCallerSecureId )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetAffectedClients()" ) ) );
+
+ TInt count(iListenerList.Count());
+ for (TInt i=0; i < count; i++)
+ {
+ if (aCallerSecureId == iListenerList[i]->Session().SecureId() )
+ {
+ //Filter away
+ }
+ else
+ {
+ aAffectedClients.Append( iListenerList[i]->Priority() );
+ }
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetAffectedClients - %d client(s) found - return" ), count ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Creates a new condition evaluator or returns an existing one.
+// Once the evaluator is created, it will not be destroyed until channel
+// is closed.
+// ---------------------------------------------------------------------------
+//
+CSensrvConditionEvaluator* CSensrvChannel::ConditionEvaluatorL()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ConditionEvaluatorL()" ) ) );
+
+ if (!iConditionEvaluator)
+ {
+ iConditionEvaluator = CSensrvConditionEvaluator::NewL( iChannelInfo );
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ConditionEvaluatorL - return 0x%x" ), iConditionEvaluator ) );
+
+ return iConditionEvaluator;
+ }
+
+// ---------------------------------------------------------------------------
+// Handles next transaction
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::HandleNextTransaction()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction()" ) ) );
+
+ CSensrvTransaction* transaction = iChannelQueue->First();
+
+ // Handle transactions until a transaction is left in executing state
+ while (transaction)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - Handling transaction of type: %d" ), transaction->Type() ) );
+
+ if (transaction->State() != CSensrvTransaction::ETransStateQueued)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - Previous transaction still executing" ) ) );
+ transaction = NULL;
+ break;
+ }
+
+ TInt err(KErrNone);
+
+ transaction->SetState(CSensrvTransaction::ETransStateExecuting);
+
+ TBool ssyTransaction(EFalse);
+
+ // Check channel closed state, only open and close have special operations
+ if ( iState == EChannelStateClosed
+ && ( transaction->Type() != CSensrvTransaction::ETransTypeOpenChannel
+ && transaction->Type() != CSensrvTransaction::ETransTypeCloseChannel ) )
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - ERROR: Channel closed." ) ) );
+ err = KErrNotFound;
+
+ // Since channel is closed, also delete listener, if it exists
+ DeleteListener(transaction->Session());
+ }
+ else
+ {
+ switch(transaction->Type())
+ {
+ ///////////////////////////////////////////////
+ case CSensrvTransaction::ETransTypeOpenChannel:
+ {
+ // If session already has a listener, channel is already open
+ // for this client, which is an error
+ CSensrvChannelListener* listener = GetListener(transaction->Session());
+
+ if (listener)
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - ERROR: ETransTypeOpenChannel, listener already exists." ) ) );
+ err = KErrAlreadyExists;
+ }
+ else
+ {
+ // Add new listener for the session
+ TRAP(err, listener = CSensrvChannelListener::NewL(*transaction->Session(), *this, iProxy));
+
+ if (err == KErrNone)
+ {
+ err = iListenerList.Append(listener);
+ if (err == KErrNone )
+ {
+ // Quick update is allowed only when the highest has been searched earlier.
+ if ( iHighestListenerPriorityMultiples > 0 )
+ {
+ // Update cached highest listener priority tracking
+ TInt priority( listener->Priority() );
+ if ( priority > iHighestListenerPriority )
+ {
+ iHighestListenerPriority = priority;
+ iHighestListenerPriorityMultiples = 1;
+ }
+ else if ( priority == iHighestListenerPriority )
+ {
+ iHighestListenerPriorityMultiples++;
+ }
+ }
+ }
+ else
+ {
+ delete listener;
+ listener = NULL;
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - ERROR: ETransTypeOpenChannel, listener append failed: %d." ), err ) );
+ }
+ }
+ else
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - ERROR: ETransTypeOpenChannel, new listener creation failed: %d" ), err ) );
+ }
+ }
+
+ // If channel state is closed, SSY needs to handle transaction to open channel.
+ // Also stop unloading timer if it is active.
+ if ( err == KErrNone && iState == EChannelStateClosed )
+ {
+ // Stop unload timer if it happens to be active
+ iProxy.StopUnloadTimer();
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - Opening channel to SSY" ) ) );
+ ssyTransaction = ETrue;
+ }
+
+ // Write maximum buffering count and data item size to message, if buffer exists.
+ if ( err == KErrNone && iChannelBuffer )
+ {
+ CSensrvTransaction::TChannelOpenMessageData data( iMaxBufferingCount, iChannelInfo.iDataItemSize );
+ err = transaction->SetMessageData( &data );
+ }
+
+ // Create mediator transactions to be used in notifying property changes.
+ // These transactions are never deleted and are reused.
+ if ( err == KErrNone && !iPropertyChangedTransaction )
+ {
+ TRAP( err, iPropertyChangedTransaction = CSensrvTransaction::NewL(
+ NULL,
+ &iProxy,
+ this,
+ CSensrvTransaction::ETransTypeMediatorPropertyChanged ) );
+
+ if ( err != KErrNone )
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - ERROR: ETransTypeMediatorPropertyChanged transaction creation failed: %d" ), err ) );
+ }
+ }
+
+ if ( err != KErrNone)
+ {
+ DeleteListener(transaction->Session());
+ }
+ // If SSY transaction required, handle the indication when the SSY transaction completes
+ if ( err == KErrNone && !ssyTransaction )
+ {
+ HandleDependencyOnOpen();
+
+ // Update indicator values on open and notify changes to clients
+ HandleSetPropertySuccessIndOnCreateOrDelete();
+ }
+ }
+ break;
+
+ ///////////////////////////////////////////////
+ case CSensrvTransaction::ETransTypeCloseChannel:
+ {
+ //get the listener
+ CSensrvChannelListener* listener = FindListener( transaction->Session() );
+
+ TInt priority( KMinTInt );
+
+ if ( listener )
+ {
+ priority = listener->Priority();
+ }
+
+ DeleteListener( transaction->Session() );
+
+ HandleDependencyOnClose( priority ); //listener is gone
+
+ // If there are more listeners remaining, or channel already closed, do not close channel
+ if ( iState == EChannelStateClosed )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - Channel already closed, not closing channel to SSY" ) ) );
+ }
+ else if ( iListenerList.Count() > 0 )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - More clients remaining, not closing channel to SSY" ) ) );
+ }
+ else
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - Closing channel to SSY" ) ) );
+ ssyTransaction = ETrue;
+ }
+ // Update indicator values on close and notify changes to clients
+
+ HandleSetPropertySuccessIndOnCreateOrDelete();
+ }
+ break;
+
+ ///////////////////////////////////////////////
+ case CSensrvTransaction::ETransTypeStartListening:
+ case CSensrvTransaction::ETransTypeStartConditionListening:
+ {
+ err = HandleStartListeningTransaction(*transaction);
+ ssyTransaction = ETrue;
+ }
+ break;
+
+ ///////////////////////////////////////////////
+ case CSensrvTransaction::ETransTypeStopListening:
+ case CSensrvTransaction::ETransTypeStopConditionListening:
+ {
+ HandleStopListeningTransaction(*transaction, ssyTransaction);
+ }
+ break;
+
+ ///////////////////////////////////////////////
+ case CSensrvTransaction::ETransTypeGetProperty:
+ case CSensrvTransaction::ETransTypeGetAllProperties:
+ case CSensrvTransaction::ETransTypeSetProperty:
+ {
+ ssyTransaction = ETrue;
+ CSensrvChannelListener* listener = GetListener(transaction->Session());
+ if ( !listener )
+ {
+ //Listener doesn't exist anymore (for some reason).
+ err = KErrNotFound;
+ }
+ }
+ break;
+
+ ///////////////////////////////////////////////
+ default:
+ // Unexpected transaction type, so we do not know what to do with it
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - ERROR: Invalid transaction type" ) ) );
+ User::Panic(KSensrvPanicCategory, ESensrvPanicUnknownTransactionType);
+ break;
+ }
+ }
+
+ if (err == KErrNone && ssyTransaction)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - Notifying SSY..." ) ) );
+ // If SSY mediator is not yet initialized, it is an error
+ __ASSERT_ALWAYS(iProxy.SsyMediator(), User::Panic(KSensrvPanicCategory, ESensrvPanicNullSsyMediator));
+
+ // Notify SSY mediator that transaction is ready to be handled.
+ err = iProxy.SsyMediator()->Notify(transaction);
+ }
+
+ // If there was error, transaction needs to be removed from queue (which also completes it)
+ // Transaction also needs to be completed if SSY transaction is not needed.
+ // If transaction is completed, next one in queue is handled.
+ if (err != KErrNone)
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - ERROR: Failed to handle next transaction: %d, type: %d" ), err, transaction->Type() ) );
+ transaction->SetErrorCode(err);
+ iChannelQueue->Remove(transaction, CSensrvTransactionQueue::ERemovalTypeComplete);
+
+ // Prepare to handle next transaction
+ transaction = iChannelQueue->First();
+ }
+ else if (!ssyTransaction)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - SSY transaction not needed, completing transaction" ) ) );
+ iChannelQueue->Remove(transaction, CSensrvTransactionQueue::ERemovalTypeComplete);
+
+ // Prepare to handle next transaction
+ transaction = iChannelQueue->First();
+ }
+ else
+ {
+ // SSY transaction executing, no need for further transaction handling now
+ iProxy.TransactionMonitor()->AddTransaction(transaction);
+ transaction = NULL;
+ }
+ } // End while(transaction)
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Gets listener pointer from list or NULL if no listener found.
+// ---------------------------------------------------------------------------
+//
+CSensrvChannelListener* CSensrvChannel::GetListener(CSensrvSession* aSession)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetListener(aSession: 0x%x)" ), aSession ) );
+
+ CSensrvChannelListener* listener = NULL;
+ TInt count(iListenerList.Count());
+
+ for (TInt i=0; i < count; i++)
+ {
+ if (&iListenerList[i]->Session() == aSession)
+ {
+ listener = iListenerList[i];
+ break;
+ }
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetListener - return 0x%x" ), listener ) );
+
+ return listener;
+ }
+
+// ---------------------------------------------------------------------------
+// Deletes listener if it exists
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::DeleteListener(CSensrvSession* aSession)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::DeleteListener(aSession: 0x%x)" ), aSession ) );
+
+ TInt count(iListenerList.Count());
+ TBool deleted( EFalse );
+
+ for ( TInt i=0; !deleted && i < count; i++ )
+ {
+ if ( &iListenerList[i]->Session() == aSession )
+ {
+ deleted = ETrue;
+ CSensrvChannelListener* ptr = iListenerList[i];
+ if ( ptr == iCurrentSetPropertyControl )
+ {
+ // Reset the property control
+ iCurrentSetPropertyControl = NULL;
+ }
+ if ( iHighestListenerPriorityMultiples > 0 &&
+ ptr->Priority() == iHighestListenerPriority )
+ {
+ // Update cached highest listener priority tracking
+ if ( !( --iHighestListenerPriorityMultiples ) )
+ {
+ // Reset the highest priority when there are no multiples.
+ // Next GetHighestListenerPriority() call triggers complete priority check.
+ iHighestListenerPriority = KMinTInt;
+ }
+ }
+ delete ptr;
+ iListenerList.Remove(i);
+ }
+ }
+
+ // If listener was not found, it is normally not an error, but in some cases it is interesting.
+ // -> Trace only regular COMPONENT_TRACE
+ if ( !deleted )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::DeleteListener - Listener not found" ) ) );
+ }
+
+ // Check if unload timer needs to be started, since there are no more clients
+ if (!iListenerList.Count())
+ {
+ iProxy.StartUnloadTimerIfNeeded();
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::DeleteListener - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// Finds a listener based on session
+// ---------------------------------------------------------------------------
+//
+CSensrvChannelListener* CSensrvChannel::FindListener( CSensrvSession* aSession )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::FindListener(aSession: 0x%x)" ), aSession ) );
+
+ TInt count( iListenerList.Count() );
+ CSensrvChannelListener* ptr( NULL );
+
+ if ( aSession )
+ {
+ for ( TInt i=0; i < count; i++ )
+ {
+ if ( &iListenerList[i]->Session() == aSession )
+ {
+ ptr = iListenerList[ i ];
+ break;
+ }
+ }
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::FindListener - return" ) ) );
+
+ return ptr;
+ }
+
+// ---------------------------------------------------------------------------
+// Closes the channel to SSY if there are no more listeners.
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::CloseIfNeeded()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::CloseIfNeeded()" ) ) );
+
+ // Check listener count and state
+ if (iState == EChannelStateClosed)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::CloseIfNeeded - Close NOT needed, channel already closed" ) ) );
+ }
+ else
+ {
+ TInt err(KErrNone);
+ TInt count(iListenerList.Count());
+ CSensrvTransaction* transaction = NULL;
+
+ if (!count)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::CloseIfNeeded - Close needed, no clients" ) ) );
+ // Create internal close transaction and queue it
+ TRAP(err, transaction = CSensrvTransaction::NewL(
+ NULL,
+ &iProxy,
+ this,
+ CSensrvTransaction::ETransTypeCloseChannel));
+ }
+ else if (iState == EChannelStateListening)
+ {
+ // Check if any of other clients are actually listening. If not,
+ // queue stop listening transaction
+ TBool activeFound(EFalse);
+
+ for (TInt i=0; !activeFound && i < count; i++)
+ {
+ if ( iListenerList[i]->State() & CSensrvChannelListener::EChannelListenerStateConditionListening
+ || iListenerList[i]->State() & CSensrvChannelListener::EChannelListenerStateDataListening)
+ {
+ activeFound = ETrue;
+ }
+ }
+
+ if (!activeFound)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::CloseIfNeeded - Stop needed, no active clients" ) ) );
+ TRAP(err, transaction = CSensrvTransaction::NewL(
+ NULL,
+ &iProxy,
+ this,
+ CSensrvTransaction::ETransTypeStopListening));
+ }
+ else
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::CloseIfNeeded - Stop NOT needed, active client found" ) ) );
+ }
+ }
+ else
+ {
+ // State open and some other clients, no need to do anything
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::CloseIfNeeded - Close NOT needed, channel open and other clients found " ) ) );
+ }
+
+ if ( (err == KErrNone) && (transaction) )
+ {
+ // Queue transaction. If there is some open transaction queued before close,
+ // that is alright, close/stop will be ignored in transaction handling if state at
+ // that point is not suitable.
+ transaction->SetState(CSensrvTransaction::ETransStateQueued);
+ err = iChannelQueue->Add(transaction);
+
+ if (err != KErrNone)
+ {
+ delete transaction;
+ transaction = NULL;
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::CloseIfNeeded - ERROR: Unable to queue close/stop transaction" ) ) );
+ }
+ }
+ else
+ {
+ transaction = NULL;
+ }
+ }
+
+ // Note that if there is an error creating/queueing transaction, channel will stay in incorrect state,
+ // but can't do anything about it.
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::CloseIfNeeded - return" ) ) );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Handles start data and condition listening transactions
+// ---------------------------------------------------------------------------
+//
+TInt CSensrvChannel::HandleStartListeningTransaction(CSensrvTransaction& aTransaction)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleStartListeningTransaction()" ) ) );
+
+ TInt err(KErrNone);
+
+ CSensrvChannelListener::TSensrvChannelListenerState targetState
+ (CSensrvChannelListener::EChannelListenerStateDataListening);
+
+ if (aTransaction.Type() == CSensrvTransaction::ETransTypeStartConditionListening)
+ {
+ // Condition evaluator must exist
+ TRAP( err, ConditionEvaluatorL() );
+
+ targetState = CSensrvChannelListener::EChannelListenerStateConditionListening;
+ }
+ else // ETransTypeStartListening
+ {
+ // Target state already data listening
+ }
+
+ if (err == KErrNone)
+ {
+ // Check that there is listener for this client session
+ CSensrvChannelListener* listener = GetListener(aTransaction.Session());
+
+ if (!listener)
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleStartListeningTransaction - ERROR: Listener doesn't exist." ) ) );
+ err = KErrNotFound;
+ }
+ else if (listener->State() & targetState)
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleStartListeningTransaction - ERROR: Listener already listening." ) ) );
+ err = KErrAlreadyExists;
+ }
+ else
+ {
+ // Create mediator transactions to be used in notifying data writes to buffer.
+ // These transactions are never deleted and are reused.
+ if (!iDataAvailableTransaction)
+ {
+ TRAP(err, iDataAvailableTransaction = CSensrvTransaction::NewL(
+ NULL,
+ &iProxy,
+ this,
+ CSensrvTransaction::ETransTypeMediatorNewDataAvailable));
+
+ if (err != KErrNone)
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleStartListeningTransaction - ERROR: ETransTypeMediatorNewDataAvailable transaction creation failed: %d" ), err ) );
+ }
+ }
+
+ if (err == KErrNone && !iForceBufferFilledTransaction)
+ {
+ TRAP(err, iForceBufferFilledTransaction = CSensrvTransaction::NewL(
+ NULL,
+ &iProxy,
+ this,
+ CSensrvTransaction::ETransTypeMediatorForceBufferFilled));
+
+ if (err != KErrNone)
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleStartListeningTransaction - ERROR: ETransTypeMediatorForceBufferFilled transaction creation failed: %d" ), err ) );
+ }
+ }
+
+ if (err == KErrNone && !iForceChannelCloseTransaction)
+ {
+ TRAP(err, iForceChannelCloseTransaction = CSensrvTransaction::NewL(
+ NULL,
+ &iProxy,
+ this,
+ CSensrvTransaction::ETransTypeMediatorForceChannelClose));
+
+ if (err != KErrNone)
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleStartListeningTransaction - ERROR: ETransTypeMediatorForceChannelClose transaction creation failed: %d" ), err ) );
+ }
+ }
+
+ if ( err == KErrNone )
+ {
+ // Get buffering count and period from message
+ TSensrvStartListeningParametersPckgBuf pckg;
+ err = aTransaction.Message()->Read( KSensrvStartListeningParametersSlot, pckg );
+
+ if ( err == KErrNone )
+ {
+ TSensrvStartListeningParameters startParams = pckg();
+
+ TSensrvResourceChannelInfo::TSensrvChannelGroup group = ChannelGroup();
+
+ if ( group == TSensrvResourceChannelInfo::ESensrvChannelGroupEvent
+ || group == TSensrvResourceChannelInfo::ESensrvChannelGroupState )
+ {
+ startParams.iBufferingPeriod = 0;
+ }
+
+ err = listener->StartListening( startParams.iDesiredBufferingCount,
+ startParams.iMaximumBufferingCount,
+ startParams.iBufferingPeriod,
+ targetState );
+ if (err != KErrNone)
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleStartListeningTransaction - ERROR: Listener adding failed: %d" ), err ) );
+ }
+ }
+ else
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleStartListeningTransaction - ERROR: Start parameters reading failed: %d" ), err ) );
+ }
+ }
+ }
+ }
+ else
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleStartListeningTransaction - ERROR: Condition evaluator plugin loading failed: %d" ), err ) );
+ }
+
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleStartListeningTransaction - return %d" ), err ) );
+
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// Handles stop data and condition listening transactions
+// ---------------------------------------------------------------------------
+//
+TInt CSensrvChannel::HandleStopListeningTransaction(CSensrvTransaction& aTransaction,
+ TBool& aSsyTransactionNeeded)
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleStopListeningTransaction()" ) ) );
+
+ TInt err(KErrNone);
+
+ CSensrvChannelListener::TSensrvChannelListenerState currentState
+ (CSensrvChannelListener::EChannelListenerStateDataListening);
+
+ if (aTransaction.Type() == CSensrvTransaction::ETransTypeStopConditionListening)
+ {
+ currentState = CSensrvChannelListener::EChannelListenerStateConditionListening;
+ }
+ else // ETransTypeStartListening
+ {
+ // Target state already data listening
+ }
+
+ // Check that there is listener for this client session
+ CSensrvChannelListener* listener = GetListener(aTransaction.Session());
+
+ if (listener && !(listener->State() & currentState))
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - ERROR: Listener not listening." ) ) );
+ err = KErrNotFound;
+ }
+ else
+ {
+ if (listener)
+ {
+ listener->StopListening(currentState, ETrue);
+ }
+
+ if (iState == EChannelStateOpen)
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleNextTransaction - ERROR: Channel not listening. Listener: 0x%x" ), listener ) );
+ err = KErrNotFound;
+ }
+ else // iState == EChannelStateListening
+ {
+ // Check if there are any more active listeners
+ TInt count(iListenerList.Count());
+ TBool activeFound(EFalse);
+
+ for (TInt i=0; !activeFound && i < count; i++)
+ {
+ if ( iListenerList[i]->State() & CSensrvChannelListener::EChannelListenerStateConditionListening
+ || iListenerList[i]->State() & CSensrvChannelListener::EChannelListenerStateDataListening)
+ {
+ activeFound = ETrue;
+ }
+ }
+
+ if (!activeFound)
+ {
+ // No active listeners remain, stop listening at SSY
+ aSsyTransactionNeeded = ETrue;
+ }
+ else
+ {
+ // At least one active listener remaining, do not stop listening at SSY
+ aSsyTransactionNeeded = EFalse;
+ }
+ }
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleStartListeningTransaction - return %d" ), err ) );
+
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::GetHighestListenerPriority()
+// ---------------------------------------------------------------------------
+//
+TInt CSensrvChannel::GetHighestListenerPriority( TInt& aHighestPriority )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetHighestListenerPriority()" ) ) );
+
+ // Prefer the cached results if possible
+ if ( iHighestListenerPriorityMultiples <= 0 )
+ {
+ // Search the highest priority and its multiples from this channel and cache the results
+ iHighestListenerPriorityMultiples = 0;
+ iHighestListenerPriority = KMinTInt;
+ TInt i( iListenerList.Count() );
+ for( i--; i >= 0; i-- )
+ {
+ CSensrvChannelListener* ptr = iListenerList[ i ];
+ TInt priority( ptr->Priority() );
+ if ( priority > iHighestListenerPriority )
+ {
+ iHighestListenerPriority = priority;
+ iHighestListenerPriorityMultiples = 1;
+ }
+ else if ( priority == iHighestListenerPriority )
+ {
+ iHighestListenerPriorityMultiples++;
+ }
+ }
+ }
+
+ aHighestPriority = iHighestListenerPriority;
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetHighestListenerPriority() - channel: %d priority: %d multiples: %d return" ),
+ iId, iHighestListenerPriority, iHighestListenerPriorityMultiples ) );
+
+ return iHighestListenerPriorityMultiples;
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::GetLowestChannelPriority()
+// ---------------------------------------------------------------------------
+//
+TInt CSensrvChannel::GetLowestChannelPriority( const RSensrvChannelList* aAffectedChannelsList, TSensrvChannelId& aChannelId )
+ {
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetLowestChannelPriority()" ) ) );
+
+ TInt lowestPriority( KMaxTInt );
+ TInt newPriority( 0 );
+ TInt multiplesOnChannel( 0 );
+
+ if ( aAffectedChannelsList )
+ {
+ TInt i( aAffectedChannelsList->Count() );
+ CSensrvChannel* channel = NULL;
+ for ( i--; i >= 0; i-- )
+ {
+ if ( ( *aAffectedChannelsList )[ i ] != iId )
+ {
+ channel = iProxy.GetChannelForId( ( *aAffectedChannelsList )[ i ] );
+ if ( channel )
+ {
+ multiplesOnChannel = channel->GetHighestListenerPriority( newPriority );
+ if ( multiplesOnChannel > 0 )
+ {
+ if ( newPriority < lowestPriority )
+ {
+ lowestPriority = newPriority;
+ aChannelId = ( *aAffectedChannelsList )[ i ];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetLowestChannelPriority() - channel %d priority: %d" ), aChannelId, lowestPriority ) );
+
+ return lowestPriority;
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::GetHighestChannelPriority()
+// ---------------------------------------------------------------------------
+//
+TInt CSensrvChannel::GetHighestChannelPriority( const RSensrvChannelList* aAffectedChannelsList, TSensrvChannelId& aChannelId )
+ {
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetHighestChannelPriority()" ) ) );
+
+ TInt highestPriority( KMinTInt );
+ TInt newPriority( 0 );
+ TInt multiplesOnChannel( 0 );
+
+ if ( aAffectedChannelsList )
+ {
+ TInt i( aAffectedChannelsList->Count() );
+ CSensrvChannel* channel = NULL;
+ for ( i--; i >= 0; i-- )
+ {
+ if ( ( *aAffectedChannelsList )[ i ] != iId )
+ {
+ channel = iProxy.GetChannelForId( ( *aAffectedChannelsList )[ i ] );
+ if ( channel )
+ {
+ multiplesOnChannel = channel->GetHighestListenerPriority( newPriority );
+ if ( multiplesOnChannel > 0 )
+ {
+ if ( newPriority > highestPriority )
+ {
+ highestPriority = newPriority;
+ aChannelId = ( *aAffectedChannelsList )[ i ];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetHighestChannelPriority() - channel %d priority: %d" ), aChannelId, highestPriority ) );
+
+ return highestPriority;
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::GetHighestListenerPriorityOfAffectedChannels()
+// ---------------------------------------------------------------------------
+//
+TInt CSensrvChannel::GetHighestListenerPriorityOfAffectedChannels( TInt& aHighestPriority )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetHighestListenerPriorityOfAffectedChannels()" ) ) );
+
+ // Search the highest priority and its multiples from all affected channels
+ RSensrvChannelList* affectedChannels = GetAffectedChannels();
+ aHighestPriority = KMinTInt;
+ TInt multiples( 0 );
+ if ( affectedChannels )
+ {
+ TInt i( affectedChannels->Count() );
+ TInt highestOfChannel( 0 );
+ TInt multiplesOnChannel( 0 );
+ CSensrvChannel* channel = NULL;
+ for ( i--; i >= 0; i-- )
+ {
+ channel = iProxy.GetChannelForId( ( *affectedChannels )[ i ] );
+ if ( channel )
+ {
+ multiplesOnChannel = channel->GetHighestListenerPriority( highestOfChannel );
+ if ( multiplesOnChannel > 0 )
+ {
+ if ( highestOfChannel > aHighestPriority )
+ {
+ aHighestPriority = highestOfChannel;
+ multiples = multiplesOnChannel;
+ }
+ else if ( highestOfChannel == aHighestPriority )
+ {
+ multiples += multiplesOnChannel;
+ }
+ }
+ }
+ }
+
+ affectedChannels->Reset();
+ delete affectedChannels;
+ affectedChannels = NULL;
+
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetHighestListenerPriorityOfAffectedChannels() - priority: %d multiples: %d return" ),
+ aHighestPriority, multiples ) );
+
+ return multiples;
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::UpdateSetPropertySuccessIndToChannelListeners()
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::UpdateSetPropertySuccessIndToChannelListeners(
+ CSensrvChannel& aChannel, TInt aHighestOfAffectedChannels, TInt aMultiplesOnAffectedChannels )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::UpdateSetPropertySuccessIndToChannelListeners()" ) ) );
+
+ TInt highestOfChannel( 0 );
+ TInt multiplesOnChannel( aChannel.GetHighestListenerPriority( highestOfChannel ) );
+ if ( multiplesOnChannel > 0 )
+ {
+ if ( aChannel.iCurrentSetPropertyControl &&
+ aChannel.iCurrentSetPropertyControl->Priority() < highestOfChannel )
+ {
+ // Reset the property control due to higher priority listener
+ aChannel.iCurrentSetPropertyControl = NULL;
+ }
+ CSensrvChannelListener::TPropertySetSuccessEvaluationData evaluationData(
+ aHighestOfAffectedChannels, aMultiplesOnAffectedChannels,
+ highestOfChannel, multiplesOnChannel );
+ TInt i( aChannel.iListenerList.Count() );
+ for( i--; i >= 0; i-- )
+ {
+ aChannel.iListenerList[ i ]->HandleSetPropertySuccessInd( evaluationData );
+ }
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::UpdateSetPropertySuccessIndToChannelListeners() - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::HandleSetPropertySuccessIndOnPropertyChange()
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::HandleSetPropertySuccessIndOnPropertyChange()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleSetPropertySuccessIndOnPropertyChange()" ) ) );
+
+ TInt highestOfAffectedChannels( 0 );
+ TInt multiplesOnAffectedChannels( GetHighestListenerPriorityOfAffectedChannels( highestOfAffectedChannels ) );
+
+ // Send the priority information for listener of this channel to be evaluated
+ UpdateSetPropertySuccessIndToChannelListeners(
+ *this, highestOfAffectedChannels, multiplesOnAffectedChannels );
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleSetPropertySuccessIndOnPropertyChange() - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::HandleSetPropertySuccessIndOnCreateOrDelete()
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::HandleSetPropertySuccessIndOnCreateOrDelete()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleSetPropertySuccessIndOnCreateOrDelete()" ) ) );
+
+ // Get the priority information
+ RSensrvChannelList* affectedChannels = GetAffectedChannels();
+ if ( affectedChannels )
+ {
+ // Get the priority information
+ TInt highestOfAffectedChannels( 0 );
+ TInt multiplesOnAffectedChannels( GetHighestListenerPriorityOfAffectedChannels(
+ highestOfAffectedChannels ) );
+
+ // Send the priority information for listeners of affected channels to be evaluated
+ TInt i( affectedChannels->Count() );
+ for ( i--; i >= 0; i-- )
+ {
+ CSensrvChannel* channel = iProxy.GetChannelForId( ( *affectedChannels )[ i ] );
+ if ( channel )
+ {
+ UpdateSetPropertySuccessIndToChannelListeners(
+ *channel, highestOfAffectedChannels, multiplesOnAffectedChannels );
+ }
+ }
+
+ affectedChannels->Reset();
+ delete affectedChannels;
+ affectedChannels = NULL;
+
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleSetPropertySuccessIndOnCreateOrDelete() - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::TakePropertySetControl()
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::TakePropertySetControl( CSensrvChannelListener* aListener )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::TakePropertySetControl()" ) ) );
+
+ if ( iCurrentSetPropertyControl != aListener )
+ {
+ if ( aListener )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::TakePropertySetControl() channel: %d listener: 0x%x priority: %d" ),
+ iId, aListener, aListener->Priority() ) );
+ }
+ else
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::TakePropertySetControl() channel: %d listener: 0x%x" ), iId, aListener ) );
+ }
+ iCurrentSetPropertyControl = aListener;
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::TakePropertySetControl() - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::GetAffectedChannels()
+// ---------------------------------------------------------------------------
+//
+RSensrvChannelList* CSensrvChannel::GetAffectedChannels() const
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetAffectedChannels()" ) ) );
+
+ RSensrvChannelList* ret = new RSensrvChannelList();
+
+ if ( iProxy.SsyMediator() && ret )
+ {
+ iProxy.SsyMediator()->AffectedChannels( iId, iPropertyProvider, ret );
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetAffectedChannels() - return 0x%x" ), ret ) );
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::GetAvailabilityAffectedChannels()
+// ---------------------------------------------------------------------------
+//
+RSensrvChannelList* CSensrvChannel::GetAvailabilityAffectedChannels( TSensrvAvailability aValue ) const
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetAvailabilityAffectedChannels()" ) ) );
+
+ RSensrvChannelList* ret = new RSensrvChannelList();
+
+ if ( iProxy.SsyMediator() && ret )
+ {
+ iProxy.SsyMediator()->AvailabilityAffectedChannels( iId, iPropertyProvider, ret, aValue );
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::GetAvailabilityAffectedChannels() - return 0x%x" ), ret ) );
+ return ret;
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::HandleDependencyOnOpen()
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::HandleDependencyOnOpen()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnOpen() channel %d" ), iId ) );
+
+ TInt propErr( KErrNone ); //for property reading status
+ TSensrvProperty property( KSensrvPropIdAvailability, KSensrvItemIndexNone, 0 ); //for property
+
+ TRAP( propErr, iPropertyProvider->GetPropertyL( iId, property ) ); //handle property reading error below
+
+ if ( propErr == KErrNone )
+ {//availability property read OK ->
+ TInt isAvailable( static_cast<TInt>( ESensrvAvailabilityFalse ) ); //for availability property value
+
+ property.GetValue( isAvailable ); //get iId channel availability property
+
+ if ( ESensrvAvailabilityFalse == ( static_cast<TSensrvAvailability>( isAvailable ) ) )
+ {//current channel is not available, check if it needs to be set available ->
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnOpen - channel %d unavailable (%d)" ),iId, isAvailable ) );
+
+ RSensrvChannelList* affectedChannels = GetAvailabilityAffectedChannels( ESensrvAvailabilityTrue ); //get the affected channels
+
+ if ( affectedChannels )
+ {//affected channels returned a valid pointer ->
+ if ( affectedChannels->Count() )
+ {//there are affected channels ->
+ TInt channelPriority( KMinTInt ); //for current channel priority
+ TInt othersPriority( KMinTInt ); //for other channel priority
+ TSensrvChannelId otherChannelId( 0 ); //for other channel channel id
+
+ (void)GetHighestListenerPriority( channelPriority ); //get current channel highest priority, multiplicity value is not needed, thus cast'd to void
+
+ othersPriority = GetLowestChannelPriority( affectedChannels, otherChannelId );
+
+ if ( channelPriority <= othersPriority )
+ {//a higher priority client is blocking this channel ->
+ //current channel highest is not high enough!
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnOpen - channel %d priority (%d) is not high enough (vs. %d) to be enabled" ),iId, channelPriority, othersPriority ) );
+ }//<- a higher priority client is blocking this channel
+
+ else
+ {//this channel now has high enough priority user to enable and override another channel ->
+ //other has lower highest priority, disable it and enable this
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnOpen - channel %d priority (%d) is high enough (vs. %d)" ),iId, channelPriority, othersPriority ) );
+
+ (void)SetChannelAvailability( iId /*<- to enable*/, otherChannelId /* <- to disable */, property );
+ }//<- this channel has now high enough priority user to enable and override another channel
+ }//<-there are affected channels
+ else
+ {// no affected channels in list ->
+ (void)SetChannelAvailability( iId /*<- to enable*/, property, ESensrvAvailabilityTrue );
+ } // <- no affected channels
+
+ affectedChannels->Reset();
+ delete affectedChannels;
+ affectedChannels = NULL;
+
+ }//<- affected channels returned a valid pointer
+ }//<- current channel is not available, check if it needs to be set available
+ else
+ {//Current channel is available ->
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnOpen - channel %d already available (%d) or no affected channels" ),iId, isAvailable ) );
+ }//<- Current channel is available
+ }//<- availability property read OK
+ else
+ {
+ //Error reading property
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnOpen - ERROR: Unable to get property Error: %d" ), propErr ) );
+ }
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnOpen - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::HandleDependencyOnClose()
+// ---------------------------------------------------------------------------
+//
+void CSensrvChannel::HandleDependencyOnClose( const TInt &aPriority )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnClose() channel %d" ), iId ) );
+
+ TInt propErr( KErrNone );
+
+ TSensrvProperty property( KSensrvPropIdAvailability, KSensrvItemIndexNone, 0 );
+
+ TRAP( propErr, iPropertyProvider->GetPropertyL( iId, property ) ); //get availability property for current channel
+
+ if ( propErr == KErrNone )
+ {//availability property read OK ->
+
+ TInt isAvailable( static_cast<TInt>( ESensrvAvailabilityFalse ) ); //for availability property value
+
+ property.GetValue( isAvailable ); //get iId channel availability property
+
+ if ( ESensrvAvailabilityTrue == ( static_cast<TSensrvAvailability>( isAvailable ) ) )
+ {//Current channel is available, check if it needs to be set unavailable ->
+
+ RSensrvChannelList* affectedChannels = GetAvailabilityAffectedChannels( ESensrvAvailabilityFalse );
+
+ if ( affectedChannels )
+ {//affected channels returned a valid pointer ->
+ if ( affectedChannels->Count() )
+ {//there are affected channels ->
+ TInt channelPriority( KMinTInt ); //for current channel priority
+ TInt othersPriority( KMinTInt ); //for other channel priority
+ TSensrvChannelId otherChannelId( 0 ); //for other channel channel id
+
+ (void)GetHighestListenerPriority( channelPriority ); //get current channel highest priority, multiplicity value is not needed, thus cast'd to void
+
+ if ( channelPriority >= aPriority )
+ {//current channel has remaining listener(s) with a higher priority than listener that just left ->
+ //do nuthin', only highest priority / channel matters
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnClose - current channel has highest or equal priority" ) ) );
+ }//<- current channel has remaining listener(s) with a higher priority than listener that just left
+ else if ( 0 < ListenerCount() )
+ {//highest priority listener of the channel left, other listeners exist ->
+
+ othersPriority = GetHighestChannelPriority( affectedChannels, otherChannelId );
+
+ if ( channelPriority < othersPriority )
+ {//an unavailable channel has a higher priority listener than current channel ->
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnClose - channel %d priority is high enough (%d) vs. current channel %d (%d)" ),
+ otherChannelId, othersPriority, iId, channelPriority ) );
+
+ (void)SetChannelAvailability( otherChannelId /* <- to enable */, iId /* <- to disable */, property );
+ }//<- an unavailable channel has a higher priority listener than current channel
+ else
+ {//an unavailable channel does not have a higher priority listener than current channel ->
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnClose - other channel %d priority is not high enough (%d) vs. current channel %d (%d)" ),
+ otherChannelId, othersPriority, iId, channelPriority ) );
+ }//<- an unavailable channel does not have a higher priority listener than current channel
+ }//<- highest priority listener of the channel left, other listeners exist
+ else
+ {//highest priority of the channel closed, no other listeners exist ->
+ othersPriority = GetHighestChannelPriority( affectedChannels, otherChannelId );
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnClose - channel %d has no more listeners, enabling channel %d" ),iId, otherChannelId ) );
+
+ (void)SetChannelAvailability( otherChannelId /* <- to enable */, iId /* <- to disable */, property );
+ } //<- highest priority of the channel closed, no other listeners exist
+ }//<- there are affected channels
+
+ affectedChannels->Reset();
+ delete affectedChannels;
+ affectedChannels = NULL;
+
+ }//<- affected channels returned a valid pointer
+ }//<- Current channel is available, check if it needs to be set unavailable
+ else
+ {//not available ->
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnClose - channel not available (%d) or no affected channels" ), isAvailable ) );
+ }//<- not available
+ }//<- availability property read OK
+ else
+ {
+ //Error reading property
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnClose - ERROR: Unable to get property Error: %d" ), propErr ) );
+ }
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::HandleDependencyOnClose - return" ) ) );
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::SetAvailability()
+// ---------------------------------------------------------------------------
+//
+TInt CSensrvChannel::SetAvailability( TSensrvChannelId aChannelId, TSensrvProperty& aProperty, TSensrvAvailability aValue, const TSecurityInfo& aSecurityInfo )
+ {
+ TInt propErr( KErrNone );
+
+ aProperty.SetValue( static_cast<TInt>( aValue ) );
+ aProperty.SetSecurityInfo( aSecurityInfo );
+
+ TRAP( propErr, iPropertyProvider->SetPropertyL( aChannelId, aProperty ) );
+
+ if ( propErr == KErrNone )
+ {
+ //property set ok
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetAvailability - Channel %d property set to %d OK" ), aChannelId, aValue ) );
+ }
+ else
+ {
+ //handle property error
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetAvailability - ERROR: Unable to set property for dependent channel - Error: %d" ), propErr ) );
+ }
+
+ return propErr;
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::SetChannelAvailability()
+// ---------------------------------------------------------------------------
+//
+TInt CSensrvChannel::SetChannelAvailability( TSensrvChannelId aChannelIdToEnable, TSensrvChannelId aChannelIdToDisable, TSensrvProperty& aProperty )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetChannelAvailability" ) ) );
+
+ TInt status ( KErrNone );
+ TSecurityInfo securityInfo;
+
+ securityInfo.SetToCurrentInfo();
+
+ status = SetAvailability( aChannelIdToDisable, aProperty, ESensrvAvailabilityFalse, securityInfo );
+
+ if ( KErrNone == status )
+ {
+ status = SetAvailability( aChannelIdToEnable, aProperty, ESensrvAvailabilityTrue, securityInfo );
+
+ if ( KErrNone != status )
+ {
+ //Handle error
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetChannelAvailability - ERROR: Unable to set channel %d to available - Error: %d" ), aChannelIdToEnable, status ) );
+
+ //rewind
+ (void)SetAvailability( aChannelIdToDisable, aProperty, ESensrvAvailabilityTrue, securityInfo );
+ }
+ }
+ else
+ {
+ //Handle error
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetChannelAvailability - ERROR: Unable to set channel %d to unavailable - Error: %d" ), aChannelIdToDisable, status ) );
+ //nothing to rewind
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetChannelAvailability() - return %d" ), status ) );
+
+ return status;
+ }
+
+// ---------------------------------------------------------------------------
+// CSensrvChannel::SetChannelAvailable()
+// ---------------------------------------------------------------------------
+//
+TInt CSensrvChannel::SetChannelAvailability( TSensrvChannelId aChannelId, TSensrvProperty& aProperty, TSensrvAvailability aValue )
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetChannelAvailability" ) ) );
+
+ TInt status ( KErrNone );
+ TSecurityInfo securityInfo;
+
+ securityInfo.SetToCurrentInfo();
+
+ status = SetAvailability( aChannelId, aProperty, aValue, securityInfo );
+ if ( KErrNone != status )
+ {
+ //Handle error
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetChannelAvailability - ERROR: Unable to set channel %d to %d - Error: %d" ), aChannelId, aValue, status ) );
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::SetChannelAvailability() - return %d" ), status ) );
+
+ return status;
+ }
+
+// ---------------------------------------------------------------------------
+// Reads channel group
+// ---------------------------------------------------------------------------
+//
+TSensrvResourceChannelInfo::TSensrvChannelGroup CSensrvChannel::ReadChannelGroup()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ReadChannelGroup()" ) ) );
+
+ // Use not defined as default if not defined or read fails
+ TInt channelGroup( TSensrvResourceChannelInfo::ESensrvChannelGroupNotDefined );
+ TInt err( KErrNone );
+
+ // Open channel group repository and get necessary values
+ CRepository* repository = NULL;
+ TRAP( err, repository = CRepository::NewL( KCRUidSensorServerChannelGroups ) );
+ if ( err == KErrNone )
+ {
+ err = repository->Get( iChannelInfo.iChannelType, channelGroup );
+ if ( err != KErrNone || channelGroup < TSensrvResourceChannelInfo::ESensrvChannelGroupNotDefined )
+ {
+ channelGroup = TSensrvResourceChannelInfo::ESensrvChannelGroupNotDefined;
+ }
+ }
+ else
+ {
+ ERROR_TRACE( ( _L( "Sensor Server - CSensrvChannel::ReadChannelGroup - Channel groups repository opening failed: %d" ), err ) );
+ }
+
+ // Cleanup repository
+ delete repository;
+ repository = NULL;
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ReadChannelGroup() - return %d" ), channelGroup ) );
+
+ return static_cast< TSensrvResourceChannelInfo::TSensrvChannelGroup >( channelGroup );
+ }
+
+// ---------------------------------------------------------------------------
+// Gets channel group
+// ---------------------------------------------------------------------------
+//
+TSensrvResourceChannelInfo::TSensrvChannelGroup CSensrvChannel::ChannelGroup()
+ {
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ChannelGroup()" ) ) );
+
+ if ( iChannelInfo.iChannelGroup == TSensrvResourceChannelInfo::ESensrvChannelGroupNotSolved )
+ {
+ iChannelInfo.iChannelGroup = ReadChannelGroup();
+ }
+
+ COMPONENT_TRACE( ( _L( "Sensor Server - CSensrvChannel::ChannelGroup() - return %d" ), iChannelInfo.iChannelGroup ) );
+
+ return iChannelInfo.iChannelGroup;
+ }