locationtriggering/ltserver/ltserverlogic/src/lbtlistaooperation.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 15:37:04 +0300
branchRCL_3
changeset 44 2b4ea9893b66
parent 13 19bff11d6c18
child 45 6b6920c56e2f
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* Copyright (c) 2007 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:  Active Object operation for serving server logic requests
*				 for listing of triggers.
*
*/



// INCLUDE FILES
#include <e32base.h>
#include <s32mem.h>
#include "lbtlistaooperation.h"
#include "lbtcontainer.h"
#include "lbtaoobserver.h"
#include "lbtglobal.h"
#include "lbtserverconsts.h"
#include "lbtcontainertriggerfilter.h"
#include "lbtcontainertriggerentry.h"
#include "lbtlisttriggeroptions.h"
#include "lbtserverlogicbase.h"
#include "lbttriggerfilterbyattribute.h"
#include "lbtlogger.h"

// ===================== MEMBER FUNCTIONS =====================

// ---------------------------------------------------------------------------
// CLbtListAOOperation::NewL
// Symbian Two - phase constructor
// ---------------------------------------------------------------------------
//
CLbtListAOOperation* CLbtListAOOperation::NewL(MLbtAOObserver& aObserver,
											   const RMessage2& aMessage,
											   CLbtContainer& aContainer,
											   TInt aClientType )
	{
	FUNC_ENTER("CLbtListAOOperation::NewL");
	CLbtListAOOperation* self = new (ELeave) CLbtListAOOperation(aObserver, aMessage, aContainer, aClientType);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(); // self
	return self;
	}

// ---------------------------------------------------------------------------
// CLbtListAOOperation::~CLbtListAOOperation
// Destructor
// ---------------------------------------------------------------------------
//
CLbtListAOOperation::~CLbtListAOOperation()
	{
	FUNC_ENTER("CLbtListAOOperation::~CLbtListAOOperation");
	// If the operation is not complete yet then complete the 
	// message with server busy
	if(IsActive())
		{
		Cancel();
		}
	iTriggerArray.ResetAndDestroy();
	delete iTriggerBuffer;
	}

// ---------------------------------------------------------------------------
// CLbtListAOOperation::CLbtListAOOperation
// C++ Default constructor
// ---------------------------------------------------------------------------
//
CLbtListAOOperation::CLbtListAOOperation(MLbtAOObserver& aObserver,
										 const RMessage2& aMessage,
										 CLbtContainer& aContainer,
										 TInt aClientType)
	: CLbtAOOperationBase(aObserver, aMessage, aContainer, aClientType)
	{
	FUNC_ENTER("CLbtListAOOperation::CLbtListAOOperation");
	}

// ---------------------------------------------------------------------------
// CLbtListAOOperation::ConstructL
// ---------------------------------------------------------------------------
//
void CLbtListAOOperation::ConstructL()
	{
	FUNC_ENTER("CLbtListAOOperation::ConstructL");
	CActiveScheduler::Add(this);
	iState = EStateNone;
	}

TInt CLbtListAOOperation::RunError(TInt aError)
	{
	FUNC_ENTER("CLbtListAOOperation::RunError");
	ERROR("RunL Error is %d", aError);
	return aError;
	}
	
