networkprotocolmodules/suplprotocolmodule/SuplProtocol/src/suplnetworkinfohandler.cpp
changeset 0 9cfd9a3ee49c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocolmodules/suplprotocolmodule/SuplProtocol/src/suplnetworkinfohandler.cpp	Tue Feb 02 01:50:39 2010 +0200
@@ -0,0 +1,544 @@
+// 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:
+// Object to monitor the ETel networki information needed by SUPL
+// protocol module
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @deprecated
+*/
+
+#include <e32debug.h>
+
+#include "suplnetworkinfohandler.h"
+#include <e32base.h>
+#include <e32property.h>
+#include <etelmm.h>
+#include <rsshared.h>
+#include "supldevloggermacros.h"
+
+using namespace CommsDat;
+
+const TUint KMaxCellIdOrLac = 65535;
+const TUint KMaxMccOrMnc = 999;
+
+
+/**
+*/
+CSuplNetworkInfoHandler::CSuplNetworkInfoHandler(MSuplNetworkInfoObserver& aObserver) :
+	CActive(EPriorityStandard),
+	iObserver(aObserver),
+	iState(EStateNull),
+	iNetworkInfoPckg(iNetworkInfo),
+	iOnStoreInfoPckg(iOnStoreInfo),
+	iOnStoreEntryPckg(iOnStoreEntry)	
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::CSuplNetworkInfoHandler() Begin\n");
+	CActiveScheduler::Add(this);
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::CSuplNetworkInfoHandler() End\n");
+	}
+
+/**
+*/	
+CSuplNetworkInfoHandler::~CSuplNetworkInfoHandler()
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::~CSuplNetworkInfoHandler() Begin\n");
+	Cancel();
+	
+	if (iTimingAdvSupport)
+		{
+		delete iCellInfoHandler;
+		iCellPhone.Close();
+		}
+	
+	iOnStore.Close();
+	
+	iNetPhone.Close();
+	iTelServer.Close();
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::~CSuplNetworkInfoHandler() End\n");
+	}
+
+/**
+*/	
+CSuplNetworkInfoHandler* CSuplNetworkInfoHandler::NewL(MSuplNetworkInfoObserver& aObserver)
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::NewL() Begin\n");
+	CSuplNetworkInfoHandler* self = new (ELeave) CSuplNetworkInfoHandler(aObserver);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::NewL() End\n");
+	return self;
+	}
+
+/**
+*/
+void CSuplNetworkInfoHandler::ConstructL()
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::ConstructL() Begin\n");
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::ConstructL() End\n");
+	}
+
+/**
+*/
+void CSuplNetworkInfoHandler::StartGettingNetworkInfoL()
+{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::StartGettingNetworkInfo() Begin\n");
+
+	//Attempt to connect to the ETel Server.  This will start C32Start if
+	//it has not already been started by the startup routine.
+	User::LeaveIfError(iTelServer.Connect());
+		
+	// Check if the Comms Process RootServer has started
+	iConfigurationProperty.Attach(KUidSystemCategory, RootServer::KUidC32StartPropertyKey.iUid);
+	TInt propertyValue = RootServer::EInitialising;
+	TInt propertyResult = iConfigurationProperty.Get(propertyValue);
+		
+	if(propertyValue < RootServer::EConfigurationComplete)
+		{
+		iState = EStateInitializing;
+		iConfigurationProperty.Subscribe(iStatus);
+		SetActive();
+		}
+	else
+		{
+		// Attempt to get network information
+		GetNetworkInfoL();
+		}
+
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::StartGettingNetworkInfo() End\n");
+}
+
+/** 
+*/
+void CSuplNetworkInfoHandler::GetNetworkInfoL()
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetNetworkInfoL() Begin\n");
+	InitialisePhonesL();
+	
+	// Connected to ETel successfully
+	if (iTimingAdvSupport)
+		{
+		// Instantiate the active object that monitors changes to 
+		// Timing Advance passing to it the initialized RMobilePhone
+		// and the observer interested in Timing Advance.
+		iCellInfoHandler = CSuplCellInfoHandler::NewL(iObserver,iCellPhone);
+		iCellInfoHandler->StartGettingCellInfo();
+		}
+
+	// Get the network info
+	iState = EStateGettingNetInfo;
+	iNetPhone.GetCurrentNetwork(iStatus, iNetworkInfoPckg, iLocArea);
+	SetActive();
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetNetworkInfoL() End\n");
+	}
+
+/**
+*/
+void CSuplNetworkInfoHandler::RunL()
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::RunL() Begin\n");
+	User::LeaveIfError(iStatus.Int());
+	
+	switch (iState)
+		{
+		case EStateInitializing:
+			{
+			TInt propertyValue = RootServer::EInitialising; // set to safe state
+			TInt propertyResult = iConfigurationProperty.Get(propertyValue);
+			
+			if(propertyValue != RootServer::EConfigurationComplete)
+				{
+				iConfigurationProperty.Subscribe(iStatus);
+				SetActive();
+				}
+			else
+				{
+				iConfigurationProperty.Cancel();
+				GetNetworkInfoL();
+				}
+			break;
+			}
+
+		case EStateGettingNetInfo:
+			{
+			if(ValidateNetInfo())
+				{
+				iObserver.NetInfoResults(iNetworkInfo, iLocArea);
+				}
+			if(iHomeNetworkInfoSupport)
+				{
+				GetMccMnc();
+				}
+			else if(iMsisdnSupport)
+				{
+				GetMsisdnStoreInfo();
+				}
+			else
+				{
+				MonitorNetworkChange();
+				}
+			break;	
+			}
+		
+		case EStateGettingMccMnc:
+			{
+			if(iStatus==KErrNone && ValidateNetInfo())
+				{
+				//All checks are done in ValidateNetInfo
+				TUint mcc = 0;
+				TLex lex(iNetworkInfo.iCountryCode);
+				lex.Val(mcc);
+				TUint mnc = 0;
+				lex.Assign(iNetworkInfo.iNetworkId);
+				lex.Val(mnc);
+				iObserver.HomeMccMncResult(mcc, mnc);
+				}
+			if(iMsisdnSupport)
+				{
+				GetMsisdnStoreInfo();
+				}
+			else
+				{
+				MonitorNetworkChange();
+				}
+			break;
+			}
+			
+		case EStateGettingMsisdnStoreInfo:
+			{
+			if(iStatus==KErrNone && iOnStoreInfo.iUsedEntries>0 && 
+					(iOnStoreInfo.iCaps & RMobilePhoneStore::KCapsIndividualEntry))
+				{
+				//Currently we simply use the first record to get the MSISDN 
+				iOnStoreEntry.iIndex = 1;
+				GetMsisdnStoreEntry();
+				}
+			else
+				{
+				iMsisdnSupport = EFalse;
+				MonitorNetworkChange();
+				}
+			break;
+			}
+		
+		case EStateGettingMsisdnStoreEntry:
+			{
+			if(iStatus==KErrNone)
+				{
+				iObserver.MsisdnResult(iOnStoreEntry.iNumber.iTelNumber);
+				}
+			else
+				{
+				iMsisdnSupport = EFalse;
+				}
+			MonitorNetworkChange();	
+			break;
+			}
+			
+		case EStateNetInfoChangeMon:
+			{
+			if(ValidateNetInfo())
+				{
+				iObserver.NetInfoResults(iNetworkInfo, iLocArea);
+				}
+			MonitorNetworkChange(); // Keep monitoring
+			break;				
+			}
+		
+		default:
+			break;		
+		}
+	
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::RunL() End\n");
+	}
+
+/**
+*/	
+void CSuplNetworkInfoHandler::DoCancel()
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::DoCancel() Begin\n");
+	//Check to see what stage we in are to find out what to cancel
+	switch (iState)
+		{
+		case EStateInitializing:
+			{
+			iConfigurationProperty.Cancel();
+			break;				
+			} 
+		case EStateGettingNetInfo:
+			{
+			iNetPhone.CancelAsyncRequest(EMobilePhoneGetCurrentNetwork);
+			break;
+			}
+		case EStateGettingMccMnc:
+			{
+			iNetPhone.CancelAsyncRequest(EMobilePhoneGetHomeNetwork);
+			break;
+			}
+		case EStateNetInfoChangeMon:
+			{
+			iNetPhone.CancelAsyncRequest(EMobilePhoneNotifyCurrentNetworkChange);
+			break;
+			}
+			
+		default:
+			break;
+		}
+	
+	if(iCellInfoHandler)
+		{
+		iCellInfoHandler->Cancel();
+		}
+	
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::DoCancel() End\n");
+	}
+
+/**
+*/	
+TInt CSuplNetworkInfoHandler::RunError(TInt /*aError*/)
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::DoCancel() Begin\n");
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::DoCancel() End\n");
+	return KErrNone;
+	}
+
+/** Asynchronous request to obtain MCC and MNC
+*/
+void CSuplNetworkInfoHandler::GetMccMnc()
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetMccMnc() Begin\n");
+	iState = EStateGettingMccMnc;
+	iNetPhone.GetHomeNetwork(iStatus, iNetworkInfoPckg);
+	SetActive();
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetMccMnc() End\n");
+	}
+
+/** Asynchronous request to obtain Msisdn - getting store info.
+*/
+void CSuplNetworkInfoHandler::GetMsisdnStoreInfo()
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetMsisdnStoreInfo() Begin\n");
+	iState = EStateGettingMsisdnStoreInfo;
+	iOnStore.GetInfo(iStatus, iOnStoreInfoPckg);
+	SetActive();
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetMsisdnStoreInfo() End\n");
+	}
+
+/** Asynchronous request to obtain Msisdn - getting store entry.
+*/
+void CSuplNetworkInfoHandler::GetMsisdnStoreEntry()
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetMsisdnStoreEntry() Begin\n");
+	iState = EStateGettingMsisdnStoreEntry;
+	//please note that the index is set in RunL for iOnStoreEntryPckg
+	iOnStore.Read(iStatus, iOnStoreEntryPckg);
+	SetActive();
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetMsisdnStoreEntry() End\n");
+	}
+
+
+/** Asychronous request to obtain notifications
+of change in the current network data
+*/
+void CSuplNetworkInfoHandler::MonitorNetworkChange()
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::MonitorNetworkChange() Begin\n");
+	iState = EStateNetInfoChangeMon;
+	iNetPhone.NotifyCurrentNetworkChange(iStatus, iNetworkInfoPckg, iLocArea);
+	SetActive();
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::MonitorNetworkChange() End\n");
+	}
+
+/** Retrieves the name of the .tsy to use from CommDB/CommsDat
+
+Hard-coded to use the .tsy file specified in the ModemBearerEntry
+which is specified (by index) by the KCDTIdModemPhoneServicesSMS
+setting in the global settings table.
+*/
+void CSuplNetworkInfoHandler::GetCommDbTSYnameL(TDes& aTsyName)
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetCommDbTSYnameL() Begin\n");
+	CMDBSession* db = CMDBSession::NewLC(KCDLatestVersion);
+
+	CMDBField<TUint32>* globalSettingField = new(ELeave) CMDBField<TUint32>(KCDTIdModemPhoneServicesSMS);
+	CleanupStack::PushL(globalSettingField);
+
+	globalSettingField->SetRecordId(1);
+	globalSettingField->LoadL(*db);
+	TUint32 modemId = *globalSettingField;
+
+	CMDBField<TDesC>* tsyField = new(ELeave) CMDBField<TDesC>(KCDTIdTsyName);
+	CleanupStack::PushL(tsyField);
+
+	tsyField->SetRecordId(modemId);
+	tsyField->LoadL(*db);
+
+	aTsyName = *tsyField;
+	CleanupStack::PopAndDestroy(3, db); // db, tsyField & globalSettingField
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::GetCommDbTSYnameL() End\n");
+	}
+
+/** Finds and opens the phones to be used to monitor current network
+info and cell info (timing advance).
+
+This method also checks if the TSY can provide the different
+bits of information needed by SUPL from ETEL: current and home network
+information, cell ID information (for Timing Advance).
+	
+@leave	Leaves if underlying ETEL.DLL returns error,
+or if we can't find a suitable Phone or can't open it.
+*/
+void CSuplNetworkInfoHandler::InitialisePhonesL()
+	{
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::InitialisePhonesL() Begin\n");
+	TInt err(KErrNone);
+		
+	// Read the name of the .tsy to load from CommDB
+	TBuf<KCommsDbSvrMaxFieldLength> tsyName;
+	GetCommDbTSYnameL(tsyName);
+
+	// Load .tsy into ETel
+	User::LeaveIfError(iTelServer.LoadPhoneModule(tsyName));
+
+	// Find available phones; check that the one we requested 
+	// to be loaded is there.
+	TInt phoneIndex(0);
+	User::LeaveIfError(iTelServer.EnumeratePhones(phoneIndex));
+	while(phoneIndex-->0)
+		{
+		TName searchTsyName;
+		// Check whether this phone belongs to loaded TSY
+		if ((iTelServer.GetTsyName(phoneIndex, searchTsyName) == KErrNone) 
+			&& (searchTsyName.CompareF(tsyName) == KErrNone)) 
+			break;
+		}
+		
+	// Open a phone to be used for monitoring the network.
+	RTelServer::TPhoneInfo phoneInfo;
+	User::LeaveIfError(iTelServer.GetPhoneInfo(phoneIndex, phoneInfo));	
+	User::LeaveIfError(iNetPhone.Open(iTelServer, phoneInfo.iName));
+	
+	// Check that the phone is ready to be used.	
+	RPhone::TStatus status;
+	User::LeaveIfError(iNetPhone.GetStatus(status));
+	if(status.iModemDetected != RPhone::EDetectedPresent)
+		{		
+		err = iNetPhone.Initialise();
+		if(err != KErrNone)
+			{
+			iNetPhone.Close();
+			User::Leave(err);
+			}
+		}	
+
+	// Check that network info can be accessed
+	TUint32 networkCaps;
+	User::LeaveIfError(iNetPhone.GetNetworkCaps(networkCaps));
+	if (!(networkCaps & RMobilePhone::KCapsGetCurrentNetwork
+		  && networkCaps & RMobilePhone::KCapsNotifyCurrentNetwork))
+		{
+		// No point in continuing
+		err = KErrNotSupported;
+		}
+	else
+		{
+		if(networkCaps & RMobilePhone::KCapsGetHomeNetwork)
+			{
+			iHomeNetworkInfoSupport = ETrue;
+			}
+		
+		// Network info can be accessed.
+
+		// Check if Timing Advance is supported by the TSY
+		// (If it isn't, that is NOT a critical error, so donnot
+		// change the returned error code)
+		iTimingAdvSupport = EFalse;
+		iTelServer.IsSupportedByModule(tsyName, KEtelFuncCellInfo, iTimingAdvSupport);
+		if (iTimingAdvSupport)
+			{
+			// Open a new phone for Get/NotifyCellInfo() requests			
+			if (KErrNone ==	iCellPhone.Open(iTelServer, phoneInfo.iName))
+				{
+				// Check that iCellPhone is ready to be used	
+				if(KErrNone == iCellPhone.GetStatus(status))
+					{
+					if(status.iModemDetected != RPhone::EDetectedPresent)
+						{
+						if(KErrNone != iCellPhone.Initialise())
+							{
+							// Unable to initialise phone
+							iCellPhone.Close();
+							iTimingAdvSupport = EFalse;
+							}
+						}
+					}
+				else
+					{
+					// Unable to get phone status
+					iCellPhone.Close();
+					iTimingAdvSupport = EFalse;					
+					}
+				}
+			else
+				{
+				// Unable to open phone
+				iTimingAdvSupport = EFalse;	
+				}
+			}
+		}
+	User::LeaveIfError(err);
+	
+	iMsisdnSupport = EFalse;
+	if(iTelServer.IsSupportedByModule(tsyName, KETelFuncMobileOwnNumberStore, iMsisdnSupport)==KErrNone && 
+			iMsisdnSupport)
+		{
+		if(iOnStore.Open(iNetPhone)!=KErrNone)
+			{
+			iMsisdnSupport=EFalse;
+			}
+		}
+	
+	SUPLLOG(ELogP1, "CSuplNetworkInfoHandler::InitialisePhonesL() End\n");
+	}
+
+/**
+Checks and fixes if necessary the network info
+*/
+TBool CSuplNetworkInfoHandler::ValidateNetInfo()
+	{
+	TUint val = 0;
+	TLex lex(iNetworkInfo.iCountryCode);
+	TInt err = lex.Val(val);
+	if(err!=KErrNone || val > KMaxMccOrMnc)
+		{
+		return EFalse;
+		}
+	lex.Assign(iNetworkInfo.iNetworkId);
+	err=lex.Val(val);
+	if(err!=KErrNone || val > KMaxMccOrMnc)
+		{
+		return EFalse;
+		}
+			
+	if(iLocArea.iAreaKnown && (iLocArea.iLocationAreaCode > KMaxCellIdOrLac || 
+			iLocArea.iCellId > KMaxCellIdOrLac))
+		{
+		return EFalse;
+		}
+	return ETrue;
+	}