// Copyright (c) 2008-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:
// Implementation of CStrtSecurityCheckTask class
//




/**
 @file
 @internalComponent
 @released
*/

#include "ssmsecuritychecknotifier.h"
#include "cmdsimsecuritycheck.h"
#include "ssmrefcustomcmdcommon.h"
#include "ssmdebug.h"

#include <e32def.h>
#include <ssm/startupdomainpskeys.h>
#include <ssm/ssmstateawaresession.h>
#include <ssm/ssmpatchableconstants.h>
#include <centralrepository.h>
#include <e32svr.h>
#include <u32hal.h>

//Ordinal postion of the security event observer NewL in the plugin dll
const TInt KSecurityEventObserverNewLOridinal = 1;

//Utility plugin name used for starting security note event observer
_LIT(KSusUtilityPlugin, "ssmclayersup.dll");

/*
 * Function to check whether Invalid Sim feature is enabled or not
 */
TUint32 IsSsmInvalidSimOn()
    {
    TUint32 retVal = 0;

#ifdef __WINS__  
        // KSsmInvalidSim is a ROM patchable constant, so need an emulator equivalent
        // if WINS then read value from epoc.ini, requires licencees to set property in epoc.ini. This value is 0xFFFFFFFF if feature is enabled.
        // Usage: In epoc.ini patchdata_KSsmInvalidSim 0xFFFFFFFF (Can be any non-zero value)
        TUint32 readValueOfInvalidSim = 0;
        if( UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalIntProperty, (TAny*)"patchdata_KSsmInvalidSim", &readValueOfInvalidSim) == KErrNone )
            {
            retVal = readValueOfInvalidSim;
            }
#else   
        retVal = KSsmInvalidSim;        
        
#endif // __WINS__
    return retVal;
    }