// ---------------------------------------------------------------------------
// CLbtListAOOperation::RunL
// ---------------------------------------------------------------------------
//
void CLbtListAOOperation::RunL()
	{
	FUNC_ENTER("CLbtListAOOperation::RunL");
	// Remove this active object from the schedule queue since 
	// async requests will not be made anymore
	Deque();

	if( iStatus.Int() == KErrCancel )
		{
		LbtGlobal::RequestComplete(iMessage, KErrCancel);
		iObserver.HandleOperationClosureL(this,iStatus.Int());		
		return;
		}
	
	switch( iMessage.Function() )
		{
		case EGetFiredTriggersCount:
		case ELbtGetFiredTriggers:
		    {
		    if( iState == EStateUpdateFiredState )
		    	{
		    	iState = EStateUpdateCompleted;
		    	return;
		    	}
		    else if( iState == EStateServiceMessageReceived )
		        {
		        ServiceGetFiredTriggersL();
		        return;
		        }
		    // Got the result from container. Return the number of triggers
			TPckg<TInt> numberOfTriggers(iTriggerArray.Count());
			// Send the number of triggers to client lib
			TInt retVal = LbtGlobal::Write(iMessage, KTriggersSize, numberOfTriggers);			
			if(retVal == KErrNone)
				{
				// Complete the message
				LbtGlobal::RequestComplete(iMessage, iStatus.Int());
				}
				
			if(iTriggerArray.Count() == 0)
				{
				// Inform the observer that this operation has completed
				iObserver.HandleOperationClosureL(this, retVal);
				return;
				}
			RArray<TLbtTriggerId>  triggerIdArray;
		    TLbtTriggerId triggerId;
		    for( TInt i=0;i<iTriggerArray.Count();i++ )
		        {
		        // This array of trigger ids is passed to container to set the 
				// fired state to false.	
				triggerId = iTriggerArray[i]->TriggerEntry()->Id();
			    triggerIdArray.AppendL( triggerId );	
		        }
		        
	        // This active object was dequed from active scheduler once container completes 
			// the list triggers.To use this again,it is necessary to add this to the 
			// active scheduler.
			CActiveScheduler::Add( this );
			
			// Set the trigger fired flag to false
			iContainer.UpdateTriggerFiredState( triggerIdArray,iAOIdentificationNum,EFalse,iStatus );
		    iState = EStateUpdateFiredState;
		    SetActive();
		    triggerIdArray.Close();	
		    break;
		    }
		case ELbtListTriggerIds:
		case ELbtGetListTriggerIdsSize:
			{
			// Got the result from container. Return the number of triggers
			TPckg<TInt> numberOfTriggers(iTriggerArray.Count());
			// Send the number of triggers to client lib
			TInt retVal = LbtGlobal::Write(iMessage, KTriggersSize, numberOfTriggers);			
			if(retVal == KErrNone)
				{
				// Complete the message
				LbtGlobal::RequestComplete(iMessage, iStatus.Int());
				}
				
			if(iTriggerArray.Count() == 0)
				{
				// Inform the observer that this operation has completed
				iObserver.HandleOperationClosureL(this, retVal);
				}
			break;
			}
		case ELbtGetTriggersBufferSize: 
			{
			// If there are no triggers found for this client then return zero
			// as the buffer size and complete this operation object
			if(iTriggerArray.Count() == 0)
				{
				TPckg<TInt> triggersSize(0);
				TInt retVal = LbtGlobal::Write(iMessage, KTriggersSize, triggersSize);
				if(retVal == KErrNone)
					{
					// Complete the message
					LbtGlobal::RequestComplete(iMessage, iStatus.Int());
					}
					
				// Inform the observer that this operation has completed
				iObserver.HandleOperationClosureL(this, retVal);
				break;
				}
			
			// If there are any triggers present then populate the buffer to get the size
			if(!iTriggerBuffer)
				{
				iTriggerBuffer = CBufFlat::NewL(512);
				}
			RBufWriteStream writeStream;
			writeStream.Open(*iTriggerBuffer);
			CleanupClosePushL(writeStream);
			writeStream.WriteInt32L(iTriggerArray.Count());
			for(TInt i=0;i<iTriggerArray.Count(); ++i)
				{
				writeStream << *(iTriggerArray[i]);				
				}
			writeStream.CommitL();
			CleanupStack::PopAndDestroy(&writeStream);
			// Write the size of the buffer
			TPckg<TInt> triggersSize(iTriggerBuffer->Size());
			TInt retVal = LbtGlobal::Write(iMessage, KTriggersSize, triggersSize);
			if(retVal == KErrNone)
				{
				// Complete the message
				LbtGlobal::RequestComplete(iMessage, iStatus.Int());
				}
			break;
			}
		default:
			{
			break;
			}
		}
	}

// ---------------------------------------------------------------------------
// CLbtListAOOperation::DoCancel
// ---------------------------------------------------------------------------
//
void CLbtListAOOperation::DoCancel()
	{
	FUNC_ENTER("CLbtListAOOperation::DoCancel");
	// Cancel container notifications
	iContainer.CancelAsyncOperation(iAOIdentificationNum);
	iMessage.Complete( iStatus.Int() );
    }

