telephonyprotocols/pdplayer/src/pdp_contention.cpp
changeset 69 b982c3e940f3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyprotocols/pdplayer/src/pdp_contention.cpp	Tue Sep 14 17:55:14 2010 +0100
@@ -0,0 +1,372 @@
+// Copyright (c) 2010 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 "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "pdp_contentionTraces.h"
+#endif
+
+
+#include <pdpmcpr.h>
+#include <pdp_contention.h>
+#include <mbmsengine.h>
+#include <etelpckt.h>
+#include <pcktcs.h>
+
+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(TInt aError)
+    {
+    __ASSERT_DEBUG(aError != KErrNone, User::Invariant());
+    OstTraceDef1(OST_TRACE_CATEGORY_DEBUG, TRACE_INTERNALS, CPRIMARYCONTEXTSMONITOR_PROCESSERROR_1, ("PDP context monitoring error: %d"), aError);
+    (void)aError;  //needed for debug builds 
+    }
+
+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));
+    User::LeaveIfError(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);
+    }
+