diff -r 000000000000 -r 72b543305e3a mobilemessaging/smum/src/MsgSimSCNumberDetector.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mobilemessaging/smum/src/MsgSimSCNumberDetector.cpp Thu Dec 17 08:44:11 2009 +0200 @@ -0,0 +1,555 @@ +/* +* Copyright (c) 2002 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: +* An active object class which takes care of reading the possible new +* service centres from SIM and adds them to pda-side Sms Settings. +* +*/ + + + +// INCLUDE FILES +#include // for CMtmUiRegistry +#include +#include +#include //CSmsSettings +#include // KErrGsmSMSSimBusy +#include +#include +#include +#include // Keys + +#include "SmumStartUpMonitor.h" +#include "SmumUtil.h" // SmumUtil +#include "MsgSimSCNumberDetector.h" +#include "SmumLogging.h" +#include "smsui.pan" // for panics + +// CONSTANTS +const TInt KMaxNameLength = 60; +const TInt KSmumGranularity = 4; +const TInt KSmumRetryCount = 20; +const TInt KSmumRetryDelay = 5000000; // 5 secs +const TInt KSmumSMSPid = 50; +// ================= MEMBER FUNCTIONS ======================= + +/* +* Symbian OS 2 phase construction and initialization. Note that operation that is returned is already active. +* A client will be notified via aClientStatus when the operation terminates. +*/ +EXPORT_C CMsgSimOperation* CMsgSimOperation::NewL( TRequestStatus& aClientStatus ) + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::NewL") + + CMsgSimOperation* self = new ( ELeave ) CMsgSimOperation( aClientStatus ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + SMUMLOGGER_LEAVEFN("CMsgSimOperation::NewL") + + return self; + } + +// C++ constructor which initializes the active object with a default priority and adds it to the active scheduler. +// C++ constructor can NOT contain any code, that +// might leave. +CMsgSimOperation::CMsgSimOperation( TRequestStatus& aStatus, TInt aPriority ) +: CActive( aPriority ), iClientStatus( &aStatus ), iRetryCount( 0 ) + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::CMsgSimOperation") + CActiveScheduler::Add( this ); + SMUMLOGGER_LEAVEFN("CMsgSimOperation::CMsgSimOperation") + } + +// Symbian OS default constructor can leave. +void CMsgSimOperation::ConstructL() + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::ConstructL") + + // initialise + iMsvSession = CMsvSession::OpenSyncL( *this ); // have to be sync; actual active object is started right after this, not in HandleSessionEventL + iClientRegistry = CClientMtmRegistry::NewL( *iMsvSession ); // get client mtm registry + iSmsClientMtm = STATIC_CAST( CSmsClientMtm*, iClientRegistry->NewMtmL( KUidMsgTypeSMS )); // get smcm object + + SMUMLOGGER_WRITE("ConstructL - Basic initialising ok, next connecting to Shared Data") + // Start the System state monitor + iStartupMonitor = CSmumStartUpMonitor::NewL( this ); + // Client status can be set pending only if we don't leave + *iClientStatus = KRequestPending; // activate the active object + // StartL() is called when iStartupMonitor ActiveObject completes + //Check is sms servicecenter fetched in every boot + iCheckSimScAlways = ( SmumUtil::CheckVariationFlagsL( KCRUidMuiuVariation, KMuiuSmsFeatures ) & + KSmsFeatureIdCheckSimAlways ); + SMUMLOGGER_LEAVEFN("CMsgSimOperation::ConstructL") + } + +// C++ virtual destructor +CMsgSimOperation::~CMsgSimOperation() + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::~CMsgSimOperation") + + Cancel(); // make sure that this object is not left on the active scheduler. + delete iSimOperation; + delete iSmsClientMtm; + delete iClientRegistry; + delete iMsvSession; + delete iStartupMonitor; + iStartupMonitor = NULL; + iClientStatus = NULL; + + SMUMLOGGER_LEAVEFN("CMsgSimOperation::~CMsgSimOperation") + } + +// ---------------------------------------------------- +// CMsgSimOperation::StartL +// This function issues request and activates the object +// +// ---------------------------------------------------- +void CMsgSimOperation::StartL() + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::StartL") + // Retry is used to define the times ReadSimParamsL() is called + iRetryCount++; + SMUMLOGGER_WRITE_FORMAT("StartL - iRetryCount :%d", iRetryCount) + + SMUMLOGGER_WRITE("StartL - BootState ok, proceed with SMSC fetch") + // start the real sim reading operation + iSimOperation = iSmsClientMtm->ReadSimParamsL( iStatus ); + SetActive(); + + SMUMLOGGER_LEAVEFN("CMsgSimOperation::StartL") + } + +// ---------------------------------------------------- +// CMsgSimOperation::CompleteRequest +// +// ---------------------------------------------------- +void CMsgSimOperation::CompleteRequest( TInt aValue ) + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::CompleteRequest") + + __ASSERT_DEBUG( !IsActive(), Panic( ESimOperationPanicRequestAlreadyActive )); + TRequestStatus* myRequestStatus = &iStatus; + User::RequestComplete( myRequestStatus, aValue ); + if( !IsActive() ) + { + SetActive(); + } + + SMUMLOGGER_LEAVEFN("CMsgSimOperation::CompleteRequest") + } + +// ---------------------------------------------------- +// CMsgSimOperation::CompleteClientRequest +// +// ---------------------------------------------------- +void CMsgSimOperation::CompleteClientRequest( TInt aValue ) + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::CompleteClientRequest") + + TBool haveClientRequestStatus = HaveClientRequestStatus(); + __ASSERT_DEBUG( haveClientRequestStatus, Panic( ESimOperationPanicClientsRequestAlreadyCompleted )); + // So that we don't attempt to complete the clients request again in the future + if ( haveClientRequestStatus ) + { + User::RequestComplete( iClientStatus, aValue ); + iClientStatus = NULL; + } + + SMUMLOGGER_LEAVEFN("CMsgSimOperation::CompleteClientRequest") + } + +// ---------------------------------------------------- +// CMsgSimOperation::HaveClientRequestStatus +// +// ---------------------------------------------------- +TBool CMsgSimOperation::HaveClientRequestStatus() const + { + SMUMLOGGER_WRITE("CMsgSimOperation::HaveClientRequestStatus") + return (iClientStatus != NULL); + } + +// ---------------------------------------------------- +// CMsgSimOperation::Panic +// +// ---------------------------------------------------- +void CMsgSimOperation::Panic(TSimOperationPanic aPanic) + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::Panic") + + _LIT(KSimOpPanicCategory, "SIMOP"); + SMUMLOGGER_WRITE_FORMAT("Panic - Panic :%d", aPanic) + User::Panic(KSimOpPanicCategory, aPanic); + + SMUMLOGGER_LEAVEFN("CMsgSimOperation::Panic") + } + +// ---------------------------------------------------- +// CMsgSimOperation::RunL +// Active object RunL method is called when the request (sim params reading operation) has been completed +// +// ---------------------------------------------------- +void CMsgSimOperation::RunL() + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::RunL") + + TInt error = iStatus.Int(); + SMUMLOGGER_WRITE_FORMAT("RunL - 1st error check :%d", error) + if ( error == KErrNone ) + { // continue if sim reading operation completed ok + TRAP( error, DoRunL()); + } + + SMUMLOGGER_WRITE_FORMAT("RunL - 2nd error check :%d", error) + // if problems with above; retry + TInt maxRetryCount = KSmumRetryCount; + if ( error == KErrTimedOut ) + { + maxRetryCount = KSmumRetryCount/10; // no use to retry many times if timed out already + } + if ( error != KErrNone /*KErrGsmSMSSimBusy*/ && iRetryCount <= maxRetryCount ) + { + SMUMLOGGER_WRITE("RunL - Retrying") + // first cancel the current simOp if still ongoing + if ( iSimOperation ) + { + SMUMLOGGER_WRITE("RunL - Deleting SIM operation") + iSimOperation->Cancel(); + delete iSimOperation; + iSimOperation = NULL; + } + // wait a bit and actual retry + User::After( KSmumRetryDelay ); + StartL(); + return; + } + + // Once the 'real' operation has completed, we inform the + // client of the result + if ( HaveClientRequestStatus() ) + { + SMUMLOGGER_WRITE("RunL - Completing client request") + CompleteClientRequest( error ); + } + + SMUMLOGGER_LEAVEFN("CMsgSimOperation::RunL") + } + +// ---------------------------------------------------- +// CCMsgSimOperation::DoRunL +// +// ---------------------------------------------------- +void CMsgSimOperation::DoRunL() + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::DoRunL") + + TIntBuf progressBuf; + progressBuf.Copy( iSimOperation->ProgressL()); + TInt error = progressBuf(); + SMUMLOGGER_WRITE_FORMAT("DoRunL - Error check :%d", error) + + if ( error == KErrNone ) // check operation status + { + CMobilePhoneSmspList* centersList = iSimOperation->ServiceCentersLC(); + TInt count = centersList->Enumerate(); // How many centre numbers are there on the SIM card? + SMUMLOGGER_WRITE_FORMAT("DoRunL - Amount of SIM SMSCs :%d", count ) + TBool emailFeatureSupported = SmumUtil::CheckEmailOverSmsSupportL(); + TBool emailEntryFound( EFalse ); + + // Check the service centre situation even if there are no service centres on SIM! + // If there are none, and only usage of service centre SIMs is allowed, all must + // be removed and the SMS service will be disabled. + + TInt numSCAddresses( 0 ); + iSmsClientMtm->SwitchCurrentEntryL( iSmsClientMtm->ServiceId() ); // load SMS settings + CMsvEntry& service = iSmsClientMtm->Entry(); + // load settings + CSmsSettings* smsSettings = CSmsSettings::NewLC(); + CSmsAccount* smsAccount = CSmsAccount::NewLC(); + smsAccount->LoadSettingsL( *smsSettings ); + TBool newDefault = EFalse; + TInt newDefaultIndex = -1; + + // Check if Only Sim SC's variation is on + if ( SmumUtil::CheckVariationFlagsL( KCRUidMuiuVariation, KMuiuSmsFeatures ) & + KSmsFeatureIdSimServiceCentresOnly ) + { + // Remove all old SMSC's + SMUMLOGGER_WRITE("DoRunL - Only Sim SC's - Deleting old ones->" ) + numSCAddresses = smsSettings->ServiceCenterCount(); + SMUMLOGGER_WRITE_FORMAT("DoRunL - Amount of old SMSC's: #%d", numSCAddresses ) + for ( TInt j = numSCAddresses; j > 0; j-- ) + { + smsSettings->RemoveServiceCenter( j - 1 ); + } + #ifdef _DEBUG + numSCAddresses = smsSettings->ServiceCenterCount(); + SMUMLOGGER_WRITE_FORMAT("DoRunL - Amount of SMSC's now: #%d", numSCAddresses ) + #endif // _DEBUG + } + + SMUMLOGGER_WRITE("DoRunL - Ready for looping SMSCs") + for ( TInt i = 0; i < count; i++ ) // add all centres from sim to sms settings + { + SMUMLOGGER_WRITE_FORMAT("DoRunL - SMSC #%d", i) + RMobileSmsMessaging::TMobileSmspEntryV1 entry; + entry = centersList->GetEntryL( i ); + TBool duplicateFound = EFalse; + + SMUMLOGGER_WRITE_FORMAT("DoRunL - SMSC Name: %S", &entry.iText ); + SMUMLOGGER_WRITE_FORMAT("DoRunL - SMSC Address: %S", &entry.iServiceCentre.iTelNumber ); + // If empty tel number field, don't add + if ( entry.iServiceCentre.iTelNumber == KNullDesC ) + { + SMUMLOGGER_WRITE_FORMAT("DoRunL - No number in SMSC #%d", i) + continue; + } + //Check is number already in cenrep + //Get default SC from phone settings for later use + TBuf defaultSmsCenterNb;; + TInt defaultSCIndex = smsSettings->DefaultServiceCenter(); + if ( defaultSCIndex > -1 ) + { + defaultSmsCenterNb = smsSettings->GetServiceCenter( defaultSCIndex ).Address(); + } + if ( iCheckSimScAlways && i == 0 ) + { + //Check is number already in cenrep + TBuf previousSmsCenterNb; + CRepository* cenRepSession = CRepository::NewLC( KCRUidSmum ); + cenRepSession->Get( KSmumPreviousSimSmscNumber, previousSmsCenterNb ); + + //Check was there different SMSC in cenrep and default SMSC in settings. + if ( entry.iServiceCentre.iTelNumber == previousSmsCenterNb && + entry.iServiceCentre.iTelNumber == defaultSmsCenterNb && + smsSettings->ServiceCenterCount() != 0 ) + { + SMUMLOGGER_WRITE_FORMAT("DoRunL - number #%d already in cenrep/settings", i) + CleanupStack::PopAndDestroy( cenRepSession ); + continue; + } + else + { + SMUMLOGGER_WRITE_FORMAT("DoRunL - number #%d not in cenrep/settings", i) + cenRepSession->Set( KSmumPreviousSimSmscNumber, entry.iServiceCentre.iTelNumber ); + CleanupStack::PopAndDestroy( cenRepSession ); + } + } + SMUMLOGGER_WRITE_FORMAT("DoRunL - Entry ProtocolId #%d", entry.iProtocolId) + // Check for Email settings + if ( emailFeatureSupported + && KSmumSMSPid == entry.iProtocolId + && !emailEntryFound ) // We'll take the first + { + SMUMLOGGER_WRITE_FORMAT("DoRunL - Email over sms entry #%d", i) + SmumUtil::WriteEmailOverSmsSettingsL( + entry.iServiceCentre.iTelNumber, + entry.iDestination.iTelNumber, + ETrue ); + emailEntryFound = ETrue; + } + else + { + // check if this SC is already in Sms settings + numSCAddresses = smsSettings->ServiceCenterCount(); + for ( TInt j = 0; j < numSCAddresses; j++ ) + { + if ( entry.iServiceCentre.iTelNumber == + smsSettings->GetServiceCenter( j ).Address() ) + { + SMUMLOGGER_WRITE_FORMAT("DoRunL - Duplicate. SMSC #%d", i) + SMUMLOGGER_WRITE_FORMAT("DoRunL - of Sms Settings SMSC #%d", j) + + duplicateFound = ETrue; + if ( i == 0 ) // first smsc in the sim but it has a duplicate already + { + newDefault = ETrue; + newDefaultIndex = j; + } + break; + } + } + + SMUMLOGGER_WRITE_FORMAT("DoRunL - After dupe-check : newDefaultIndex :%d", newDefaultIndex) + + // this is not a duplicate, find a name and add it to Sms settings + if ( !duplicateFound ) + { + + if(i==0) // first smsc in the sim and has no duplicates + { + newDefault=ETrue; + newDefaultIndex = smsSettings->ServiceCenterCount(); + } + + SMUMLOGGER_WRITE_FORMAT("DoRunL - Not a dupe : newDefaultIndex :%d", newDefaultIndex) + + TBuf name; + name = entry.iText; + + if ( name == KNullDesC ) + { + SMUMLOGGER_WRITE( "DoRunL - SMSC has no name" ) + // read Service centres from SmsSettings + TInt serviceCentres = 0; + serviceCentres = smsSettings->ServiceCenterCount(); + SMUMLOGGER_WRITE_FORMAT( + "DoRunL - Amount of Sms Settings SMSCs :%d", + serviceCentres ) + + CDesCArrayFlat* nameArray = + new ( ELeave ) CDesCArrayFlat( KSmumGranularity ); + CleanupStack::PushL( nameArray ); + + for ( TInt loop = 0 ; loop < serviceCentres; loop++ ) + { + nameArray->AppendL( + smsSettings->GetServiceCenter( loop ).Name() ); + } + SmumUtil::FindDefaultNameForSCL( name, ETrue, nameArray ); + CleanupStack::PopAndDestroy();// nameArray + } + smsSettings->AddServiceCenterL( + name, entry.iServiceCentre.iTelNumber ); + SMUMLOGGER_WRITE("DoRunL - New SMSC added") + } + } + } + // set default SC + if(newDefault) // the default has changed + { + smsSettings->SetDefaultServiceCenter( newDefaultIndex ); + SMUMLOGGER_WRITE_FORMAT("DoRunL - New default SMSC :%d", newDefaultIndex) + } + // save settings + smsAccount->SaveSettingsL( *smsSettings ); + SMUMLOGGER_WRITE("DoRunL - Saved") + #ifdef _DEBUG + TMsvEntry entry = service.Entry(); + entry.iDate.HomeTime(); + service.ChangeL( entry ); + SMUMLOGGER_WRITE("DoRunL - Entry changed") + #endif + CleanupStack::PopAndDestroy( 2 ); // msvStore, smsSettings + + if ( emailFeatureSupported && !emailEntryFound ) + { + SMUMLOGGER_WRITE("DoRunL - Empty Email settings") + HBufC* emptyStr = NULL; + emptyStr = KNullDesC().AllocLC(); + SmumUtil::WriteEmailOverSmsSettingsL( + emptyStr->Des(), + emptyStr->Des(), + ETrue ); + CleanupStack::PopAndDestroy(); // emptyStr + } + CleanupStack::PopAndDestroy(); // centersList + } + SMUMLOGGER_LEAVEFN("CMsgSimOperation::DoRunL") + } + +// ---------------------------------------------------- +// CMsgSimOperation::RunError +// Called when AO RunL leaves. Handle the leave and return +// +// ---------------------------------------------------- + +TInt CMsgSimOperation::RunError( TInt ) + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::RunError") + DoCancel(); + SMUMLOGGER_LEAVEFN("CMsgSimOperation::RunError") + return KErrNone; + } + +// ---------------------------------------------------- +// CMsgSimOperation::DoCancel +// called by active object's Cancel method +// +// ---------------------------------------------------- +void CMsgSimOperation::DoCancel() + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::DoCancel") + + if ( iSimOperation ) // if the real Sim reading operation was started: + { + iSimOperation->Cancel(); // cancel it + } + + // We don't need to complete our own request status as this function will never + // be called if our own request status has already been completed previously. + // + // We do need to complete the client's request status however. + if (iClientStatus) + { + CompleteClientRequest(KErrCancel); + } + + SMUMLOGGER_LEAVEFN("CMsgSimOperation::DoCancel") + } + + +// ---------------------------------------------------- +// CMsgSimOperation::HandleSessionEventL +// called when there is a Msv session event. +// +// ---------------------------------------------------- +void CMsgSimOperation::HandleSessionEventL( + TMsvSessionEvent aEvent, + TAny* /*aArg1*/, + TAny* /*aArg2*/, + TAny* /*aArg3*/) + { + SMUMLOGGER_ENTERFN("CMsgSimOperation::HandleSessionEventL") + SMUMLOGGER_WRITE_FORMAT("HandleSessionEventL - TMsvSessionEvent :%d", aEvent) + + // problem case handling + if ( aEvent == EMsvServerFailedToStart ) + { + // also if we couldn't start up the msv server, we simulate that the request has completed + CompleteRequest( KErrNotReady ); + } + else if (( aEvent == EMsvServerTerminated ) || ( aEvent == EMsvCloseSession )) + { + // be polite to the Messaging Server and close the session + Cancel(); + CompleteRequest( KErrNotReady ); + + delete iSimOperation; // These objects must be deleted first + iSimOperation = NULL; // as they can't exist without a MsvSession + delete iSmsClientMtm; + iSmsClientMtm = NULL; + delete iClientRegistry; + iClientRegistry = NULL; + delete iMsvSession; + iMsvSession = NULL; + iClientStatus = NULL; + } + + SMUMLOGGER_LEAVEFN("CMsgSimOperation::HandleSessionEventL") + } + +// ---------------------------------------------------- +// CMsgSimOperation::HandleStartupReadyL +// Handles events from startup state observer +// +// ---------------------------------------------------- +// +void CMsgSimOperation::HandleStartupReadyL() + { + SMUMLOGGER_WRITE( "BootState Ready" ) + // Boot ready, start the real SimOperation + StartL(); + } +// End of File