// ---------------------------------------------------------------------------
// CLbtListAOOperation::StartOperationL
// ---------------------------------------------------------------------------
//
void CLbtListAOOperation::StartOperationL()
	{
	FUNC_ENTER("CLbtListAOOperation::StartOperationL");
	switch(iFunction)
		{
		case ELbtGetTriggersBufferSize: // Get the buffer size needed to store the trigger entry objects
		case EGetFiredTriggersCount: // Get number of fired triggers for the client
		case ELbtGetListTriggerIdsSize: // Get number of triggers owned by this client
			{
			CLbtListTriggerOptions* options = CLbtListTriggerOptions::NewL();
			CleanupStack::PushL(options);
			
			CLbtContainerFilter* containerFilter = CLbtContainerFilter::NewL();
			CleanupStack::PushL(containerFilter);
			
	    	TLbtSecurityPolicy securityPolicy;
			if ( iClientType == CLbtServerLogicBase::TLbtClientLibrary )
			    {
    			securityPolicy.SetOwnerSecureId( iMessage.SecureId() );	
			    }

			if(iFunction == ELbtGetListTriggerIdsSize || 
			   iFunction == ELbtGetTriggersBufferSize )
				{
				HBufC8* listOptionsBuffer = LbtGlobal::CopyClientBuffer8LC(iMessage, KParamFilter);
				
				if( listOptionsBuffer == NULL )
					{
					CleanupStack::PopAndDestroy(2);
					iObserver.HandleOperationClosureL(this, KErrBadDescriptor);
					return;
					}
				
				// Read the buffer into a stream
				RDesReadStream stream(*listOptionsBuffer);
				CleanupClosePushL(stream);
				options->InternalizeL(stream);				
				CleanupStack::PopAndDestroy(2, listOptionsBuffer); // listOptionsBuffer, stream
				}
			else if( iFunction == EGetFiredTriggersCount )
				{
				containerFilter->AddFiredInfoInFilterL(ETrue);
				}
			
			CLbtContainerListOptions* containerOptions = CLbtContainerListOptions::NewL(options, containerFilter);
			CleanupStack::Pop(2); // options, filter

            TLbtTriggerAttributeFieldsMask triggerMask;
            TLbtTriggerDynamicInfoFieldsMask dynInfoMask;

            // Add the Trigger Id attribute since it shouls always be retrieved whether the
            // client specifies it or not.
			containerOptions->ListOptions()->GetRetrievedFields( triggerMask, dynInfoMask );
			triggerMask = triggerMask | CLbtTriggerEntry::EAttributeId;
			containerOptions->ListOptions()->SetRetrievedFields( triggerMask, dynInfoMask );
			
			containerOptions->SetDataMask(CLbtContainerTriggerEntry::EContainerAttributeFireInfo);
			// Request triggers of the client
			iContainer.ListTriggers(containerOptions, iTriggerArray,iAOIdentificationNum,iStatus,securityPolicy);
			SetActive();
			break;
			}
		default:
			{
			break;
			}
		}
	}