CCustomCmdSimSecurityCheck* CCustomCmdSimSecurityCheck::NewL()
	{
	CCustomCmdSimSecurityCheck* self = new (ELeave) CCustomCmdSimSecurityCheck();
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

void CCustomCmdSimSecurityCheck::ConstructL()
	{
	User::LeaveIfError(iSsmMiscAdaptation.Connect());
	User::LeaveIfError(iSsmStateManager.Connect());
	User::LeaveIfError(iSsmSusCli.Connect());

	iStartupPSUid = CSsmUiSpecific::StartupPSUid();
    __ASSERT_ALWAYS(0 != iStartupPSUid.iUid, PanicNow(KPanicCustomCmdSimSecurityCheck, EInvalidUid));
	iSecurityStateInfoResult = new (ELeave) TPckg<TSecurityStateInfo>(iSecurityStateInfo);
	iSsmUiSpecific = CSsmUiSpecific::InstanceL();

	iSimStatusPSObserver = CSsmSimStatusPSObserver::NewL(iStartupPSUid, iSsmUiSpecific->SimStatusPropertyKey());
	//Add active object to active scheduler
	CActiveScheduler::Add(this);
	}

CCustomCmdSimSecurityCheck::CCustomCmdSimSecurityCheck()
						: CActive( EPriorityStandard)
	{
	}

CCustomCmdSimSecurityCheck::~CCustomCmdSimSecurityCheck()
	{
	ExecuteCancel();
	iSsmMiscAdaptation.Close();		
	iSsmStateManager.Close();
	iSsmSusCli.Close();

	if(iSsmUiSpecific)
		{
		//Will be deleted after last dereference
		iSsmUiSpecific->Release();
		}
	
	delete iSsmSecurityCheckNotifier;
	delete iSecurityNoteObserver;
	delete iSecurityStateInfoResult;
	delete iSimStatusPSObserver;
	}

TInt CCustomCmdSimSecurityCheck::Initialize(CSsmCustomCommandEnv* /*aCmdEnv*/)
	{
	return KErrNone;
	}

void CCustomCmdSimSecurityCheck::Close()
	{
	}

void CCustomCmdSimSecurityCheck::Release()
	{
	delete this;
	}

void CCustomCmdSimSecurityCheck::Execute(const TDesC8& /*aParams*/, TRequestStatus& aStatus)
	{
	//Load the security event observer
	TSsmSupInfo observerPlugin(KSusUtilityPlugin, KSecurityEventObserverNewLOridinal);
	TInt retLoadSecEventObserver = iSsmSusCli.RequestLoadSup(observerPlugin);

	if(KErrNone != retLoadSecEventObserver)
		{
		DEBUGPRINT2A("Load security event observer SUP failed with error code : %d", retLoadSecEventObserver);
		}
	
	//Set the user request to pending
	aStatus = KRequestPending;
	iExecuteRequest = &aStatus;

	//Start the state change
	StartStateChange(StartupAdaptation::ESIMPresent);
	}

/**
@panic EInternalStateError if the active object is running or the state change is pending
*/
void CCustomCmdSimSecurityCheck::StartStateChange(const TSecurityState aState, const TStrtSecurityNoteType aNoteType)
	{
	__ASSERT_ALWAYS(!IsActive(), PanicNow(KPanicCustomCmdSimSecurityCheck, EInternalStateError));
	__ASSERT_ALWAYS(!iStateChangePending, PanicNow(KPanicCustomCmdSimSecurityCheck, EInternalStateError));

	iSubState = ESecuritySubStateNone;
	iStateChangePending = ETrue;
	iNoteType = aNoteType;
	iState = aState;

	//Request for security state change
	iSsmMiscAdaptation.SecurityStateChange(iState, *iSecurityStateInfoResult, iStatus);
	SetActive();
	}

void CCustomCmdSimSecurityCheck::RunL()
	{
	if(iSubState != ESecuritySubStateNone)
		{
		//Execute sim operations 
		DoExtendedSimOperations();
		return;
		}

	if (iStateChangePending)
		{
		//Start changing the state
		StateChangeL(iStatus.Int());
		}
	else
		{
		if (iStatus == KErrNone)
			{
			//Do further security check
			DoSecurityCheck();
			}
		else
			{
			//Complete client request with result code
			CompleteClientRequest(iStatus.Int());
			}
		}
	}

void CCustomCmdSimSecurityCheck::DoExtendedSimOperations()
	{
    if (KErrNone == iStatus.Int())
        {
        switch (iSubState)
            {
            case ESecuritySubStateSimRemoved:
                DoSimRemoved();
                break;
            case ESecuritySubStateSimNotSupported:
                DoSimNotSupported();
                break;
            case ESecuritySubStateSimReadable:
                DoSimReadable();
                break;
            case ESecuritySubStateSimUsable:
                DoSimUsable();
                break;
            case ESecuritySubStateSimStatusPSObserver:
                DoObserveSimStatusPS();
                break;
            default:
                __ASSERT_DEBUG(ESecuritySubStateNone == iSubState, PanicNow(KPanicCustomCmdSimSecurityCheck, EInvalidSecuritySubState));
                break;
            }
        }
    else
        {
        //Complete client request with result code
        CompleteClientRequest(iStatus.Int());
        }
	}

void CCustomCmdSimSecurityCheck::StateChangeL(const TInt aResultCode)
	{
	__ASSERT_ALWAYS(iStateChangePending, PanicNow(KPanicCustomCmdSimSecurityCheck, EInternalStateError));
	DEBUGPRINT2A("Sim security state change completed with error %d", aResultCode);

	iStateChangePending = EFalse;
	if (aResultCode == KErrNone)
		{
		//Proceed with state change in case previous state completed with out any error
		SecurityCheckL();
		}
	else
		{
		//Complete client request with result code
		CompleteClientRequest(aResultCode);
		}
	}

void CCustomCmdSimSecurityCheck::CompleteClientRequest(TInt aReason)
	{
	//Complete client request with reason code
	if (iExecuteRequest)
        {
        User::RequestComplete(iExecuteRequest, aReason);
        }
	}

void CCustomCmdSimSecurityCheck::SecurityCheckL()
    {
    //Delete the security notifier
	delete iSsmSecurityCheckNotifier;
	iSsmSecurityCheckNotifier = NULL;

	TInt errorCode = KErrNone;
    //Handle the state transition
    switch (iState)
        {
        case StartupAdaptation::ESIMPresent:
			HandleSIMPresent();
            break;
		case StartupAdaptation::ESIMReadable:
            SimReadable();
            break;
		case StartupAdaptation::ESIMInvalid:
		    HandleSIMInvalid();
		    break;
        case StartupAdaptation::ESIMRejected:
        	HandleSIMRejected();
        	break;
        case StartupAdaptation::ESIMBlocked:
        	HandleSIMBlocked();
        	break;
        case StartupAdaptation::EPINRequired:
        	HandlePINRequired();
        	break;
        case StartupAdaptation::ESIMLessOfflineSupported:
            HandleSIMLessOfflineSupported();
            break;
		case StartupAdaptation::ESIMCodesOK:
			StartStateChange( StartupAdaptation::ESIMLock );
            break;
        case StartupAdaptation::ESecurityCheckOK:
        	errorCode = RProperty::Set(CSsmUiSpecific::StarterPSUid(), KStarterSecurityPhase, EStarterSecurityPhaseSimOk );
        	if(KErrNone != errorCode)
        		{
        		DEBUGPRINT2A("Failed to set value of property CSsmUiSpecific::StarterPSUid() because of error %d", errorCode);
        		}
        	CompleteClientRequest(KErrNone);
        	break;
        case StartupAdaptation::ESecurityCheckFailed:
        	errorCode = RProperty::Set(CSsmUiSpecific::StarterPSUid(), KStarterSecurityPhase, EStarterSecurityPhaseSimNok);
        	if(KErrNone != errorCode)
        		{
        		DEBUGPRINT2A("Failed to set value of property CSsmUiSpecific::StarterPSUid() because of error %d", errorCode);
        		}
        	CompleteClientRequest(KErrNone);
        	break;
        case StartupAdaptation::ESIMLock:
            if (iSecurityStateInfo == StartupAdaptation::ESimLockRestrictionOn)
                {
                StartSecurityNoteObserverL();
                iSsmSecurityCheckNotifier = CSsmSecurityCheckNotifier::NewL(ESecInfoSimLockRestrOn);
                iSsmSecurityCheckNotifier->ShowNoteL(iStatus);
                SetActive();
                }
            else
                {
				DoSecurityCheck();
                }
            break;
        case StartupAdaptation::EAskPIN:
        case StartupAdaptation::EAskPUK:
            StartSecurityNoteObserverL();
			iSsmSecurityCheckNotifier = CSsmSecurityCheckNotifier::NewL(iNoteType);
            iSsmSecurityCheckNotifier->ShowNoteL(iStatus);
            SetActive();
			break;
        default:
            CompleteClientRequest(KErrNotSupported);
            break;
        };
    }

void CCustomCmdSimSecurityCheck::DoSecurityCheck()
    {
    //Handle pending state transition
    switch (iState)
        {
        case StartupAdaptation::ESIMLock:
            HandleSIMLock();
            break;
        case StartupAdaptation::EAskPIN:
            HandlePINAsked();
            break;
        case StartupAdaptation::EAskPUK:
            HandlePUKAsked();
            break;
        default:
            CompleteClientRequest(KErrNotSupported);
            break;
        };
	}

void CCustomCmdSimSecurityCheck::HandleSIMPresent()
    {
    switch (iSecurityStateInfo)
    	{
    	case StartupAdaptation::EYes:
    		//Start sim readable state transition
    		StartStateChange(StartupAdaptation::ESIMReadable);
    		break;
    	case StartupAdaptation::ENo:
    		if (IsSimSupported())
    			{
    			SimRemoved();
    			}
    		else
    			{
    			SimNotSupported();
    			}
    		break;
    	default:
    		DEBUGPRINT2A("Illegal security result in ESIMPresent state: %d", iSecurityStateInfo);
    		CompleteClientRequest(KErrGeneral);
    		break;
    	};
    }

void CCustomCmdSimSecurityCheck::DoSimRemoved()
	{
	//Start sim less offline support state transition
	StartStateChange(StartupAdaptation::ESIMLessOfflineSupported);
	}

void CCustomCmdSimSecurityCheck::DoSimNotSupported()
	{
	//Start sim less offline support state transition
	StartStateChange(StartupAdaptation::ESIMLessOfflineSupported);
	}

void CCustomCmdSimSecurityCheck::DoSimReadable()
	{
	if(IsSsmInvalidSimOn())
	    {
	    //Start sim invalid state transition
	    StartStateChange(StartupAdaptation::ESIMInvalid);
	    }
	else
	    {
	    //Start sim rejected state transition
        StartStateChange(StartupAdaptation::ESIMRejected);
	    }
	}

void CCustomCmdSimSecurityCheck::DoSimUsable()
	{
	TInt simStatus = ESimStatusUninitialized;
	TInt errVal = (iSimStatusPSObserver->GetValue(simStatus));
	
	if (KErrNone == errVal)
	    {
	    //Do not observe if SIM status has already changed to ESimUsable
	     if(simStatus == ESimUsable)
	         {
	         //Start security check ok state transition
	         StartStateChange(StartupAdaptation::ESecurityCheckOK);
	         }
	     else
	         {
	         //Wait till the SIM status changes to ESimUsable. 
	         //Start observing for the P&S key change
	         iSimStatusPSObserver->StartObserving(iStatus);
	         iSubState = ESecuritySubStateSimStatusPSObserver;
	         SetActive();
	         }
	    }
	else
	    {
	    DEBUGPRINT2A("Error when getting SIM status value: %d", errVal);
	    CompleteClientRequest(errVal);
	    }
	}

void CCustomCmdSimSecurityCheck::DoObserveSimStatusPS()
    {
    //Start security check ok state transition
    StartStateChange(StartupAdaptation::ESecurityCheckOK);
    }

void CCustomCmdSimSecurityCheck::SimRemoved()
    {
    TUint simStatusPropertyKey = iSsmUiSpecific->SimStatusPropertyKey();
    TSsmSwp swp(simStatusPropertyKey, ESimNotPresent);
    iSsmStateManager.RequestSwpChange(swp, iStatus);
	iSubState = ESecuritySubStateSimRemoved;
	SetActive();
    }

void CCustomCmdSimSecurityCheck::SimNotSupported()
	{
    TUint simStatusPropertyKey = iSsmUiSpecific->SimStatusPropertyKey();
    TSsmSwp swp(simStatusPropertyKey, ESimNotSupported);
	iSsmStateManager.RequestSwpChange(swp, iStatus);
	iSubState = ESecuritySubStateSimNotSupported;
	SetActive();
	}

void CCustomCmdSimSecurityCheck::SimReadable()
	{
    TUint simStatusPropertyKey = iSsmUiSpecific->SimStatusPropertyKey();
    TSsmSwp swp(simStatusPropertyKey, ESimReadable);
	iSsmStateManager.RequestSwpChange(swp, iStatus);
	iSubState = ESecuritySubStateSimReadable;
	SetActive();
	}

void CCustomCmdSimSecurityCheck::SimUsable()
	{
	TUint simStatusPropertyKey = iSsmUiSpecific->SimStatusPropertyKey();
    TSsmSwp swp(simStatusPropertyKey, ESimUsable);
    iSsmStateManager.RequestSwpChange(swp, iStatus);
	iSubState = ESecuritySubStateSimUsable;
	SetActive();	
 	}

void CCustomCmdSimSecurityCheck::HandleSIMInvalid()
    {
    switch (iSecurityStateInfo)
        {
        case StartupAdaptation::EYes:

            //Publish the Sim Security Status as ESimInvalid
            RProperty::Set(iStartupPSUid, KStartupSimSecurityStatus, ESimInvalid);
            
            //Set the security state as failed
            SetSecurityStatus(EStrtSecurityCheckFailed);

            //Start sim less offline support state transition
            StartStateChange(StartupAdaptation::ESecurityCheckFailed);
            break;
        case StartupAdaptation::ENo:
            //Start sim rejected state transition
            StartStateChange(StartupAdaptation::ESIMRejected);
            break;
        default:
            DEBUGPRINT2A("Illegal security result in ESIMInvalid state: %d", iSecurityStateInfo);
            //Complete user request with KErrGeneral
            CompleteClientRequest(KErrGeneral);
            break;
        };
    }


void CCustomCmdSimSecurityCheck::HandleSIMRejected()
    {
    switch (iSecurityStateInfo)
    	{
    	case StartupAdaptation::EYes:
    		RProperty::Set(iStartupPSUid, KStartupSimSecurityStatus, ESimRejected );

    		//Set the security state as failed
			SetSecurityStatus(EStrtSecurityCheckFailed);

			//Start sim less offline support state transition
			StartStateChange(StartupAdaptation::ESecurityCheckFailed);
			break;
    	case StartupAdaptation::ENo:
			//Start sim blocked state transition
			StartStateChange(StartupAdaptation::ESIMBlocked);
			break;
    	default:
    		DEBUGPRINT2A("Illegal security result in ESIMRejected state: %d", iSecurityStateInfo);

    		//Complete user request with KErrGeneral
    		CompleteClientRequest(KErrGeneral);
    		break;
    	};
    }

void CCustomCmdSimSecurityCheck::HandleSIMBlocked()
    {
    switch (iSecurityStateInfo)
    	{
    	case StartupAdaptation::EPUK1Required:
    		//Start PUK required state transition
    		StartStateChange(StartupAdaptation::EAskPUK, ESecCodePUK1);
    		break;
    	case StartupAdaptation::EUPUKRequired:
    		//Start UPUK required state transition
    		StartStateChange(StartupAdaptation::EAskPUK, ESecCodeUPUK);
    		break;
    	case StartupAdaptation::ENo:
    		//Start PIN required state transition
    		StartStateChange(StartupAdaptation::EPINRequired);
    		break;
    	default:
    		DEBUGPRINT2A("Illegal security result in ESIMBlocked state: %d", iSecurityStateInfo);

    		//Complete user request with KErrGeneral
    		CompleteClientRequest(KErrGeneral);
    		break;
    	};
    }

void CCustomCmdSimSecurityCheck::HandlePINRequired()
    {
    switch (iSecurityStateInfo)
    	{
    	case StartupAdaptation::EPIN1Required:
    		//Start PIN required state transition
    		StartStateChange(StartupAdaptation::EAskPIN, ESecCodePIN1);
    		break;
    	case StartupAdaptation::EUPINRequired:
    		//Start UPIN required state transition
    		StartStateChange(StartupAdaptation::EAskPIN, ESecCodeUPIN);
    		break;
    	case StartupAdaptation::ENo:
    		//Start SIM Codes OK state transition
    		StartStateChange(StartupAdaptation::ESIMCodesOK);
    		break;
    	default:
    		DEBUGPRINT2A( "Illegal security result in EPINRequired state: %d", iSecurityStateInfo );

    		//Complete user request with KErrGeneral
    		CompleteClientRequest(KErrGeneral);
    		break;
    	};
    }

void CCustomCmdSimSecurityCheck::HandleSIMLessOfflineSupported()
    {
    if (IsSimSupported())
        {
        if (iSsmUiSpecific->IsSimlessOfflineSupported())
            {
            //SIMless offline is supported

            //Set the security state as Sim less offline
            SetSecurityStatus(EStrtSimlessOffline);
            StartStateChange(StartupAdaptation::ESIMLock);
            }
        else
            {
            //SIMless offline is not supported

            //Set the security state as failed
            SetSecurityStatus(EStrtSecurityCheckFailed);
            StartStateChange(StartupAdaptation::ESecurityCheckFailed);
            }
        }
    else
        {
        //SIM not supported
        SetSecurityStatus(EStrtSimlessOffline);
        StartStateChange(StartupAdaptation::ESIMLock);
        }
    }

TBool CCustomCmdSimSecurityCheck::IsSimSupported()
	{
	return iSsmUiSpecific->IsSimSupported();
	}

void CCustomCmdSimSecurityCheck::HandleSIMLock()
    {
    switch(iSecurityStateInfo)
    	{
    	case StartupAdaptation::ESimLockRestricted:
    		//Set the sim lock status property to "Sim lock active"
		    RProperty::Set(iStartupPSUid, KStartupSimLockStatus, ESimLockActive );

		    //Set the sim security status property to "Sim unaccepted"
		    RProperty::Set(iStartupPSUid, KStartupSimSecurityStatus, ESimUnaccepted );

	        //Set the security state as failed
	        SetSecurityStatus(EStrtSecurityCheckFailed);

	        //Start security check failed state transition
	        StartStateChange(StartupAdaptation::ESecurityCheckFailed);
			break;
		case StartupAdaptation::ESimLockOk:
	       //Set the sim lock status property to "Sim lock ok"
	        RProperty::Set(iStartupPSUid, KStartupSimLockStatus, ESimLockOk );
	        SetSecurityCheckOK();
			break;
		case StartupAdaptation::ESimLockRestrictionOn:
			//Set the sim lock status property to "Sim lock restriction on"
	        RProperty::Set(iStartupPSUid, KStartupSimLockStatus, ESimLockRestrictionOn);
	        SetSecurityCheckOK();
			break;
		case StartupAdaptation::ESimLockRestrictionPending:
	        //Set the sim lock status property to "Sim lock restriction pending"
	        RProperty::Set(iStartupPSUid, KStartupSimLockStatus, ESimLockRestrictionPending);

	        //Set the sim security status property to "Sim unaccepted"
	        RProperty::Set(iStartupPSUid, KStartupSimSecurityStatus, ESimUnaccepted);

	        //Set the security state as failed
	        SetSecurityStatus( EStrtSecurityCheckFailed);

	        //Start security check failed state transition
	        StartStateChange(StartupAdaptation::ESecurityCheckFailed);
			break;
		default:
			DEBUGPRINT2A("Illegal security result in ESIMLock state: %d", iSecurityStateInfo);
			//Complete user request with KErrGeneral
			CompleteClientRequest(KErrGeneral);
			break;
		}

    }

void CCustomCmdSimSecurityCheck::SetSecurityCheckOK()
    {
    if (SecurityStatus() != EStrtSimlessOffline)
        {
        //Set the security state as passed
        SetSecurityStatus( EStrtSecurityCheckPassed);
        SimUsable();
        }
	else
		{
		//Start security check ok state transition
    	StartStateChange(StartupAdaptation::ESecurityCheckOK);
		}
    }


void CCustomCmdSimSecurityCheck::HandlePINAsked()
    {
	__ASSERT_DEBUG(NULL != iSsmSecurityCheckNotifier, PanicNow(KPanicCustomCmdSimSecurityCheck, ECmdNullPtr));

    const TBool isCodeAccepted = iSsmSecurityCheckNotifier->IsCodeAccepted();

    //Try again until PIN is either accepted or blocked.
    if (isCodeAccepted)
        {
        //Start SIM codes ok state transition
        StartStateChange(StartupAdaptation::ESIMCodesOK);
        }
    else
        {
        switch(iNoteType)
      		{
      		case ESecCodePIN1:
      			//Start security code PUK1 state transition
				StartStateChange(StartupAdaptation::EAskPUK, ESecCodePUK1);
				break;
      		case ESecCodeUPIN:
      			//Start security code UPUK state transition
      			StartStateChange(StartupAdaptation::EAskPUK, ESecCodeUPUK);
      			break;
      		default:
                DEBUGPRINT2A("Illegal code type in EAskPIN state: %d", iNoteType);
                //Complete user request with KErrGeneral
                CompleteClientRequest(KErrGeneral);
      			break;
      		}
        }
    }

void CCustomCmdSimSecurityCheck::HandlePUKAsked()
    {
	__ASSERT_DEBUG(NULL != iSsmSecurityCheckNotifier, PanicNow(KPanicCustomCmdSimSecurityCheck, ECmdNullPtr));
    
	//Is the entered code correct
    const TBool isCodeAccepted = iSsmSecurityCheckNotifier->IsCodeAccepted();

    if (isCodeAccepted)
        {
        //Start SIM code ok state transition
        StartStateChange(StartupAdaptation::ESIMCodesOK);
        }
    else
        {
        //Set the Sim security status property to "Sim rejected"
        RProperty::Set(iStartupPSUid, KStartupSimSecurityStatus, ESimRejected);

        //Set the security state as failed
        SetSecurityStatus(EStrtSecurityCheckFailed);

        //Start security check failed state transition
        StartStateChange(StartupAdaptation::ESecurityCheckFailed);
        }
    }

void CCustomCmdSimSecurityCheck::SetSecurityStatus(const TStrtSecurityStatus& aSecurityStatus)
    {
    iSsmUiSpecific->SetSecurityStatus(aSecurityStatus);
    }

TStrtSecurityStatus CCustomCmdSimSecurityCheck::SecurityStatus() const
    {
    return iSsmUiSpecific->SecurityStatus();
    }

void CCustomCmdSimSecurityCheck::StartSecurityNoteObserverL()
	{
	if(!iSecurityNoteObserver)
		{
		iSecurityNoteObserver = CSecurityNoteObserver::NewL();
		}
	}

TInt CCustomCmdSimSecurityCheck::RunError(TInt aError)
	{
	//Do the final cleanup incase of error
	Cleanup(aError);
	return KErrNone;
	}

void CCustomCmdSimSecurityCheck::DoCancel()
	{
	// Cancel all possible requests that could be outstanding on iStatus
	if(iSsmSecurityCheckNotifier)
		{
		iSsmSecurityCheckNotifier->Cancel();
		}
	if(iSecurityNoteObserver)
		{
		iSecurityNoteObserver->Cancel();
		}
	iSsmMiscAdaptation.Cancel();
	iSsmStateManager.RequestSwpChangeCancel();
	iSimStatusPSObserver->Cancel();
	}

void CCustomCmdSimSecurityCheck::ExecuteCancel()
	{
	//Call cancel method of CActive	
	Cancel();

	//Do the final cleanup before cancelling
	Cleanup(KErrCancel);
	}

void CCustomCmdSimSecurityCheck::Cleanup(TInt aError)
	{
	if (iExecuteRequest)
		{
		//Complete the user request with the given error code
		User::RequestComplete(iExecuteRequest, aError);
		}
	}

// CSsmSimStatusPSObserver 
// Active Object Class that observes for SIM status P&S key change
CSsmSimStatusPSObserver* CSsmSimStatusPSObserver::NewL(TUid aCategory, TUint aKey)
	{
	CSsmSimStatusPSObserver* self = new (ELeave) CSsmSimStatusPSObserver(aCategory, aKey);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

void CSsmSimStatusPSObserver::ConstructL()
	{
	User::LeaveIfError(iProperty.Attach(iCategory, iKey));
	}

CSsmSimStatusPSObserver::CSsmSimStatusPSObserver(TUid aCategory, TUint aKey)  
                                    : CActive(EPriorityStandard), iCategory(aCategory), iKey(aKey)
    {
    CActiveScheduler::Add(this);
    }

CSsmSimStatusPSObserver::~CSsmSimStatusPSObserver()
    {
    Cancel();
    iProperty.Close();
    }

void CSsmSimStatusPSObserver::StartObserving(TRequestStatus& aStatus)
    {
    __ASSERT_DEBUG(!(IsActive()), PanicNow(KPanicCustomCmdSimSecurityCheck, EInternalStateError));
    aStatus = KRequestPending;
    iClientStatus = &aStatus;
    iProperty.Subscribe(iStatus);
    SetActive();
    }

TInt CSsmSimStatusPSObserver::GetValue(TInt& aValue)
    {
    TInt errVal = (iProperty.Get(aValue));
    return errVal;
    }

void CSsmSimStatusPSObserver::DoCancel()
    {
    iProperty.Cancel();
    Complete(KErrCancel);
    }

void CSsmSimStatusPSObserver::RunL()
    {
    Complete(iStatus.Int());
    }

void CSsmSimStatusPSObserver::Complete(const TInt aErrorCode)
    {
    if (iClientStatus)
        {
        User::RequestComplete(iClientStatus, aErrorCode);
        iClientStatus = NULL;
        }
    }
