sysstatemgmt/systemstatemgr/cmn/src/ssmstatemonitor.cpp
author hgs
Fri, 08 Oct 2010 14:33:25 +0300
changeset 76 cb32bcc88bad
parent 0 4e1aa6a622a0
permissions -rw-r--r--
201039

// Copyright (c) 2007-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:
//

#include <ssm/ssmstateawaresession.h>
#include "ssmstatemonitor.h"
#include "cmnpanic.h"
#include "ssmdebug.h"

/**

 */
CSsmStateMonitor* CSsmStateMonitor::NewL(CSsmStateAwareSession& aObserver, TDmDomainId aId)
	{
	CSsmStateMonitor* self = new (ELeave) CSsmStateMonitor(aObserver);
	CleanupStack::PushL(self);
	self->ConstructL(aId);
	CleanupStack::Pop(self);
	return self;
	}

/**

 */
CSsmStateMonitor::CSsmStateMonitor(CSsmStateAwareSession& aObserver) : 
	CActive(CActive::EPriorityStandard),
	iObserver(aObserver)
	{
	CActiveScheduler::Add(this);
	}

/**

 */
CSsmStateMonitor::~CSsmStateMonitor()
	{
	Cancel();
	iSas.Close();
	}

/**

 */
void CSsmStateMonitor::ConstructL(TDmDomainId aId)
	{
	SSMLOGLEAVEIFERROR(iSas.Connect(aId)); //will leave in release builds as well
	
	//Setup change subscription
	iStatus = KRequestPending;
	iSas.RequestStateNotification(iStatus);
	SetActive();
	
	//Read current state and store locally
	iState = iSas.State();
	}

/**

 */
void CSsmStateMonitor::DoCancel()
	{
	iSas.RequestStateNotificationCancel();
	}

/**

 */
void CSsmStateMonitor::RunL()
	{
	SSMLOGLEAVEIFERROR(iStatus.Int());
	
	//Re-issue a subscription request before retrieving the current value
	iStatus = KRequestPending;
	iSas.AcknowledgeAndRequestStateNotification(KErrNone, iStatus);
	SetActive();
	
	//Update local copy
	iState = iSas.State();
	
	//Notify our clients
	iObserver.NotifySubscribers(iState);			
	}

/**
@panic ECmnStateMonError1 if an error occurs in RunL
 */
TInt CSsmStateMonitor::RunError(TInt aError)
	{
	iSas.AcknowledgeStateNotification(aError);
	DEBUGPRINT2A("CSsmStateMonitor::RunError: %d", aError);
	User::Panic(KPanicSsmCmn, ECmnStateMonError1); //A panic here is easier to track than a panic in CActiveScheduler
	return aError;  //lint !e527 Unreachable
	}

/**

 */
TSsmState CSsmStateMonitor::State() const
	{
	return iState;
	}


CSsmDeferralMonitor::CSsmDeferralMonitor(RSsmStateAwareSession& aStateAwareSession, CSsmStateAwareSession2& aOwnerActiveObject)
    : CActive(CActive::EPriorityHigh), iSsmStateAwareSession(aStateAwareSession), iOwnerActiveObject(aOwnerActiveObject), iCeaseDeferral(EFalse)
    {
    CActiveScheduler::Add(this);
    }

CSsmDeferralMonitor::~CSsmDeferralMonitor()
    {
    Cancel();
    }

/**
 * Defers the Acknowledgement.
 */
void CSsmDeferralMonitor::DeferNotification()
    {
    __ASSERT_ALWAYS(!IsActive(), User::Panic(KPanicSsmCmn, ECmnErrDeferNotif)); 
    iSsmStateAwareSession.DeferAcknowledgement(iStatus);
    SetActive();
    }

/**
Informs the object that the state transition has
been _successfully_ acknowledged
*/
void CSsmDeferralMonitor::NotifyOfAcknowledgement()
    {
    if (IsActive())
        {
        iCeaseDeferral = ETrue;
        }
    }

void CSsmDeferralMonitor::RunL()
    {
    const TInt error = iStatus.Int();
    TBool ceaseDeferral = iCeaseDeferral;
    iCeaseDeferral = EFalse;
    // We are leaving with error after resetting iCeaseDeferral. This is because
    // we might again RequestStateNotification() in HandleDeferralError(), in which case 
    // we need to reset iCeaseDeferral to EFalse so that deferral may happen again.
    User::LeaveIfError(error);

    if(!ceaseDeferral)
        {
        DeferNotification();
        }
	else
        {
        // At this point we know error == KErrNone
        // However, we return the error code KErrCompletion, as this
        // is what would have happened, had the acknowledgment come in
        // a little earlier,
        // whilst the deferral was still outstanding on the server.
        User::Leave(KErrCompletion);
        }
    }

/**
 Handle errors thrown from RunL() - call HandleDeferralErrror()    
*/
TInt CSsmDeferralMonitor::RunError(TInt aError)
    {
    DEBUGPRINT2A("CSsmDeferralMonitor::RunError: %d", aError);
    return iOwnerActiveObject.HandleDeferralError(aError);
    }

/**
 * Cancels the outstanding deferral request.
 */
void CSsmDeferralMonitor::DoCancel()
    {
    iSsmStateAwareSession.CancelDeferral();
    }