// ---------------------------------------------------------------------------
// CLbtListAOOperation::ServiceMessageL
// ---------------------------------------------------------------------------
//
void CLbtListAOOperation::ServiceMessageL(const RMessage2 aMessage)
	{
	FUNC_ENTER("CLbtListAOOperation::ServiceMessageL");
	iMessage=aMessage;
	switch(aMessage.Function())
		{
		case ELbtGetFiredTriggers:
			{
			iMessage = aMessage;
			if( iState == EStateUpdateCompleted )
				{
				ServiceGetFiredTriggersL();
				}
			else
				{
				iState = EStateServiceMessageReceived;
				}
		    break;
			}
		case ELbtListTriggerIds: // Send the acquired triggers id's
			{
			CBufFlat* buffer = CBufFlat::NewL(512);
			CleanupStack::PushL(buffer);
			RBufWriteStream writeStream;
			writeStream.Open(*buffer);
			CleanupClosePushL(writeStream);			
			for(TInt i=0;i<iTriggerArray.Count(); ++i)
				{
				TLbtTriggerId triggerId = iTriggerArray[i]->TriggerEntry()->Id();
				TUint8* ptr = reinterpret_cast<TUint8*>(&triggerId);
				writeStream.WriteL(ptr, sizeof(TLbtTriggerId));				
				}
			writeStream.CommitL();			
			CleanupStack::PopAndDestroy(&writeStream);
			TPtr8 ptr = buffer->Ptr(0);
			
			// Write the trigger array into the IPC
			TInt retVal = LbtGlobal::Write(iMessage, KParamTriggerEntry, ptr);			
			if(retVal == KErrNone)
				{
				// Complete the message
				LbtGlobal::RequestComplete(iMessage, KErrNone);
				}
			CleanupStack::PopAndDestroy(buffer);
			// Inform the observer that this operation has completed
	        iObserver.HandleOperationClosureL(this, KErrNone);
	        break;
			}
		case ELbtGetTriggers:
			{
			TInt error = KErrNone;
			if( iTriggerBuffer )
				{
				TPtr8 ptr = iTriggerBuffer->Ptr(0);
				// Write the trigger array into the IPC
				TInt retVal = LbtGlobal::Write(iMessage, KParamTriggerEntry, ptr);			
				if(retVal == KErrNone)
					{
					// Complete the message
					LbtGlobal::RequestComplete(iMessage, KErrNone);
					}
				delete iTriggerBuffer;
				iTriggerBuffer = NULL;
				}
			else
				{
				error = KErrNotFound;
				LbtGlobal::RequestComplete(iMessage, KErrNotFound);
				}
			// Inform the observer that this operation has completed
	        iObserver.HandleOperationClosureL( this, error );
			break;
			}
		default:
			{
			// Not received the first part of the message. This 
			// should not happen and should be made sure by the client
			// library
			LbtGlobal::RequestComplete(iMessage, KErrUnknown);
			// Inform the observer that this operation has completed
	        iObserver.HandleOperationClosureL(this, KErrNone);
			break;
			}
		}
    }
	
// ---------------------------------------------------------------------------
// CLbtListAOOperation::CancelListOperation
// ---------------------------------------------------------------------------
//
void CLbtListAOOperation::CancelListOperation()
	{
	FUNC_ENTER("CLbtListAOOperation::CancelListOperation");
	if(iStatus.Int()==KRequestPending)
		{
		Cancel();
		}
	else
		{
		// HandleOperationClosureL method internally calls LoadOrUnloadStrategyPluginL 
		// method which may leave only during the loading operation,but here the expected 
		// behaviour is the unloading of strategy plugin which never fails .Hence we have ignored.
        LbtGlobal::RequestComplete(iMessage,KErrCancel);   
		TRAP_IGNORE( iObserver.HandleOperationClosureL(this,KErrCancel) );
		}	
	}

// ---------------------------------------------------------------------------
// CLbtListAOOperation::ServiceGetFiredTriggersL
// ---------------------------------------------------------------------------
//
void CLbtListAOOperation::ServiceGetFiredTriggersL()
    {
    FUNC_ENTER("CLbtListAOOperation::ServiceGetFiredTriggers");
    //TInt sizeOfFireInfo = sizeof(TLbtTriggerFireInfo);
	CBufFlat* buffer = CBufFlat::NewL(512);
	CleanupStack::PushL(buffer);
	RBufWriteStream writeStream;
	writeStream.Open(*buffer);
	CleanupClosePushL(writeStream);

	for(TInt i=0;i<iTriggerArray.Count(); ++i)
		{
		TLbtTriggerFireInfo fireInfo;
		// Get the fire info from Container
		fireInfo = iTriggerArray[i]->ExtendedTriggerInfo()->GetFiredInfo();
		TUint8* ptr = reinterpret_cast<TUint8*>(&fireInfo);
		writeStream.WriteL(ptr, sizeof(TLbtTriggerFireInfo));
		}
	writeStream.CommitL();
	CleanupStack::PopAndDestroy(&writeStream);
	TPtr8 ptr = buffer->Ptr(0);			
	// Write the trigger array into the IPC			
	TInt retVal = LbtGlobal::Write(iMessage, KParamTriggerFireInfo, ptr);			
	if(retVal == KErrNone)
		{
		// Complete the message
		LbtGlobal::RequestComplete(iMessage, KErrNone);
		}
	CleanupStack::PopAndDestroy(buffer);
	// Inform the observer that this operation has completed
    iObserver.HandleOperationClosureL(this, KErrNone);
    }
// end of file