phonebookengines/contactsmodel/cntview/cntphbksyncwatcher.cpp
changeset 0 e686773b3f54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntview/cntphbksyncwatcher.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,382 @@
+// Copyright (c) 2005-2009 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 <cntdb.h>
+#include <phbksync.h>
+
+#include "CNTSTD.H"
+#include "CNTPHBKSYNCWATCHER.H"
+
+
+//uncomment for commonly required debug printing
+//#define __VERBOSE_DEBUG__
+
+
+
+/*
+ class CContactPhbkSyncWatcher is a simple class that aggregates
+ synchronisation events from the different ICC phonebooks (e.g. Global ADN or USIM App ADN)
+ */
+CContactPhbkSyncWatcher* CContactPhbkSyncWatcher::NewL(MContactSynchroniser& aSyncPlugin)
+	{
+	CContactPhbkSyncWatcher* self = new (ELeave) CContactPhbkSyncWatcher(aSyncPlugin);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+	
+
+/*
+ Release all resources.
+ */
+CContactPhbkSyncWatcher::~CContactPhbkSyncWatcher()
+	{
+	__ASSERT_DEBUG(iObservers.Count() == 0, Panic(ECntPhonebookSyncObserverList));
+	iObservers.Close();
+	// delete each phbk watcher
+	iWatchers.ResetAndDestroy();
+	iWatchers.Close();
+	}
+
+
+CContactPhbkSyncWatcher::CContactPhbkSyncWatcher(MContactSynchroniser& aSyncPlugin) : iSyncPlugin(aSyncPlugin)
+	{
+	}
+
+
+/*
+ Create an array of active objects, one for each Phonebook on the ICC (SIM card),
+ to observer Phonebook Synchroniser state change events.
+ */
+void CContactPhbkSyncWatcher::ConstructL()
+	{
+	RArray<TUid> phbkList;
+	CleanupClosePushL(phbkList);
+
+	// get list of phonebooks for type of ICC (SIM card) present
+	TInt error = iSyncPlugin.PhonebookList(phbkList);
+	User::LeaveIfError(error);
+	const TInt count = phbkList.Count();
+
+	for (TInt j = 0; j < count; ++j)
+		{
+		iWatchers.AppendL(CSinglePhbkWatcher::NewLC(*this, phbkList[j]));
+		CleanupStack::Pop(); // CSinglePhbkWatcher
+		}
+
+	CleanupStack::PopAndDestroy();	// close phbkList
+	}
+
+
+/*
+ Add Contact View to observer list.
+ */
+void CContactPhbkSyncWatcher::AddPhbkObserverL(MContactPhbkSyncObserver& aChangeNotifier)
+	{
+	iObservers.AppendL(&aChangeNotifier);
+	}
+
+
+/*
+ Remove Contact View from observer list.
+ */
+void CContactPhbkSyncWatcher::RemovePhbkObserver(MContactPhbkSyncObserver& aChangeNotifier)
+	{
+	const TInt observerIndex = iObservers.Find(&aChangeNotifier);
+
+	if (observerIndex != KErrNotFound)
+		{
+		iObservers.Remove(observerIndex);
+		}
+	}
+
+
+/*
+ Count of views Phonebooks that are Synchronised.
+ */
+TInt CContactPhbkSyncWatcher::PhonebooksReady()
+	{
+	// number of phonebooks that are ready
+	return iPhonebooksReady;
+	}
+
+/*
+ Count of views Phonebooks that are locked (PIN not yet entered).
+ */
+TInt CContactPhbkSyncWatcher::PhonebooksWaiting()
+	{
+	// number of phonebooks that are waiting
+	return iPhonebooksWaiting;
+	}
+
+/*
+ Last error, if any, from Phonebook Synchronisation.
+ */
+TInt CContactPhbkSyncWatcher::PhonebookSyncError()
+	{
+	// most recent phbksync error
+	return iSyncError;
+	}
+
+/*
+ Pointer to the Phonebook Synchroniser plug-in.
+ */
+MContactSynchroniser& CContactPhbkSyncWatcher::SyncPlugin()
+	{
+	return iSyncPlugin;
+	}
+
+
+/*
+ Count of views observing Phonebook Synchroniser events.
+ */
+TInt CContactPhbkSyncWatcher::ObserverCount()
+	{
+	return iObservers.Count();
+	}
+
+
+/*
+ Distributor of Phonebook Sync state changes.
+ 
+ 
+ */
+void CContactPhbkSyncWatcher::SendWatcherEvent(TPhonebookState aNewState, TPhonebookState aOldState, TInt aError)
+	{
+#if defined(__VERBOSE_DEBUG__)
+	RDebug::Print(_L("[CNTMODEL] CContactPhbkSyncWatcher::SendWatcherEvent(NewState = %i, OldState = %i, error = %i)\n\r"), 
+		aNewState, aOldState, aError);
+#endif
+
+	// Guard maybe the state has not really changed
+	if (aNewState != aOldState)
+		{
+		// track numbers of synchronised & locked phonebooks:
+		
+		// decrement count associated with the old state
+		switch (aOldState)
+			{
+		case EIccPhbkNotSynchronised:
+			break;
+		case EIccPhbkSynchronised:
+			--iPhonebooksReady;
+			break;
+		case EIccWaitForPhbkToBeReady:
+			--iPhonebooksWaiting;
+			break;
+		case EIccPhbkSyncError:
+			--iPhonebookErrors;
+			if (0 == iPhonebookErrors)
+				{
+				iSyncError = KErrNone;
+				}
+			break;
+			}
+
+		// increment count associated with the new state
+		switch (aNewState)
+			{
+		case EIccPhbkNotSynchronised:
+			break;
+		case EIccPhbkSynchronised:
+			++iPhonebooksReady;
+			break;
+		case EIccWaitForPhbkToBeReady:
+			++iPhonebooksWaiting;
+			break;
+		case EIccPhbkSyncError:
+			++iPhonebookErrors;
+			iSyncError = aError;
+			break;
+			}
+
+#if defined(__VERBOSE_DEBUG__)
+		RDebug::Print(_L("[ PhonebooksReady = %i, PhonebooksWaiting = %i, PhonebookErrors = %i, SyncError = %i)\n\r"), 
+			iPhonebooksReady, iPhonebooksWaiting, iPhonebookErrors, iSyncError);
+#endif
+
+		// distribute the state change to all observing contact views
+		const TInt count = iObservers.Count();
+		for(TInt loop = count; loop > 0; --loop)
+			{
+			iObservers[loop - 1]->ContactPhbkSyncEventHandler(aNewState);
+			}
+		}
+	}
+
+
+/*
+ class CSinglePhbkWatcher tracks the status of an ICC phonebook
+
+ This is a very simple CActive derived class.
+ */
+CSinglePhbkWatcher* CSinglePhbkWatcher::NewLC(CContactPhbkSyncWatcher& aSyncWatcher, TUid& aPhonebookUid)
+	{
+#if defined(__VERBOSE_DEBUG__)
+	RDebug::Print(_L("[CNTMODEL] CSinglePhbkWatcher::CSinglePhbkWatcher(PhonebookUid = 0x%X)\n\r"), aPhonebookUid.iUid);
+#endif
+
+	CSinglePhbkWatcher* self = new(ELeave) CSinglePhbkWatcher(aSyncWatcher, aPhonebookUid);
+	CleanupStack::PushL(self);
+	return self;
+	}
+	
+	
+/*
+ Standard CActive destructor.
+ */
+CSinglePhbkWatcher::~CSinglePhbkWatcher()
+	{
+	Cancel();
+	}
+
+
+/*
+ Standard CActive constructor, adds itself to the active scheduler.
+ */
+CSinglePhbkWatcher::CSinglePhbkWatcher(CContactPhbkSyncWatcher& aSyncWatcher, TUid& aPhonebookUid) :
+	CActive(CActive::EPriorityStandard), iSyncWatcher(aSyncWatcher), iPhonebookUid(aPhonebookUid), iPhbkState(EIccPhbkNotSynchronised)
+	{
+	CActiveScheduler::Add(this);
+	// ensure active scheduler calls RunL for the first time
+	TRequestStatus* ptrStatus = &iStatus;
+	*ptrStatus = KRequestPending;
+	User::RequestComplete(ptrStatus, KErrNone);
+	SetActive();
+	}
+
+
+/*
+ Register for Phonebook Synchroniser state change notification for this phonebook.
+ */
+void CSinglePhbkWatcher::Start()
+	{
+#if defined(__VERBOSE_DEBUG__)
+	RDebug::Print(_L("[CNTMODEL] CSinglePhbkWatcher{PhonebookUid = 0x%X}::Start(), &iStatus = 0x%X\n\r"),
+		iPhonebookUid.iUid, &iStatus);
+#endif
+
+	// Waiting for ICC to be ready and for this Phonebook to synchronise
+	iSyncWatcher.SyncPlugin().NotifySyncStateChange(iStatus, iPhonebookUid);
+	SetActive();
+	}
+
+
+/*
+ Cancel any active request to the phonebook synchroniser
+ */
+void CSinglePhbkWatcher::DoCancel()
+	{
+#if defined(__VERBOSE_DEBUG__)
+	RDebug::Print(_L("[CNTMODEL] CSinglePhbkWatcher{PhonebookUid = 0x%X}::DoCancel()\n\r"), iPhonebookUid.iUid);
+#endif
+
+	// cleanup for Delete, RunL may have left an outstanding NotifySyncStateChangeL request
+	iSyncWatcher.SyncPlugin().CancelNotifyRequest(iPhonebookUid);
+	}
+
+
+/*
+ Process Phonebook Synchroniser notifications for this Phonebook.
+ 
+ Error conditions drop out to the RunError() handler.
+ This can only end up at the Synchronised or Not Synchronised states,
+ which are passed back to the parent CContactPhbkSyncWatcher.
+ */
+void CSinglePhbkWatcher::RunL()
+	{
+#if defined(__VERBOSE_DEBUG__)
+	RDebug::Print(_L("[CNTMODEL] CSinglePhbkWatcher{PhonebookUid = 0x%X}::RunL(), iStatus = %i\n\r"), iPhonebookUid.iUid, iStatus.Int());
+#endif
+	
+	const TInt status = iStatus.Int();
+
+	// re-start, for next change
+	Start();
+
+	// ignore KErrCancel
+	if (status != KErrCancel)
+		{
+
+		User::LeaveIfError(status);
+
+		TBool isPhbkSync = iSyncWatcher.SyncPlugin().IsSynchronisedL(iPhonebookUid);
+
+		TPhonebookState oldState = iPhbkState;
+		if (isPhbkSync)
+			{
+			iPhbkState = EIccPhbkSynchronised;
+			}
+		else
+			{
+			iPhbkState = EIccPhbkNotSynchronised;
+			}
+
+		iSyncWatcher.SendWatcherEvent(iPhbkState, oldState);
+		}
+	}
+
+
+/*
+ Process Phonebook Synchroniser errors for this Phonebook.
+ 
+ Error conditions either come from completion with an error code or 
+ the Phonebook Synchroniser IsSynchronisedL() method leaving.
+ This can only end up at the PhbkLocked or PhbkSyncError states,
+ which are passed back to the parent CContactPhbkSyncWatcher.
+ */
+TInt CSinglePhbkWatcher::RunError(TInt aError)
+	{
+#if defined(__VERBOSE_DEBUG__)
+	RDebug::Print(_L("[CNTMODEL] CSinglePhbkWatcher{PhonebookUid = 0x%X}::RunError(%i)\n\r"), iPhonebookUid.iUid, aError);
+#endif
+
+	// IsSynchronisedL() left
+	if (IsAcceptableError(aError))
+		{
+		// notify that ICC phonebook is locked
+		iSyncWatcher.SendWatcherEvent(EIccWaitForPhbkToBeReady, iPhbkState);
+		iPhbkState = EIccWaitForPhbkToBeReady;
+		}
+	else
+		{
+		// notify that ICC phonebook sync has an error
+		iSyncWatcher.SendWatcherEvent(EIccPhbkSyncError, iPhbkState, aError);
+		iPhbkState = EIccPhbkSyncError;
+		}
+	return KErrNone;
+	}
+	
+/*
+Process Phonebook errors recieved in RunError and check if they should be treated
+as acceptable errors or as sync errors.
+*/
+TBool CSinglePhbkWatcher::IsAcceptableError(TInt aSyncError)
+	{
+	switch(aSyncError)
+		{
+		case KErrAccessDenied:
+		case KErrNotReady:
+			{
+			return ETrue;	
+			}
+		default:
+			return EFalse;
+		}	
+	}
+
+