sensorservices/sensorserver/src/server/sensrvchannel.cpp
changeset 0 4e1aa6a622a0
child 21 ccb4f6b3db21
--- /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;
+    }