locationtriggering/ltcontainer/src/lbtcontainerao.cpp
changeset 0 667063e416a2
child 20 2b4ea9893b66
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/locationtriggering/ltcontainer/src/lbtcontainerao.cpp	Tue Feb 02 01:06:48 2010 +0200
@@ -0,0 +1,1029 @@
+/*
+* Copyright (c) 2005 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:  location triggering server client interface
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32base.h>
+#include <lbtstartuptrigger.h>
+#include "lbtcontainerao.h"
+#include "lbtlisttriggerobserver.h"
+#include "lbtupdateasyncoperation.h"
+#include "lbtlistasyncoperation.h"
+#include "lbtdeleteasyncoperation.h"
+#include "lbtcreateasyncoperation.h"
+#include "lbtdbtriggersmanager.h"
+#include "lbtramtriggersmanager.h"
+#include "lbttriggerchangeobserver.h"
+#include "lbtcontainer.h"
+#include "lbttriggerconditionarea.h"
+#include "lbttriggerstoreinterface.h"
+#include "lbtcontainerextendedtriggerinfo.h"
+#include "lbtlogger.h"
+
+
+
+
+
+// ================= LOCAL FUNCTIONS ========================
+ 
+// ================= MEMBER FUNCTIONS =======================
+
+// ------------------------------------------------------------------
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ------------------------------------------------------------------
+//
+
+CLbtContainerAO::CLbtContainerAO(RPointerArray<MLbtTriggerStore>& aTriggerStores,
+                                 RArray<CLbtContainer::TLbtTriggerStoreChangeObserver>& aObservers ):
+								 CActive(EPriorityStandard),
+								 iClientStatus(NULL),
+								 iAsyncRequest(EOpNone),
+								 iTriggerStores(aTriggerStores),
+								 iTriggerStoreCtr (0),
+								 iObservers(aObservers)
+    
+    {   
+    CActiveScheduler::Add(this);    
+    }
+
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::ConstructL.
+// ------------------------------------------------------------------
+//
+void CLbtContainerAO::ConstructL()
+    {
+    for(TInt i=0;i<iTriggerStores.Count();++i)
+    	{
+    	iTriggerStores[i]->SetStoreChangeObserver(this);
+    	}	
+    }
+
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::NewL
+// ------------------------------------------------------------------
+//
+CLbtContainerAO* CLbtContainerAO::NewL(RPointerArray<MLbtTriggerStore>& aTriggerStores,
+                                       RArray<CLbtContainer::TLbtTriggerStoreChangeObserver>& aObservers )
+    {
+    FUNC_ENTER("CLbtContainerAO::NewL");
+    CLbtContainerAO* self = new (ELeave) CLbtContainerAO(aTriggerStores,aObservers);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+   
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::~CLbtContainerAO
+// ------------------------------------------------------------------
+//
+CLbtContainerAO::~CLbtContainerAO()
+    {
+    FUNC_ENTER("CLbtContainerAO::~CLbtContainerAO");
+	if(IsActive())      
+		{
+		Cancel();
+		}	
+	iAsyncOpQueue.ResetAndDestroy();
+    }
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::AddAsyncOpToQueue
+// ------------------------------------------------------------------
+//
+void CLbtContainerAO::AddAsyncOpToQueue( CLbtContainerAOOperation* aAsyncOp)
+    {
+    FUNC_ENTER("CLbtContainerAO::AddAsyncOpToQueue");
+    // Append to the queue of asynchronous requests.
+    if(aAsyncOp)
+        {
+        iAsyncOpQueue.Append(aAsyncOp);
+        // if AO is not active, start serving the current request.
+        StartNextAsyncOperation();
+        }        
+    }
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::StartNextAsyncOperation
+// ------------------------------------------------------------------
+//
+void CLbtContainerAO::StartNextAsyncOperation()
+    {
+    FUNC_ENTER("CLbtContainerAO::StartNextAsyncOperation");
+    // Check if any of the trigger stores are busy
+    for(TInt i=0;i<iTriggerStores.Count();++i)
+    	{
+    	if(iTriggerStores[i]->IsStoreBusy())
+    		{
+    		return;
+    		}
+    	}
+
+    if(!IsActive())
+        {
+        if(iTriggerStores.Count() > 0)
+            {
+            iTriggerStoreCtr = -1; 
+            iAsyncOpQueue[0]->SetPrevReturnCode(KErrNotReady);
+            iAsyncOpQueue[0]->SetCurrentReturnCode(KErrNotReady);
+            iAsyncRequest = iAsyncOpQueue[0]->GetAOOperationType();
+            }
+        else
+            {
+            TRequestStatus* status = iAsyncOpQueue[0]->GetStatus();
+            User::RequestComplete(status,KErrNotSupported);
+            return;
+            }
+        iStatus = KRequestPending;    
+        TRequestStatus* status = &iStatus;    
+        SetActive();
+        /* Do a Self Complete so that the RunL() gets scheduled */
+        User::RequestComplete(status,KErrNone);
+        }
+    }
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::GetTriggersL
+// ------------------------------------------------------------------
+//
+void CLbtContainerAO::GetTriggersL( const RArray<TLbtTriggerId>& aTriggerIds,
+								    RPointerArray < CLbtContainerTriggerEntry >& aTriggers,
+								    TInt& aOpId,
+								    TRequestStatus& aStatus,
+								    TLbtSecurityPolicy aSecurityPolicy )
+	{
+	FUNC_ENTER("CLbtContainerAO::GetTriggers");
+	CLbtListAsyncOperation* listop = CLbtListAsyncOperation::NewL( aTriggerIds,
+    															   aTriggers,
+    															   aSecurityPolicy,
+    															   aStatus);
+    listop->SetOpCode( aOpId );
+    AddAsyncOpToQueue( listop );
+	}
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::ListTriggersL
+// ------------------------------------------------------------------
+//
+void CLbtContainerAO::ListTriggersL( CLbtContainerListOptions* aFilter,
+    								 RPointerArray < CLbtContainerTriggerEntry >& aTriggers,
+								     TInt aOpCode,
+								     TRequestStatus& aStatus,
+								     TLbtSecurityPolicy aSecurityPolicy )
+    {
+    FUNC_ENTER("CLbtContainerAO::ListTriggersL");
+    iSortingOption = aFilter->ListOptions()->SortingOption();
+    CLbtListAsyncOperation* listop = CLbtListAsyncOperation::NewL( aFilter,
+    															   aTriggers,
+    															   aSecurityPolicy,
+    															   aStatus);
+    listop->SetOpCode(aOpCode);
+    AddAsyncOpToQueue(listop);
+    }
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::UpdateTriggerL
+// ------------------------------------------------------------------
+//    
+void CLbtContainerAO::UpdateTriggerL( CLbtContainerTriggerEntry& aEntry,
+        							  TLbtTriggerDataMask aDataMask,
+        							  TLbtTriggerAttributeFieldsMask aAttrMask,
+        							  TInt aOpCode,
+        							  TRequestStatus& aStatus,
+        							  TLbtSecurityPolicy aSecurityPolicy )
+    {
+    FUNC_ENTER("CLbtContainerAO::UpdateTriggerL");
+    iDataMask = aDataMask;
+    iAttrMask = aAttrMask;
+    CLbtUpdateAsyncOperation* updateop = CLbtUpdateAsyncOperation::NewL( aEntry,
+    																	 aDataMask,
+    																	 aAttrMask,
+    																	 aStatus,
+    																	 aSecurityPolicy,
+    																	 EOpUpdateTrigger);
+    updateop->SetOpCode(aOpCode);
+    AddAsyncOpToQueue(updateop);
+    }
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::UpdateTriggerL
+// ------------------------------------------------------------------
+//
+void CLbtContainerAO::UpdateTriggerFiredStateL( RArray<TLbtTriggerId>& aTriggerIds,
+											    TBool aFireBool,
+											    TInt aOpCode,
+					                    	    TRequestStatus& aStatus )
+	{
+	FUNC_ENTER("CLbtContainerAO::UpdateTriggerL - Filter");
+	aStatus = KRequestPending;
+    CLbtUpdateAsyncOperation* updateop = CLbtUpdateAsyncOperation::NewL( aTriggerIds, 
+    																	 aStatus,
+    																	 aFireBool,
+    																	 KLbtNullSecurity,
+    																	 EOpUpdateTriggersFiredState );
+    updateop->SetOpCode(aOpCode);
+    AddAsyncOpToQueue(updateop);
+	}
+        
+// ------------------------------------------------------------------
+// CLbtContainerAO::UpdateTriggersStateL
+// ------------------------------------------------------------------
+//
+void  CLbtContainerAO::UpdateTriggersStateL( CLbtTriggerEntry::TLbtTriggerState aState,
+            								 CLbtContainerUpdateFilter* aFilter,
+            								 TInt aOpCode,
+            								 TLbtFireOnUpdate aFireOnUpdate,
+            								 TRequestStatus& aStatus,
+            								 TLbtSecurityPolicy aSecurityPolicy ) 
+    {
+    FUNC_ENTER("CLbtContainerAO::UpdateTriggersStateL");
+    aStatus = KRequestPending;
+    CLbtUpdateAsyncOperation* updateop = CLbtUpdateAsyncOperation::NewL( aState,
+    																	 aFilter,
+    																	 aFireOnUpdate,
+    																	 aStatus,    																	 
+    																	 aSecurityPolicy,
+    																	 EOpUpdateTriggerState);
+    updateop->SetOpCode(aOpCode);
+    AddAsyncOpToQueue(updateop);
+    }
+ 
+ 
+// ------------------------------------------------------------------
+// CLbtContainerAO::UpdateTriggersValidityL
+// ------------------------------------------------------------------
+//            
+void CLbtContainerAO::UpdateTriggersValidityL( TLbtTriggerDynamicInfo::TLbtTriggerValidity aValidity,
+            								   RArray <TLbtTriggerId>& aTriggerIds,
+            								   TInt aOpCode,
+            								   TRequestStatus& aStatus,
+            								   TLbtSecurityPolicy aSecurityPolicy ) 
+            
+    {
+    FUNC_ENTER("CLbtContainerAO::UpdateTriggersValidityL");
+    CLbtUpdateAsyncOperation* updateop = CLbtUpdateAsyncOperation::NewL( aValidity,
+    																	 aTriggerIds,
+    																	 aStatus,
+    																	 aSecurityPolicy,
+    																	 EOpUpdateTriggersValidity);
+    updateop->SetOpCode(aOpCode);
+    AddAsyncOpToQueue(updateop);
+    }
+    
+    
+// ------------------------------------------------------------------
+// CLbtContainerAO::DeleteTriggersL
+// ------------------------------------------------------------------
+//    
+void CLbtContainerAO::DeleteTriggersL( CLbtContainerUpdateFilter* aFilter,
+									   TInt aOpCode,
+									   TRequestStatus& aStatus,
+									   TLbtSecurityPolicy aSecurityPolicy )
+    {
+    FUNC_ENTER("CLbtContainerAO::DeleteTriggersL");
+    CLbtDeleteAsyncOperation* deleteop = CLbtDeleteAsyncOperation::NewL(aFilter, aStatus, aSecurityPolicy);
+    deleteop->SetOpCode(aOpCode);
+    AddAsyncOpToQueue(deleteop);
+    }
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::CreateTriggerL
+// ------------------------------------------------------------------
+//    
+void CLbtContainerAO::CreateTriggerL(CLbtContainerTriggerEntry* aEntry,TInt aOpCode,TRequestStatus& aStatus) 
+ 	{
+ 	FUNC_ENTER("CLbtContainerAO::CreateTriggerL");
+ 	CLbtCreateAsyncOperation* createop = CLbtCreateAsyncOperation::NewL(aEntry,aStatus);
+ 	createop->SetOpCode(aOpCode);
+ 	AddAsyncOpToQueue(createop);	
+ 	}
+
+// ---------------------------------------------------------
+// CLbtContainerAO::RunL
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CLbtContainerAO::RunL()
+    {
+    FUNC_ENTER("CLbtContainerAO::RunL");
+   	TInt error=iStatus.Int();
+   	
+   	if( error == KErrCancel )
+   		{
+   		if( iAsyncOpQueue.Count() > 0 )
+			{
+			StartNextAsyncOperation();
+			}
+		return;
+   		}
+   	
+   	if(iTriggerStoreCtr < iTriggerStores.Count() - 1)
+   	    {
+        iTriggerStoreCtr++;
+        if(iTriggerStoreCtr == 0)
+            {             
+            iAsyncOpQueue[0]->StartAOOperationL( iTriggerStores[iTriggerStoreCtr],iStatus); 
+            SetActive();
+            }
+        else if(iTriggerStoreCtr == 1)
+            {
+            if(error == KErrNone || error == KErrNotFound)
+                {
+                iAsyncOpQueue[0]->SetCurrentReturnCode(error);                
+                iAsyncOpQueue[0]->StartAOOperationL( iTriggerStores[iTriggerStoreCtr],iStatus);
+                SetActive();                
+                }
+            else 
+                {
+                CompleteAsyncRequest(error);
+                if(iAsyncOpQueue.Count()>0)
+   	                {
+           	        StartNextAsyncOperation();
+                    }
+                }
+            }
+        else if(iTriggerStoreCtr>1)
+            {
+            TInt prevError = iAsyncOpQueue[0]->GetPrevReturnCode();
+            TInt currError = iAsyncOpQueue[0]->GetCurrentReturnCode();
+            
+            /* if previous error is KErrNotFound and current is KErrNone
+             * then make previous as KErrNone 
+             * else  if prev is KErrNone, that means that the operation has
+             * succeeded in atleast one trigger store so,
+             * let the prev code remain KErrNone
+             * even if the currErr is KErrNotFound
+             */
+            if((prevError == KErrNotFound || prevError == KErrNotReady) && (currError == KErrNone || currError == KErrNotReady))
+                {
+                iAsyncOpQueue[0]->SetPrevReturnCode(currError);
+                }
+            
+            /* Now once the prev code is modified, set the current code
+             * to the one this operation returned.
+             */
+            
+            iAsyncOpQueue[0]->SetCurrentReturnCode(error);
+            TInt prevCode,currCode;
+            prevCode = iAsyncOpQueue[0]->GetCurrentReturnCode();
+            currCode = iAsyncOpQueue[0]->GetPrevReturnCode();
+            
+            /* Start the operation with the next trigger store only if
+             * both the prevCode and CurrCode  are KErrNone or KErrNotFound
+             * else complete the request with the error code
+             */
+            if(((prevCode == KErrNotFound) ||( prevCode == KErrNone) || (prevCode == KErrNotReady))&&(currCode == KErrNotFound || currCode == KErrNone))
+                {
+                 if(iTriggerStoreCtr<iTriggerStores.Count())
+                    {
+                    iAsyncOpQueue[0]->StartAOOperationL( iTriggerStores[iTriggerStoreCtr],iStatus);
+                    SetActive();   
+                    }
+                  else
+                    {
+                    CompleteAsyncRequest(currCode);
+                    if(iAsyncOpQueue.Count()>0)
+   	                    {
+               	        StartNextAsyncOperation();
+                        }
+                    } 
+                 
+                }
+            else
+                {
+                CompleteAsyncRequest(currCode);
+                 if(iAsyncOpQueue.Count()>0)
+   	                {
+           	        StartNextAsyncOperation();
+                    }
+                }
+            }
+   	    }
+   	else
+   	    {
+        TInt prevCode = iAsyncOpQueue[0]->GetPrevReturnCode();
+        TInt currCode = iAsyncOpQueue[0]->GetCurrentReturnCode();    
+        
+        if(prevCode == KErrNone || currCode == KErrNone || error == KErrNone)
+            {
+            CompleteAsyncRequest(KErrNone);
+            }
+        else 
+            {
+            CompleteAsyncRequest(error);
+            }   
+             
+   	    if(iAsyncOpQueue.Count()>0)
+   	        {
+   	        StartNextAsyncOperation();
+   	        }
+   	    }    
+    }
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::CompleteAsyncRequest
+// ------------------------------------------------------------------
+//
+void CLbtContainerAO::CompleteAsyncRequest(TInt aErr)
+    {
+    FUNC_ENTER("CLbtContainerAO::CompleteAsyncRequest");
+    CLbtContainerAOOperation* asyncObjPtr = iAsyncOpQueue[0];    
+                
+    if( (iAsyncRequest == EOpCreateTrigger) && 
+        (aErr == KErrNone) )
+		{
+		CLbtCreateAsyncOperation* createop = static_cast <CLbtCreateAsyncOperation*> (asyncObjPtr);
+		
+		RArray<TLbtTriggerId> triggerIds;
+		CLbtContainerTriggerEntry* entry = const_cast<CLbtContainerTriggerEntry*>(createop->ContainerTriggerEntry());
+   		triggerIds.Append(entry->TriggerEntry()->Id());
+   		
+   		
+   		TLbtTriggerEventMask eventMask;
+   		
+   		// Append the manager uids and owner uids into the array
+   		RArray<TUid> managerui;
+   		managerui.Append( entry->TriggerEntry()->ManagerUi() );
+		
+   		TUid ownerUid;
+   		ownerUid.iUid = (TInt)( entry->ExtendedTriggerInfo()->OwnerSid().iId);
+   		managerui.Append( ownerUid );
+   		
+   		if( entry->TriggerEntry()->Type() == CLbtTriggerEntry::ETypeStartup )
+   			{
+   			CLbtStartupTrigger* startupTrigger = static_cast<CLbtStartupTrigger*>(entry->TriggerEntry());
+			TSecureId secureId;
+			TBuf16<KMaxFileName> fileName;
+			startupTrigger->GetProcessId(fileName, secureId);
+			TUid startupUid;
+			startupUid.iUid = (TInt)(secureId.iId);
+			
+			if( startupUid != KNullUid )
+				{				
+				managerui.Append( startupUid );
+				}
+   			}   		
+   
+   		// Give the observer callback through interface
+		for( TInt i = 0; i<iObservers.Count(); i++ )
+			{
+			TInt isRequested = EFalse;	
+			ProcessFilter(isRequested,iObservers[i].iEventMask,eventMask);
+			if(isRequested)
+				{
+				MLbtContainerChangeEventObserver::TLbtContainerChangedAreaType changeType = 
+										MLbtContainerChangeEventObserver::ETypeUnKnown;
+				const CLbtTriggerConditionArea* conditionBase = 
+						static_cast<const CLbtTriggerConditionArea*>(entry->TriggerEntry()->GetCondition());				
+				if(conditionBase)
+					{
+					CLbtGeoAreaBase* areaBase = conditionBase->TriggerArea();
+					
+					if(areaBase)
+						{
+						CLbtGeoAreaBase::TGeoAreaType areaType = areaBase->Type();
+					
+						if(areaType == CLbtGeoAreaBase::ECircle)
+							{
+							changeType = MLbtContainerChangeEventObserver::ETypeCircularTriggerChange;
+							}
+						else if(areaType == CLbtGeoAreaBase::ECellular)
+							{
+							changeType = MLbtContainerChangeEventObserver::ETypeCellularTriggerChange;
+							}
+						else
+							{
+							changeType = MLbtContainerChangeEventObserver::ETypeRectangularTriggerChange;
+							}
+						}					
+					}				
+								
+				//Ownership of triggersModified array is transferred to the client
+		    	iObservers[i].iObserver->TriggerStoreChanged(triggerIds, CLbtContainer::ELbtConTriggerCreated, changeType, managerui);
+		    	triggerIds.Reset();		    	
+				}
+			}
+		triggerIds.Close();
+		managerui.Close();
+    	}
+
+    if( EOpListTriggers == iAsyncRequest )
+	    {
+	    if( aErr == KErrNone)
+	        {
+	        RPointerArray<CLbtContainerTriggerEntry>* triggers = NULL;
+	        CLbtListAsyncOperation* listAsync = static_cast<CLbtListAsyncOperation*> (asyncObjPtr);
+            triggers = listAsync->GetTriggerList();
+
+            // sort the list using sorting options            
+            if( triggers )
+                {
+                SortTriggers(*triggers);        
+                }
+	        }
+	    else
+	        {
+            CLbtListAsyncOperation* listOp = static_cast<CLbtListAsyncOperation*>(asyncObjPtr);
+            RPointerArray<CLbtContainerTriggerEntry>* triggers = listOp->GetTriggerList();
+            triggers->ResetAndDestroy();
+	        }
+	     }
+    
+    // Now,notify the trigger store change observers.
+     if( EOpListTriggers != iAsyncRequest &&
+         EOpCreateTrigger != iAsyncRequest )
+		 {
+		 NotifyListeners();	
+		 }
+     
+    TRequestStatus* status = asyncObjPtr->GetStatus();
+    // Sorting is completed,complete the client request.
+    User::RequestComplete(status,aErr);     
+
+	iAsyncOpQueue.Remove(0);	
+	iAsyncRequest = EOpNone;
+    delete asyncObjPtr;    
+    }
+
+// ---------------------------------------------------------
+// CLbtContainerAO::RunError
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CLbtContainerAO::RunError(TInt /*aError*/)
+    {
+    FUNC_ENTER("CLbtContainerAO::RunError");
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+// CLbtContainerAO::DoCancel
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CLbtContainerAO::DoCancel()
+    {
+    FUNC_ENTER("CLbtContainerAO::DoCancel");
+	CLbtContainerAOOperation* cancelObj = iAsyncOpQueue[0];
+	// Cancel current operation of trigger store
+	
+	TInt error = KErrCancel;
+	if( iTriggerStoreCtr!= -1 )
+	    {
+	    error = iTriggerStores[iTriggerStoreCtr]->CancelCurrentOperation();
+	    }
+	CompleteAsyncRequest( error );	
+	if(iAsyncOpQueue.Count()>0)
+        {
+        StartNextAsyncOperation();
+        }
+    }
+
+// ---------------------------------------------------------
+// CLbtContainerAO::NotifyListeners
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CLbtContainerAO::NotifyListeners()
+	{
+	FUNC_ENTER("CLbtContainerAO::NotifyListeners");
+	TLbtTriggerEventMask eventMask;
+		
+	CLbtRamTriggersManager* ramTriggerMgr = NULL;
+	CLbtDbTriggersManager* dbTriggerMgr = NULL;
+	
+	RArray<MLbtTriggerStore::TLbtTriggerModifiedInfo> triggerInfoArray;
+	
+	// Get the list of triggers which were modified for a  given operation
+	for( TInt i = 0; i<iTriggerStores.Count(); i++ )
+		{
+		if( CLbtTriggerEntry::ETypeSession == iTriggerStores[i]->SupportedTriggerTypes() )
+			{
+			ramTriggerMgr = static_cast<CLbtRamTriggersManager*> (iTriggerStores[i]);
+			ramTriggerMgr->TriggersModified(triggerInfoArray);	
+			}
+		else if( CLbtTriggerEntry::ETypeStartup == iTriggerStores[i]->SupportedTriggerTypes() )
+			{
+			dbTriggerMgr = static_cast<CLbtDbTriggersManager*> (iTriggerStores[i]);
+			dbTriggerMgr->TriggersModified(triggerInfoArray);		
+			}	
+		}
+		
+	if(triggerInfoArray.Count() <= 0)
+		{
+		triggerInfoArray.Close();
+		// If no triggers are modified then no notification required
+		return;
+		}
+
+	TInt changedAreaType = MLbtContainerChangeEventObserver::ETypeUnKnown;
+	for(TInt i=0;i<triggerInfoArray.Count();++i)
+		{
+		if(triggerInfoArray[i].iAreaType == CLbtGeoAreaBase::ECircle)
+			{
+			changedAreaType = changedAreaType | MLbtContainerChangeEventObserver::ETypeCircularTriggerChange;
+			}
+		else if(triggerInfoArray[i].iAreaType == CLbtGeoAreaBase::ECellular)
+			{
+			changedAreaType = changedAreaType | MLbtContainerChangeEventObserver::ETypeCellularTriggerChange;
+			}
+		else if(triggerInfoArray[i].iAreaType == CLbtGeoAreaBase::ERectangular)
+			{
+			changedAreaType = changedAreaType | MLbtContainerChangeEventObserver::ETypeRectangularTriggerChange;
+			}
+		}
+
+	RArray<TLbtTriggerId> triggersModified;
+	RArray<TUid> managerUis;
+	for(TInt i=0;i<triggerInfoArray.Count();++i)
+		{
+		triggersModified.Append(triggerInfoArray[i].iTriggerId);
+		
+		if( managerUis.Find(triggerInfoArray[i].iManagerUi) == KErrNotFound )
+			{
+			// Appen both manager ui and owner into manager uis
+			managerUis.Append(triggerInfoArray[i].iManagerUi);			
+			}
+			
+		if( managerUis.Find(triggerInfoArray[i].iOwner) == KErrNotFound )
+			{
+			managerUis.Append(triggerInfoArray[i].iOwner);
+			}
+		
+		if( managerUis.Find(triggerInfoArray[i].iStartupProcess) == KErrNotFound &&
+		    triggerInfoArray[i].iStartupProcess !=  KNullUid )
+			{
+			managerUis.Append(triggerInfoArray[i].iStartupProcess);
+			}
+		}
+
+	TBool isRequested = EFalse;
+	// Give the observer callback through interface
+	for( TInt i = 0; i<iObservers.Count(); i++ )
+		{
+		isRequested = EFalse;	
+		ProcessFilter(isRequested,iObservers[i].iEventMask,eventMask);
+		if(isRequested)
+			{
+			MLbtContainerChangeEventObserver::TLbtContainerChangedAreaType areaType = 
+					static_cast<MLbtContainerChangeEventObserver::TLbtContainerChangedAreaType>(changedAreaType);
+			//Ownership of triggersModified array is transferred to the client
+		    iObservers[i].iObserver->TriggerStoreChanged( triggersModified, 
+		    											  eventMask, 
+		    											  areaType,
+		    											  managerUis );			
+			}
+		}
+	triggersModified.Close();
+	triggerInfoArray.Close();
+	managerUis.Close();
+	}
+
+// ---------------------------------------------------------
+// CLbtContainerAO::ProcessFilter
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CLbtContainerAO::ProcessFilter(TBool& aIsRequested,TLbtTriggerEventMask& aRequestedMask,TLbtTriggerEventMask& aEventMask)
+	{
+	FUNC_ENTER("CLbtContainerAO::ProcessFilter");
+	aEventMask = 0;
+	if( EOpUpdateTrigger == iAsyncRequest )
+		{
+		// Depending on the bitmask,form trigger change event
+		if( iAttrMask & CLbtTriggerEntry::EAttributeName )
+			{
+			aEventMask = aEventMask | CLbtContainer::ELbtConTriggerNameFieldChanged;
+			if((aRequestedMask&CLbtContainer::ELbtConTriggerNameFieldChanged) == CLbtContainer::ELbtConTriggerNameFieldChanged)
+				{
+				aIsRequested = ETrue;
+				}	
+			}
+		
+		if( iAttrMask & CLbtTriggerEntry::EAttributeState )
+			{
+			aEventMask = aEventMask | CLbtContainer::ELbtConTriggerStateFieldChanged;
+			if((aRequestedMask&CLbtContainer::ELbtConTriggerStateFieldChanged) == CLbtContainer::ELbtConTriggerStateFieldChanged)
+				{
+				aIsRequested = ETrue;
+				}
+			}
+		
+		if( iAttrMask & CLbtTriggerEntry::EAttributeCondition )
+			{
+			aEventMask = aEventMask | CLbtContainer::ELbtConTriggerConditionFieldChanged;
+			if((aRequestedMask&CLbtContainer::ELbtConTriggerConditionFieldChanged) == CLbtContainer::ELbtConTriggerConditionFieldChanged)
+				{
+				aIsRequested = ETrue;
+				}	
+			}
+		
+		if( iAttrMask & CLbtTriggerEntry::EAttributeStartUpProcessId )
+			{
+			aEventMask = aEventMask | CLbtContainer::ELbtConTriggerStartupFieldChanged;
+			if((aRequestedMask&CLbtContainer::ELbtConTriggerStartupFieldChanged) == CLbtContainer::ELbtConTriggerStartupFieldChanged)
+				{
+				aIsRequested = ETrue;
+				}	
+			}
+		
+		if( iDataMask & CLbtContainerTriggerEntry::EContainerAttributeRectTriggerArea )
+			{
+			aEventMask = aEventMask | CLbtContainer::ELbtConTriggerRectAreaFieldChanged;
+			if((aRequestedMask&CLbtContainer::ELbtConTriggerRectAreaFieldChanged) == CLbtContainer::ELbtConTriggerRectAreaFieldChanged)
+				{
+				aIsRequested = ETrue;
+				}	
+			}
+	
+		if( iDataMask & CLbtContainerTriggerEntry::EContainerAttributeHysteresisRadius )
+			{
+			aEventMask = aEventMask | CLbtContainer::ELbtConTriggerHysteresisFieldChanged;
+			if((aRequestedMask&CLbtContainer::ELbtConTriggerHysteresisFieldChanged) == CLbtContainer::ELbtConTriggerHysteresisFieldChanged)
+				{
+				aIsRequested = ETrue;
+				}	
+			}
+		
+		if( iDataMask & CLbtContainerTriggerEntry::EContainerAttributeIsFired )
+			{
+			aEventMask = aEventMask | CLbtContainer::ELbtConTriggerFiredFieldChanged;
+			if((aRequestedMask&CLbtContainer::ELbtConTriggerFiredFieldChanged) == CLbtContainer::ELbtConTriggerFiredFieldChanged)
+				{
+				aIsRequested = ETrue;
+				}	
+			}
+		
+		if( iDataMask & CLbtContainerTriggerEntry::EContainerAttributeStrategyData )
+			{
+			aEventMask = aEventMask | CLbtContainer::ELbtConTriggerStrategyDataFieldChanged;
+			if((aRequestedMask&CLbtContainer::ELbtConTriggerStrategyDataFieldChanged) == CLbtContainer::ELbtConTriggerStrategyDataFieldChanged)
+				{
+				aIsRequested = ETrue;
+				}		
+			}
+		
+		if( iDataMask & CLbtContainerTriggerEntry::EContainerDynInfoAttributeValidity )
+			{
+			aEventMask = aEventMask | CLbtContainer::ELbtConTriggerValidityFieldChanged;
+			if((aRequestedMask&CLbtContainer::ELbtConTriggerValidityFieldChanged) == CLbtContainer::ELbtConTriggerValidityFieldChanged)
+				{
+				aIsRequested = ETrue;
+				}
+			}
+		
+		if( iDataMask & CLbtContainerTriggerEntry::EContainerAttributeIsTriggerFireOnCreation )
+			{
+			aEventMask = aEventMask | CLbtContainer::ELbtConTriggerFireOnCreationFieldChanged;
+			if((aRequestedMask&CLbtContainer::ELbtConTriggerFireOnCreationFieldChanged) == CLbtContainer::ELbtConTriggerFireOnCreationFieldChanged)
+				{
+				aIsRequested = ETrue;
+				}
+			}                
+		}
+	else if( EOpUpdateTriggerState == iAsyncRequest )
+		{
+		//form trigger change event
+		aEventMask = CLbtContainer::ELbtConTriggerStateFieldChanged;	
+		if( aRequestedMask & CLbtContainer::ELbtConTriggerStateFieldChanged )
+			{
+			aIsRequested = ETrue;
+			}	
+		}
+	else if( EOpUpdateTriggersValidity == iAsyncRequest )
+		{
+		// form trigger change event
+		aEventMask = CLbtContainer::ELbtConTriggerValidityFieldChanged;
+		if( aRequestedMask & CLbtContainer::ELbtConTriggerValidityFieldChanged )
+			{
+			aIsRequested = ETrue;
+			}			
+		}
+	else if( EOpDeleteTriggers == iAsyncRequest )
+		{
+		// form trigger change event
+		aEventMask = CLbtContainer::ELbtConTriggerDeleted;	
+		if( aRequestedMask & CLbtContainer::ELbtConTriggerDeleted )
+			{
+			aIsRequested = ETrue;
+			}			
+		}
+	else if( EOpCreateTrigger == iAsyncRequest )
+		{		
+		if( aRequestedMask & CLbtContainer::ELbtConTriggerCreated )
+			{
+			aEventMask = CLbtContainer::ELbtConTriggerCreated;
+			aIsRequested = ETrue;
+			}
+		
+		if( aRequestedMask & CLbtContainer::ELbtConTriggerEnabledAndValidCreated )
+			{
+			// Get the currently running ao operation object and check if the trigger is enabled and valid
+			CLbtCreateAsyncOperation* operation = static_cast<CLbtCreateAsyncOperation*>(iAsyncOpQueue[0]);
+			CLbtContainerTriggerEntry* entry = const_cast<CLbtContainerTriggerEntry*>(operation->ContainerTriggerEntry());
+			
+			if( entry->TriggerEntry()->State() == CLbtTriggerEntry::EStateEnabled && 
+				entry->DynInfo()->iValidity == TLbtTriggerDynamicInfo::EValid)
+				{
+				// The trigger is enabled and valid, hence notify
+				aEventMask = CLbtContainer::ELbtConTriggerEnabledAndValidCreated;
+				aIsRequested = ETrue;
+				}			
+			}
+		}
+	}
+ 
+// ------------------------------------------------------------------
+// CLbtContainerAO::SortTriggers
+// ------------------------------------------------------------------
+//
+void CLbtContainerAO::SortTriggers(RPointerArray<CLbtContainerTriggerEntry>& aTriggers)
+	 {
+	 FUNC_ENTER("CLbtContainerAO::SortTriggers");
+	 if(CLbtListTriggerOptions::ELbtNoSorting == iSortingOption)
+		 {
+		 //No sorting
+		 return;
+		 }
+	 else if(CLbtListTriggerOptions::ELbtTriggerNameAscending == iSortingOption)
+		 {
+		 //sort by name ascending
+		 SortByName(aTriggers);
+		 }
+	else if(CLbtListTriggerOptions::ELbtTriggerNameDescending == iSortingOption)
+		{
+		//sort by name ascending
+		// reverse the array
+		SortByName(aTriggers);
+		ReverseArray(aTriggers);		
+		}
+	else if(CLbtListTriggerOptions::ELbtDistanceToLatestLocationAscending == iSortingOption)
+		{
+		//sort by distance ascending
+		SortByDistance(aTriggers);	
+		}		
+	 }
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::SortByName
+// ------------------------------------------------------------------
+//
+void CLbtContainerAO::SortByName(RPointerArray<CLbtContainerTriggerEntry>& aTriggers)
+	{
+	FUNC_ENTER("CLbtContainerAO::SortByName");
+    TBool isFinished=EFalse;
+    CLbtContainerTriggerEntry* temp=NULL;
+
+    while(!isFinished)
+	    {
+	    isFinished=ETrue;
+	    for(TInt i = 1 ;i <= aTriggers.Count()-1 ; i++)
+		    {
+		    if( aTriggers[i]->TriggerEntry()->Name() < aTriggers[i-1]->TriggerEntry()->Name() )	
+			    {
+			    temp=aTriggers[i-1];
+			    aTriggers[i-1]=aTriggers[i];
+			    aTriggers[i]=temp;
+			    isFinished=EFalse;
+			    }
+	        }	       
+	    }
+	}
+    
+// ------------------------------------------------------------------
+// CLbtContainerAO::SortByDistance
+// ------------------------------------------------------------------
+//        
+void CLbtContainerAO::SortByDistance(RPointerArray<CLbtContainerTriggerEntry>& aTriggers)
+	{
+	FUNC_ENTER("CLbtContainerAO::SortByDistance");
+	TBool isFinished=EFalse;
+    CLbtContainerTriggerEntry* temp=NULL;
+
+    while(!isFinished)
+	    {
+	    isFinished=ETrue;
+	    for(TInt i = 1 ;i <= aTriggers.Count()-1 ; i++)
+		    {
+		    if( aTriggers[i]->DynInfo()->iDistanceToLatestLocation < aTriggers[i-1]->DynInfo()->iDistanceToLatestLocation )	
+			    {
+			    temp=aTriggers[i-1];
+			    aTriggers[i-1]=aTriggers[i];
+			    aTriggers[i]=temp;
+			    isFinished=EFalse;
+			    }
+	        }	       
+	    }
+    }
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::ReverseArray
+// ------------------------------------------------------------------
+//
+void CLbtContainerAO::ReverseArray(RPointerArray<CLbtContainerTriggerEntry>& aTriggers)
+	{
+	FUNC_ENTER("CLbtContainerAO::ReverseArray");
+	int i=0;
+	int j=aTriggers.Count()-1;
+	CLbtContainerTriggerEntry* temp=NULL;
+	
+	while(i < j)
+		{
+		temp=aTriggers[i];
+		aTriggers[i]=aTriggers[j];
+		aTriggers[j]=temp;
+		i++;
+		j--;
+		}
+	}
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::CancelAsyncRequest
+// ------------------------------------------------------------------
+//
+void CLbtContainerAO::CancelAsyncRequest(TInt aOpId)
+	{
+	FUNC_ENTER("CLbtContainerAO::CancelAsyncRequest");
+	
+	if(iAsyncOpQueue.Count() > 0)
+		{
+		if(iAsyncOpQueue[0]->GetOpCode() == aOpId)
+			{
+			// Currently running operation
+			if( IsActive() )
+				{
+				Cancel();
+				}
+			else
+				{
+				CLbtContainerAOOperation* cancelObj = iAsyncOpQueue[0];
+				iAsyncOpQueue.Remove(0);
+				if( iAsyncRequest == EOpListTriggers )
+					{
+					CLbtListAsyncOperation* listOp = static_cast<CLbtListAsyncOperation*> (cancelObj);
+					listOp->FreeArray();
+					}
+				TRequestStatus* status = cancelObj->GetStatus();
+				User::RequestComplete(status, KErrCancel);
+				delete cancelObj;
+				if(iAsyncOpQueue.Count()>0)
+			        {
+			        StartNextAsyncOperation();
+			        }
+				}	
+			}
+		else
+			{
+			for(TInt i=1;i < iAsyncOpQueue.Count(); ++i)
+				{
+				if(iAsyncOpQueue[i]->GetOpCode() == aOpId)
+					{
+					CLbtContainerAOOperation* cancelObj = iAsyncOpQueue[i];
+					iAsyncOpQueue.Remove(i);
+					TRequestStatus* status = cancelObj->GetStatus();
+					User::RequestComplete(status,KErrCancel);
+					delete cancelObj;
+					break;
+					}
+				}			
+			}
+		}	
+	}
+
+// ------------------------------------------------------------------
+// CLbtContainerAO::NotifyTriggerStoreReadyToServe
+// ------------------------------------------------------------------
+//
+void CLbtContainerAO::NotifyTriggerStoreReadyToServe()
+	{
+	FUNC_ENTER("CLbtContainerAO::NotifyTriggerStoreReadyToServe");
+	if(iAsyncOpQueue.Count() > 0)
+	    {
+	    StartNextAsyncOperation();
+	    }
+	}
+
+//  End of File