phonebookengines/contactsmodel/cntview/cntphbksyncwatcher.cpp
changeset 0 e686773b3f54
child 24 0ba2181d7c28
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 #include <cntdb.h>
       
    18 #include <phbksync.h>
       
    19 
       
    20 #include "CNTSTD.H"
       
    21 #include "CNTPHBKSYNCWATCHER.H"
       
    22 
       
    23 
       
    24 //uncomment for commonly required debug printing
       
    25 //#define __VERBOSE_DEBUG__
       
    26 
       
    27 
       
    28 
       
    29 /*
       
    30  class CContactPhbkSyncWatcher is a simple class that aggregates
       
    31  synchronisation events from the different ICC phonebooks (e.g. Global ADN or USIM App ADN)
       
    32  */
       
    33 CContactPhbkSyncWatcher* CContactPhbkSyncWatcher::NewL(MContactSynchroniser& aSyncPlugin)
       
    34 	{
       
    35 	CContactPhbkSyncWatcher* self = new (ELeave) CContactPhbkSyncWatcher(aSyncPlugin);
       
    36 	CleanupStack::PushL(self);
       
    37 	self->ConstructL();
       
    38 	CleanupStack::Pop(self);
       
    39 	return self;
       
    40 	}
       
    41 	
       
    42 
       
    43 /*
       
    44  Release all resources.
       
    45  */
       
    46 CContactPhbkSyncWatcher::~CContactPhbkSyncWatcher()
       
    47 	{
       
    48 	__ASSERT_DEBUG(iObservers.Count() == 0, Panic(ECntPhonebookSyncObserverList));
       
    49 	iObservers.Close();
       
    50 	// delete each phbk watcher
       
    51 	iWatchers.ResetAndDestroy();
       
    52 	iWatchers.Close();
       
    53 	}
       
    54 
       
    55 
       
    56 CContactPhbkSyncWatcher::CContactPhbkSyncWatcher(MContactSynchroniser& aSyncPlugin) : iSyncPlugin(aSyncPlugin)
       
    57 	{
       
    58 	}
       
    59 
       
    60 
       
    61 /*
       
    62  Create an array of active objects, one for each Phonebook on the ICC (SIM card),
       
    63  to observer Phonebook Synchroniser state change events.
       
    64  */
       
    65 void CContactPhbkSyncWatcher::ConstructL()
       
    66 	{
       
    67 	RArray<TUid> phbkList;
       
    68 	CleanupClosePushL(phbkList);
       
    69 
       
    70 	// get list of phonebooks for type of ICC (SIM card) present
       
    71 	TInt error = iSyncPlugin.PhonebookList(phbkList);
       
    72 	User::LeaveIfError(error);
       
    73 	const TInt count = phbkList.Count();
       
    74 
       
    75 	for (TInt j = 0; j < count; ++j)
       
    76 		{
       
    77 		iWatchers.AppendL(CSinglePhbkWatcher::NewLC(*this, phbkList[j]));
       
    78 		CleanupStack::Pop(); // CSinglePhbkWatcher
       
    79 		}
       
    80 
       
    81 	CleanupStack::PopAndDestroy();	// close phbkList
       
    82 	}
       
    83 
       
    84 
       
    85 /*
       
    86  Add Contact View to observer list.
       
    87  */
       
    88 void CContactPhbkSyncWatcher::AddPhbkObserverL(MContactPhbkSyncObserver& aChangeNotifier)
       
    89 	{
       
    90 	iObservers.AppendL(&aChangeNotifier);
       
    91 	}
       
    92 
       
    93 
       
    94 /*
       
    95  Remove Contact View from observer list.
       
    96  */
       
    97 void CContactPhbkSyncWatcher::RemovePhbkObserver(MContactPhbkSyncObserver& aChangeNotifier)
       
    98 	{
       
    99 	const TInt observerIndex = iObservers.Find(&aChangeNotifier);
       
   100 
       
   101 	if (observerIndex != KErrNotFound)
       
   102 		{
       
   103 		iObservers.Remove(observerIndex);
       
   104 		}
       
   105 	}
       
   106 
       
   107 
       
   108 /*
       
   109  Count of views Phonebooks that are Synchronised.
       
   110  */
       
   111 TInt CContactPhbkSyncWatcher::PhonebooksReady()
       
   112 	{
       
   113 	// number of phonebooks that are ready
       
   114 	return iPhonebooksReady;
       
   115 	}
       
   116 
       
   117 /*
       
   118  Count of views Phonebooks that are locked (PIN not yet entered).
       
   119  */
       
   120 TInt CContactPhbkSyncWatcher::PhonebooksWaiting()
       
   121 	{
       
   122 	// number of phonebooks that are waiting
       
   123 	return iPhonebooksWaiting;
       
   124 	}
       
   125 
       
   126 /*
       
   127  Last error, if any, from Phonebook Synchronisation.
       
   128  */
       
   129 TInt CContactPhbkSyncWatcher::PhonebookSyncError()
       
   130 	{
       
   131 	// most recent phbksync error
       
   132 	return iSyncError;
       
   133 	}
       
   134 
       
   135 /*
       
   136  Pointer to the Phonebook Synchroniser plug-in.
       
   137  */
       
   138 MContactSynchroniser& CContactPhbkSyncWatcher::SyncPlugin()
       
   139 	{
       
   140 	return iSyncPlugin;
       
   141 	}
       
   142 
       
   143 
       
   144 /*
       
   145  Count of views observing Phonebook Synchroniser events.
       
   146  */
       
   147 TInt CContactPhbkSyncWatcher::ObserverCount()
       
   148 	{
       
   149 	return iObservers.Count();
       
   150 	}
       
   151 
       
   152 
       
   153 /*
       
   154  Distributor of Phonebook Sync state changes.
       
   155  
       
   156  
       
   157  */
       
   158 void CContactPhbkSyncWatcher::SendWatcherEvent(TPhonebookState aNewState, TPhonebookState aOldState, TInt aError)
       
   159 	{
       
   160 #if defined(__VERBOSE_DEBUG__)
       
   161 	RDebug::Print(_L("[CNTMODEL] CContactPhbkSyncWatcher::SendWatcherEvent(NewState = %i, OldState = %i, error = %i)\n\r"), 
       
   162 		aNewState, aOldState, aError);
       
   163 #endif
       
   164 
       
   165 	// Guard maybe the state has not really changed
       
   166 	if (aNewState != aOldState)
       
   167 		{
       
   168 		// track numbers of synchronised & locked phonebooks:
       
   169 		
       
   170 		// decrement count associated with the old state
       
   171 		switch (aOldState)
       
   172 			{
       
   173 		case EIccPhbkNotSynchronised:
       
   174 			break;
       
   175 		case EIccPhbkSynchronised:
       
   176 			--iPhonebooksReady;
       
   177 			break;
       
   178 		case EIccWaitForPhbkToBeReady:
       
   179 			--iPhonebooksWaiting;
       
   180 			break;
       
   181 		case EIccPhbkSyncError:
       
   182 			--iPhonebookErrors;
       
   183 			if (0 == iPhonebookErrors)
       
   184 				{
       
   185 				iSyncError = KErrNone;
       
   186 				}
       
   187 			break;
       
   188 			}
       
   189 
       
   190 		// increment count associated with the new state
       
   191 		switch (aNewState)
       
   192 			{
       
   193 		case EIccPhbkNotSynchronised:
       
   194 			break;
       
   195 		case EIccPhbkSynchronised:
       
   196 			++iPhonebooksReady;
       
   197 			break;
       
   198 		case EIccWaitForPhbkToBeReady:
       
   199 			++iPhonebooksWaiting;
       
   200 			break;
       
   201 		case EIccPhbkSyncError:
       
   202 			++iPhonebookErrors;
       
   203 			iSyncError = aError;
       
   204 			break;
       
   205 			}
       
   206 
       
   207 #if defined(__VERBOSE_DEBUG__)
       
   208 		RDebug::Print(_L("[ PhonebooksReady = %i, PhonebooksWaiting = %i, PhonebookErrors = %i, SyncError = %i)\n\r"), 
       
   209 			iPhonebooksReady, iPhonebooksWaiting, iPhonebookErrors, iSyncError);
       
   210 #endif
       
   211 
       
   212 		// distribute the state change to all observing contact views
       
   213 		const TInt count = iObservers.Count();
       
   214 		for(TInt loop = count; loop > 0; --loop)
       
   215 			{
       
   216 			iObservers[loop - 1]->ContactPhbkSyncEventHandler(aNewState);
       
   217 			}
       
   218 		}
       
   219 	}
       
   220 
       
   221 
       
   222 /*
       
   223  class CSinglePhbkWatcher tracks the status of an ICC phonebook
       
   224 
       
   225  This is a very simple CActive derived class.
       
   226  */
       
   227 CSinglePhbkWatcher* CSinglePhbkWatcher::NewLC(CContactPhbkSyncWatcher& aSyncWatcher, TUid& aPhonebookUid)
       
   228 	{
       
   229 #if defined(__VERBOSE_DEBUG__)
       
   230 	RDebug::Print(_L("[CNTMODEL] CSinglePhbkWatcher::CSinglePhbkWatcher(PhonebookUid = 0x%X)\n\r"), aPhonebookUid.iUid);
       
   231 #endif
       
   232 
       
   233 	CSinglePhbkWatcher* self = new(ELeave) CSinglePhbkWatcher(aSyncWatcher, aPhonebookUid);
       
   234 	CleanupStack::PushL(self);
       
   235 	return self;
       
   236 	}
       
   237 	
       
   238 	
       
   239 /*
       
   240  Standard CActive destructor.
       
   241  */
       
   242 CSinglePhbkWatcher::~CSinglePhbkWatcher()
       
   243 	{
       
   244 	Cancel();
       
   245 	}
       
   246 
       
   247 
       
   248 /*
       
   249  Standard CActive constructor, adds itself to the active scheduler.
       
   250  */
       
   251 CSinglePhbkWatcher::CSinglePhbkWatcher(CContactPhbkSyncWatcher& aSyncWatcher, TUid& aPhonebookUid) :
       
   252 	CActive(CActive::EPriorityStandard), iSyncWatcher(aSyncWatcher), iPhonebookUid(aPhonebookUid), iPhbkState(EIccPhbkNotSynchronised)
       
   253 	{
       
   254 	CActiveScheduler::Add(this);
       
   255 	// ensure active scheduler calls RunL for the first time
       
   256 	TRequestStatus* ptrStatus = &iStatus;
       
   257 	*ptrStatus = KRequestPending;
       
   258 	User::RequestComplete(ptrStatus, KErrNone);
       
   259 	SetActive();
       
   260 	}
       
   261 
       
   262 
       
   263 /*
       
   264  Register for Phonebook Synchroniser state change notification for this phonebook.
       
   265  */
       
   266 void CSinglePhbkWatcher::Start()
       
   267 	{
       
   268 #if defined(__VERBOSE_DEBUG__)
       
   269 	RDebug::Print(_L("[CNTMODEL] CSinglePhbkWatcher{PhonebookUid = 0x%X}::Start(), &iStatus = 0x%X\n\r"),
       
   270 		iPhonebookUid.iUid, &iStatus);
       
   271 #endif
       
   272 
       
   273 	// Waiting for ICC to be ready and for this Phonebook to synchronise
       
   274 	iSyncWatcher.SyncPlugin().NotifySyncStateChange(iStatus, iPhonebookUid);
       
   275 	SetActive();
       
   276 	}
       
   277 
       
   278 
       
   279 /*
       
   280  Cancel any active request to the phonebook synchroniser
       
   281  */
       
   282 void CSinglePhbkWatcher::DoCancel()
       
   283 	{
       
   284 #if defined(__VERBOSE_DEBUG__)
       
   285 	RDebug::Print(_L("[CNTMODEL] CSinglePhbkWatcher{PhonebookUid = 0x%X}::DoCancel()\n\r"), iPhonebookUid.iUid);
       
   286 #endif
       
   287 
       
   288 	// cleanup for Delete, RunL may have left an outstanding NotifySyncStateChangeL request
       
   289 	iSyncWatcher.SyncPlugin().CancelNotifyRequest(iPhonebookUid);
       
   290 	}
       
   291 
       
   292 
       
   293 /*
       
   294  Process Phonebook Synchroniser notifications for this Phonebook.
       
   295  
       
   296  Error conditions drop out to the RunError() handler.
       
   297  This can only end up at the Synchronised or Not Synchronised states,
       
   298  which are passed back to the parent CContactPhbkSyncWatcher.
       
   299  */
       
   300 void CSinglePhbkWatcher::RunL()
       
   301 	{
       
   302 #if defined(__VERBOSE_DEBUG__)
       
   303 	RDebug::Print(_L("[CNTMODEL] CSinglePhbkWatcher{PhonebookUid = 0x%X}::RunL(), iStatus = %i\n\r"), iPhonebookUid.iUid, iStatus.Int());
       
   304 #endif
       
   305 	
       
   306 	const TInt status = iStatus.Int();
       
   307 
       
   308 	// re-start, for next change
       
   309 	Start();
       
   310 
       
   311 	// ignore KErrCancel
       
   312 	if (status != KErrCancel)
       
   313 		{
       
   314 
       
   315 		User::LeaveIfError(status);
       
   316 
       
   317 		TBool isPhbkSync = iSyncWatcher.SyncPlugin().IsSynchronisedL(iPhonebookUid);
       
   318 
       
   319 		TPhonebookState oldState = iPhbkState;
       
   320 		if (isPhbkSync)
       
   321 			{
       
   322 			iPhbkState = EIccPhbkSynchronised;
       
   323 			}
       
   324 		else
       
   325 			{
       
   326 			iPhbkState = EIccPhbkNotSynchronised;
       
   327 			}
       
   328 
       
   329 		iSyncWatcher.SendWatcherEvent(iPhbkState, oldState);
       
   330 		}
       
   331 	}
       
   332 
       
   333 
       
   334 /*
       
   335  Process Phonebook Synchroniser errors for this Phonebook.
       
   336  
       
   337  Error conditions either come from completion with an error code or 
       
   338  the Phonebook Synchroniser IsSynchronisedL() method leaving.
       
   339  This can only end up at the PhbkLocked or PhbkSyncError states,
       
   340  which are passed back to the parent CContactPhbkSyncWatcher.
       
   341  */
       
   342 TInt CSinglePhbkWatcher::RunError(TInt aError)
       
   343 	{
       
   344 #if defined(__VERBOSE_DEBUG__)
       
   345 	RDebug::Print(_L("[CNTMODEL] CSinglePhbkWatcher{PhonebookUid = 0x%X}::RunError(%i)\n\r"), iPhonebookUid.iUid, aError);
       
   346 #endif
       
   347 
       
   348 	// IsSynchronisedL() left
       
   349 	if (IsAcceptableError(aError))
       
   350 		{
       
   351 		// notify that ICC phonebook is locked
       
   352 		iSyncWatcher.SendWatcherEvent(EIccWaitForPhbkToBeReady, iPhbkState);
       
   353 		iPhbkState = EIccWaitForPhbkToBeReady;
       
   354 		}
       
   355 	else
       
   356 		{
       
   357 		// notify that ICC phonebook sync has an error
       
   358 		iSyncWatcher.SendWatcherEvent(EIccPhbkSyncError, iPhbkState, aError);
       
   359 		iPhbkState = EIccPhbkSyncError;
       
   360 		}
       
   361 	return KErrNone;
       
   362 	}
       
   363 	
       
   364 /*
       
   365 Process Phonebook errors recieved in RunError and check if they should be treated
       
   366 as acceptable errors or as sync errors.
       
   367 */
       
   368 TBool CSinglePhbkWatcher::IsAcceptableError(TInt aSyncError)
       
   369 	{
       
   370 	switch(aSyncError)
       
   371 		{
       
   372 		case KErrAccessDenied:
       
   373 		case KErrNotReady:
       
   374 			{
       
   375 			return ETrue;	
       
   376 			}
       
   377 		default:
       
   378 			return EFalse;
       
   379 		}	
       
   380 	}
       
   381 
       
   382