mobilemessaging/smum/src/MsgSimSCNumberDetector.cpp
changeset 0 72b543305e3a
--- /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 <mtuireg.h>    // for CMtmUiRegistry
+#include <etelmm.h>
+#include <mmlist.h>
+#include <smutset.h>    //CSmsSettings
+#include <exterror.h>   // KErrGsmSMSSimBusy
+#include <csmsaccount.h>
+#include <centralrepository.h>
+#include <messagingvariant.hrh>
+#include <messaginginternalcrkeys.h>    // 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<TGsmSmsTelNumberMaxLen> defaultSmsCenterNb;;            
+            TInt defaultSCIndex = smsSettings->DefaultServiceCenter();
+            if ( defaultSCIndex > -1 )
+                {
+                defaultSmsCenterNb = smsSettings->GetServiceCenter( defaultSCIndex ).Address(); 
+                }    
+            if ( iCheckSimScAlways && i == 0 )
+                {
+                //Check is number already in cenrep
+                TBuf<TGsmSmsTelNumberMaxLen> 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<KMaxNameLength> 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