telephonyprotocols/pdplayer/src/pdptiermanager.cpp
changeset 0 3553901f7fa8
child 15 fc69e1e37771
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyprotocols/pdplayer/src/pdptiermanager.cpp	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,536 @@
+// Copyright (c) 2008-2009 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:
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include "pdptiermanager.h"
+#include "mbmsengine.h"
+#include "pdptiermanagerselector.h"
+#include <comms-infras/ss_log.h>
+#include <comms-infras/coretiermanagerstates.h>
+#include <comms-infras/coretiermanageractivities.h>
+#include <pcktcs.h>
+
+#include "pdpmcpr.h"
+
+#ifdef SYMBIAN_TRACE_ENABLE
+#define KPDPTierMgrTag KESockMetaConnectionTag
+_LIT8(KPDPTierMgrSubTag, "pdptiermgr");
+#endif
+
+using namespace Messages;
+using namespace MeshMachine;
+using namespace ESock;
+using namespace ConnectionServ;
+using namespace NetStateMachine;
+using namespace CommsDat;
+
+namespace PDPTierManagerActivities
+{
+DECLARE_DEFINE_ACTIVITY_MAP(stateMap)
+ACTIVITY_MAP_END_BASE(TMActivities, coreTMActivities)
+}
+
+
+CContextTypeChecker::CContextTypeChecker(RPacketService& aPacketService, MContextEventsObserver& aCallback):CActive(EPriorityStandard),
+	iPacketService(aPacketService), iCallback(aCallback)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CContextTypeChecker::~CContextTypeChecker()
+	{
+	iContextName = NULL;
+	}
+
+void CContextTypeChecker::Start(const TName* aContextName)
+	{
+	iContextName = aContextName;
+	iPacketService.EnumerateContextsInNif(iStatus, *iContextName, iCountInNif);
+	SetActive();
+	}
+
+void CContextTypeChecker::RunL()
+	{
+	User::LeaveIfError(iStatus.Int());
+	if (iCountInNif == 1) // This is a primary context
+		{
+		iCallback.PrimaryContextAddedL(iContextName);
+		}
+	else
+		{
+		iCallback.SecondaryContextAdded(iContextName);
+		}
+	}
+
+void CContextTypeChecker::DoCancel()
+	{
+	iPacketService.CancelAsyncRequest(EPacketEnumerateContextsInNif);
+	}
+
+TInt CContextTypeChecker::RunError(TInt aError)
+	{
+	// Report an error
+	iCallback.ContextTypeCheckingError(iContextName, aError);
+	return KErrNone; // Make ActiveScheduler happy
+	}
+
+CPrimaryContextsMonitor::CPrimaryContextsMonitor(RPacketService& aPacketService, MContentionObserver& aCallback) : CActive(EPriorityStandard),
+	iPacketService(aPacketService), iCallback(aCallback)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CPrimaryContextsMonitor::~CPrimaryContextsMonitor()
+	{
+	Cancel();
+	iContextMonitors.ResetAndDestroy();
+	delete iContextTypeChecker;
+	iAddedContextsNames.ResetAndDestroy();
+	}
+
+void CPrimaryContextsMonitor::StartL()
+	{
+	iContextTypeChecker = new(ELeave) CContextTypeChecker(iPacketService, *this);
+	iState = EEnumeratingContexts;
+	iPacketService.EnumerateNifs(iStatus, iInitialNifsCount);
+	SetActive();
+	}
+
+void CPrimaryContextsMonitor::PrimaryContextAddedL(const TName* aContextName)
+	{
+	// Create new status monitor for this context
+	StartContextStatusMonitoringL(*aContextName);
+	RemoveContextNameAndCheckNext(aContextName);
+	}
+
+void CPrimaryContextsMonitor::SecondaryContextAdded(const TName* aContextName)
+	{
+	// This is not a primary context, just delete its name.
+	RemoveContextNameAndCheckNext(aContextName);
+	}
+
+void CPrimaryContextsMonitor::RemoveContextNameAndCheckNext(const TName* aContextName)
+	{
+	TInt nameIndex = iAddedContextsNames.Find(aContextName);
+	__ASSERT_DEBUG(nameIndex != KErrNotFound, User::Invariant());
+	delete iAddedContextsNames[nameIndex];
+	iAddedContextsNames.Remove(nameIndex);
+
+	if (iAddedContextsNames.Count() > 1)
+		// Should be more than one here, coz we are waiting for new context added all the time,
+		// so the last one item is always empty.
+		{
+		iContextTypeChecker->Start(iAddedContextsNames[0]);
+		}
+	}
+
+void CPrimaryContextsMonitor::PrimaryContextDeleted(const CContextStatusMonitor* aContextStatusMonitor)
+	{
+	if (aContextStatusMonitor->IsPassedThroughActiveState())
+		{
+		iCallback.ContentionResolved();
+		}
+	DeleteContextStatusMonitor(aContextStatusMonitor);
+	}
+
+void CPrimaryContextsMonitor::ContextTypeCheckingError(const TName* aContextName, TInt aError)
+	{
+	RemoveContextNameAndCheckNext(aContextName);
+	ProcessError(aError);
+	}
+
+
+void CPrimaryContextsMonitor::ContextMonitoringError(const CContextStatusMonitor* aContextStatusMonitor, TInt aError)
+	{
+	DeleteContextStatusMonitor(aContextStatusMonitor);
+	ProcessError(aError);
+	}
+
+void CPrimaryContextsMonitor::DeleteContextStatusMonitor(const CContextStatusMonitor* aContextStatusMonitor)
+	{
+	TInt monitorIndex = iContextMonitors.Find(aContextStatusMonitor);
+	__ASSERT_DEBUG(monitorIndex != KErrNotFound, User::Invariant());
+	delete iContextMonitors[monitorIndex];
+	iContextMonitors.Remove(monitorIndex);
+	}
+
+void CPrimaryContextsMonitor::ProcessError(
+	#ifdef _DEBUG
+		TInt aError
+	#else	//remove compilation warning in release builds
+		TInt /*aError*/
+	#endif
+	)
+	{
+	__ASSERT_DEBUG(aError != KErrNone, User::Invariant());
+	__FLOG_STATIC1(KPDPTierMgrTag, KPDPTierMgrSubTag, _L("PDP context monitoring error: %d"), aError);
+	}
+
+void CPrimaryContextsMonitor::RunL()
+	{
+	User::LeaveIfError(iStatus.Int());
+	SwitchStateL();
+	RPacketService::TNifInfoV2Pckg nifInfoV2Pckg(iCurrentNifInfo);
+	switch(iState)
+		{
+		case EGettingInfo:
+			StartContextStatusMonitoringL(iCurrentNifInfo.iContextName);
+			iPacketService.GetNifInfo(iStatus, iCurrentNifIndex, nifInfoV2Pckg);
+			++iCurrentNifIndex;
+			SetActive();
+			break;
+		case EListening:
+			// All functions in RPacketService and RPacketContext,
+			// that can be used to check if context is primary, are asynchronous.
+			// We could not call them here, coz can miss some events from NotifyContextAdded
+			// So subscribe to NotifyContextAdded as soon as possible and check context
+			// type using CContextTypeChecker active object
+			TName *contextName = new (ELeave) TName;
+			CleanupStack::PushL(contextName);
+			iAddedContextsNames.AppendL(contextName);
+			CleanupStack::Pop(contextName);
+			// subscribe to NotifyContextAdded
+			iPacketService.NotifyContextAdded(iStatus, *contextName);
+			SetActive();
+			// if there are any items in iAddedContextsNames except that one that has been added above, i.e count > 1
+			// starting asynchronous context type checking
+			if (!iContextTypeChecker->IsActive() && iAddedContextsNames.Count()>1)
+				{
+				iContextTypeChecker->Start(iAddedContextsNames[0]);
+				}
+			break;
+		}
+	}
+void CPrimaryContextsMonitor::DoCancel()
+	{
+	switch(iState)
+		{
+		case EEnumeratingContexts:
+			iPacketService.CancelAsyncRequest(EPacketEnumerateNifs);
+			break;
+		case EGettingInfo:
+			iPacketService.CancelAsyncRequest(EPacketGetNifInfo);
+			break;
+		case EListening:
+			iPacketService.CancelAsyncRequest(EPacketNotifyContextAdded);
+			break;
+		}
+
+	}
+
+TInt CPrimaryContextsMonitor::RunError(TInt aError)
+	{
+	// Process an error
+	ProcessError(aError);
+	return KErrNone; // Make ActiveScheduler happy
+	}
+
+
+void CPrimaryContextsMonitor::SwitchStateL()
+	{
+	if (iState == EEnumeratingContexts)
+		{
+		if (iInitialNifsCount > 0)
+			{
+			iState = EGettingInfo;
+			}
+		else
+			{
+			iState = EListening;
+			}
+		}
+	else if (iState == EGettingInfo && iCurrentNifIndex == iInitialNifsCount)
+		{
+		StartContextStatusMonitoringL(iCurrentNifInfo.iContextName);
+		iState = EListening;
+		}
+	}
+
+void CPrimaryContextsMonitor::StartContextStatusMonitoringL(const TName& aContextName)
+	{
+	CContextStatusMonitor* newStatusMonitor = new (ELeave) CContextStatusMonitor(iPacketService, *this);
+	CleanupStack::PushL(newStatusMonitor);
+	iContextMonitors.AppendL(newStatusMonitor);
+	CleanupStack::Pop(newStatusMonitor);
+	newStatusMonitor->StartL(aContextName);
+	}
+
+CContextStatusMonitor::CContextStatusMonitor(RPacketService& aPacketService, MContextEventsObserver& aCallback):CActive(EPriorityStandard),
+	iPacketService(aPacketService), iCallback(aCallback)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CContextStatusMonitor::~CContextStatusMonitor()
+	{
+	Cancel();
+	iPacketContext.Close();
+	}
+
+TBool CContextStatusMonitor::StartL(const TName& aContextName)
+	{
+	iContextName.Copy(aContextName);
+	User::LeaveIfError(iPacketContext.OpenExistingContext(iPacketService, iContextName));
+	iPacketContext.GetStatus(iContextStatus);
+
+	if (iContextStatus == RPacketContext::EStatusDeleted)
+		{
+		return EFalse;
+		}
+
+	if (iContextStatus == RPacketContext::EStatusActive ||
+		iContextStatus == RPacketContext::EStatusSuspended ||
+		iContextStatus == RPacketContext::EStatusDeactivating)
+		{
+		iWasActive = ETrue;
+		}
+
+	iPacketContext.NotifyStatusChange(iStatus, iContextStatus);
+	SetActive();
+	return ETrue;
+	}
+
+void CContextStatusMonitor::RunL()
+	{
+	User::LeaveIfError(iStatus.Int());
+	if (iContextStatus == RPacketContext::EStatusActive)
+		{
+		iWasActive = ETrue;
+		}
+
+	if (iContextStatus == RPacketContext::EStatusDeleted)
+		{
+		iPacketContext.CancelAsyncRequest(EPacketContextNotifyStatusChange);
+		iCallback.PrimaryContextDeleted(this);
+		}
+	else
+		{
+		iPacketContext.NotifyStatusChange(iStatus, iContextStatus);
+		SetActive();
+		}
+	}
+
+void CContextStatusMonitor::DoCancel()
+	{
+	iPacketContext.CancelAsyncRequest(EPacketContextNotifyStatusChange);
+	}
+
+TInt CContextStatusMonitor::RunError(TInt aError)
+	{
+	iCallback.ContextMonitoringError(this, aError);
+	return KErrNone;
+	}
+
+CPdpContentionManager* CPdpContentionManager::NewL(const ESock::CTierManagerBase& aTierManager, RPacketService& aPacketService)
+	{
+	CPdpContentionManager* self = new (ELeave) CPdpContentionManager(aTierManager);
+	CleanupStack::PushL(self);
+	self->ConstructL(aPacketService);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CPdpContentionManager::CPdpContentionManager(const ESock::CTierManagerBase& aTierManager):
+CContentionManager(aTierManager)
+	{
+	}
+
+CPdpContentionManager::~CPdpContentionManager()
+	{
+	delete iPrimaryContextsMonitor;
+	}
+
+void CPdpContentionManager::ConstructL(RPacketService& aPacketService)
+	{
+	iPrimaryContextsMonitor = new (ELeave) CPrimaryContextsMonitor(aPacketService, *this);
+	}
+
+void CPdpContentionManager::StartMonitoringL()
+	{
+	if (iPrimaryContextsMonitor)
+		{
+		iPrimaryContextsMonitor->StartL();
+		}
+	}
+
+void CPdpContentionManager::ContentionResolved(const TContentionRequestItem& aContentionRequest, TBool aResult)
+	{
+	CPdpMetaConnectionProvider* pdpMcpr = static_cast<CPdpMetaConnectionProvider*>(aContentionRequest.iMcpr);
+	
+	pdpMcpr->ContentionResolved(aContentionRequest.iPendingCprId, aResult);
+	}
+
+void CPdpContentionManager::ContentionOccured(ESock::CMetaConnectionProviderBase& aMcpr)
+	{
+	CPdpMetaConnectionProvider& pdpMcpr = static_cast<CPdpMetaConnectionProvider&>(aMcpr);
+	
+	pdpMcpr.ContentionOccured();
+	}
+
+void CPdpContentionManager::ReportContentionAvailabilityStatus(ESock::CMetaConnectionProviderBase& aMcpr, const ESock::TAvailabilityStatus& aStatus) const
+	{
+	CPdpMetaConnectionProvider& pdpMcpr = static_cast<CPdpMetaConnectionProvider&>(aMcpr);
+	
+	pdpMcpr.ReportContentionAvailabilityStatus(aStatus);
+	}
+
+/**
+The NewL factory function for PDPTierManager.
+This function also acts as the single ECom entry point into this object.
+@param aFactory The  reference to CTierManagerFactoryBase
+@return CPDPTierManager*
+*/
+CPDPTierManager* CPDPTierManager::NewL(ESock::CTierManagerFactoryBase& aFactory)
+	{
+ 	CPDPTierManager* self = new(ELeave)CPDPTierManager(aFactory, PDPTierManagerActivities::stateMap::Self());
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/**
+Constructor for CPDPTierManager
+*/
+CPDPTierManager::CPDPTierManager(ESock::CTierManagerFactoryBase& aFactory,
+								const MeshMachine::TNodeActivityMap& aActivityMap)
+	:CCoreTierManager(aFactory,aActivityMap)
+	{
+	LOG_NODE_CREATE(KPDPTierMgrTag, CPDPTierManager);
+	}
+
+/**
+Descructor for CPDPTierManager
+*/
+CPDPTierManager::~CPDPTierManager()
+	{
+	LOG_NODE_DESTROY(KPDPTierMgrTag, CPDPTierManager);
+	delete iPdpContentionManager;
+	iPdpContentionManager = NULL;
+	if (iMBMSEngine)
+		{
+		iMBMSEngine->Cancel();
+		delete iMBMSEngine;
+		iMBMSEngine = NULL;
+		}
+	}
+
+/**
+Create selector for this Tier.
+@return MProviderSelector*
+*/
+MProviderSelector* CPDPTierManager::DoCreateProviderSelectorL(const Meta::SMetaData& aSelectionPreferences)
+	{
+	__CFLOG_VAR((KPDPTierMgrTag, KPDPTierMgrSubTag, _L8("CPdpTierManager[%08x]::DoSelectProvider()"), this));
+	return TPdpSelectorFactory::NewSelectorL(aSelectionPreferences);
+	}
+
+/**
+ConstructL function of CPDPTierManager.
+This function is used to retrieve tsy name.
+@return void
+*/
+void CPDPTierManager::ConstructL()
+	{
+	__CFLOG_VAR((KPDPTierMgrTag, KPDPTierMgrSubTag, _L8("ConstructL::In CPDPTierManager")));
+	iMBMSEngine = CMBMSEngine::NewL(NodeId(), *this);
+	}
+
+/**
+ The PacketServiceAttachedCallbackL is a callback function.
+ It's called by MBMSEngine when RPacketService has been attached.
+*/
+void CPDPTierManager::PacketServiceAttachedCallbackL()
+	{
+	if (!iPdpContentionManager)
+		{
+		iPdpContentionManager = CPdpContentionManager::NewL(*this, iMBMSEngine->GetRPacketService());
+		}
+	static_cast<CPdpContentionManager*>(iPdpContentionManager)->StartMonitoringL();
+	}
+
+/**
+The ReceivedL function for PDPTierManager.
+The messages from RConnectionServ are received in ReceivedL function.
+@param aCFMessage The  reference to Messages::TSignatureBase
+@return TInt*
+*/
+void CPDPTierManager::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
+	{
+	//TODO I think that the generic TCancel handling will do this - so perhaps remove this and CancelAndRemoveFromRequestList!
+	if (aMessage.IsMessage<TEBase::TCancel>())
+		{
+		TRAPD(err, iMBMSEngine->CancelAndRemoveFromRequestListL(aSender));
+		if (err == KErrNone)
+			{
+			aMessage.ClearMessageId();
+			}
+		else if (err != KErrNotFound)
+			{
+			User::Leave(err);
+			}
+		// err == KErrNotFound
+		// Probably this is not cancel for MBMS request but cancel for PDP availability notification request
+		// It will be processed by core TM then.
+		}
+
+	if (aMessage.IsMessage<TCFTierStatusProvider::TTierNotificationRegistration>())
+		{
+		TCFTierStatusProvider::TTierNotificationRegistration* msgTNR = message_cast<TCFTierStatusProvider::TTierNotificationRegistration>(&aMessage);
+
+		const Messages::TNodeSignal::TMessageId requestType = TCFTierStatusProvider::TTierNotificationRegistration::Id();
+		CRefCountOwnedParameterBundle* requestBundleOwner = msgTNR->iBundle;
+
+		TRAPD(err, iMBMSEngine->AddToRequestListL(FindClient(aSender), aSender, requestType, requestBundleOwner));
+		if (err == KErrNone)
+			{
+			aMessage.ClearMessageId();
+			}
+		else if (err != KErrArgument)
+			{
+			User::Leave(err);
+			}
+		// err == KErrArgument
+		// Probably this is not MBMS notification request but PDP availability notification request
+		// It will be processed by core TM then.
+		}
+
+	TNodeContext<CPDPTierManager> ctx(*this, aMessage, aSender, aRecipient);
+	CCoreTierManager::Received(ctx);
+	User::LeaveIfError(ctx.iReturn);
+	}
+
+TBool CPDPTierManager::HandleContentionL(ESock::CMetaConnectionProviderBase* aMcpr, Messages::TNodeId& aPendingCprId, TUint aPriority)
+	{
+	User::LeaveIfNull(iMBMSEngine);
+	if (!iPdpContentionManager)
+		{
+		iPdpContentionManager = CPdpContentionManager::NewL(*this, iMBMSEngine->GetRPacketService());
+		}
+	return iPdpContentionManager->HandleContentionL(aMcpr, aPendingCprId, aPriority);
+	}
+
+TBool CPDPTierManager::IsUnavailableDueToContention(const ESock::CMetaConnectionProviderBase* aMetaConnectionProvider) const
+	{
+	if (!iPdpContentionManager)
+		return EFalse;
+	return iPdpContentionManager->IsUnavailableDueToContention(aMetaConnectionProvider);
+	}
+
+