pimprotocols/phonebooksync/Server/SyncContactsWithICC.cpp
changeset 0 e686773b3f54
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 // Copyright (c) 2002-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 // Contains method implementations for the Active Object classes used by the Phonebook 
       
    15 // Synchroniser.
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21  @internalComponent
       
    22 */
       
    23 
       
    24 #include "common.h"
       
    25 #include "Phonebook.h"
       
    26 #include "PhonebookManager.h"
       
    27 #include "SyncContactICCEntry.h"
       
    28 #include "phbksynclog.h"
       
    29 #include "phbksyncsvr.h"
       
    30 #include "SyncEngineSession.h"
       
    31 #include "SyncEngineServer.h"
       
    32 #include "phbksyncsess.h"
       
    33 #include "SyncContactsWithICC.h"
       
    34 
       
    35 
       
    36 /**
       
    37  *  Number of retries to read the ICC in an ICC multiple read operation.
       
    38  */
       
    39 const TInt KMaxICCReadRetryCnt = 1;
       
    40 
       
    41 
       
    42 /**
       
    43  *	Delay for retry (will be multiplied by an increasing factor).
       
    44  */
       
    45 const TInt KReadRetryDelayBase = 100000;
       
    46 
       
    47 
       
    48 
       
    49 /**
       
    50  *  Static factory method used to create a CSyncContactsWithICC object.
       
    51  *
       
    52  *  @param aSession           Reference to the engine session.
       
    53  *  @param aPhonebookManager  Reference to the Phonebook Manager which stores
       
    54  *                            all the phonebook parameters.
       
    55  *  @param aDb                Reference to the database.
       
    56  *  @param aPhone             Handle to the phone object.
       
    57  *  @param aPhonebookUid      Phonebook UID for the contact to be deleted from.
       
    58  *  @param aClientMessage     Handle to the engine message request.
       
    59  */
       
    60 CSyncContactsWithICC* CSyncContactsWithICC::NewL(CSyncEngineSession& aSession,
       
    61 												 CPhoneBookManager& aPhoneBookManager,
       
    62 												 CContactDatabase& aDb,
       
    63 												 RMobilePhone& aPhone,
       
    64 												 TUid aPhonebookUid,
       
    65 												 const RMessage2& aClientMessage)
       
    66 	{
       
    67 	CSyncContactsWithICC*  self = new(ELeave) CSyncContactsWithICC(aSession,
       
    68 																   aPhoneBookManager,
       
    69 																   aDb,
       
    70 																   aPhone,
       
    71 																   aPhonebookUid,
       
    72 																   aClientMessage);
       
    73 	CleanupStack::PushL(self);
       
    74 	self->ConstructL();
       
    75 	CleanupStack::Pop(self);
       
    76 
       
    77 	return self;
       
    78 	} // CSyncContactsWithICC::NewL
       
    79 
       
    80 
       
    81 /**
       
    82  *  Standard constructor.
       
    83  *
       
    84  *  @param aSession           Reference to the engine session.
       
    85  *  @param aPhonebookManager  Reference to the Phonebook Manager which stores
       
    86  *                            all the phonebook parameters.
       
    87  *  @param aDb                Reference to the database.
       
    88  *  @param aPhone             Handle to the phone object.
       
    89  *  @param aPhonebookUid      Phonebook UID for the contact to be deleted from.
       
    90  *  @param aClientMessage     Handle to the engine message request.
       
    91  */
       
    92 CSyncContactsWithICC::CSyncContactsWithICC(CSyncEngineSession& aSession,
       
    93 										   CPhoneBookManager& aPhonebookManager,
       
    94 										   CContactDatabase& aDb,
       
    95 										   RMobilePhone& aPhone,
       
    96 										   TUid aPhonebookUid,
       
    97 										   const RMessage2& aClientMessage)
       
    98   : CActive(EPriorityNormal),
       
    99 	iSession(aSession),
       
   100 	iPhonebookManager(aPhonebookManager),
       
   101 	iDb(aDb),
       
   102 	iPhone(aPhone),
       
   103 	iPhonebookUid(aPhonebookUid),
       
   104 	iClientMessage(aClientMessage),
       
   105 	iState(ESyncContactsWithICCStateIdle),
       
   106 	iPhonebookDataPtr(NULL,0),
       
   107 	iNumOfEntries(1),
       
   108 	iSlotNum(1)
       
   109 	{
       
   110 	// NOP
       
   111 	} // CSyncContactsWithICC::CSyncContactsWithICC
       
   112 
       
   113 
       
   114 /**
       
   115  *  Standard destructor. This will cancel any pending active requests.
       
   116  */
       
   117 CSyncContactsWithICC::~CSyncContactsWithICC()
       
   118 	{
       
   119 	LOGACTIVE1(_L8("~CSyncContactsWithICC()"));
       
   120 
       
   121 	Cancel();
       
   122 
       
   123 	delete iPhonebookData;
       
   124 	iUnconfirmedEntries.Close();
       
   125 	iTimer.Close();
       
   126 	} // CSyncContactsWithICC::~CSyncContactsWithICC
       
   127 
       
   128 
       
   129 /**
       
   130  *  Second phase constructor.
       
   131  */
       
   132 void CSyncContactsWithICC::ConstructL()
       
   133 	{
       
   134 	LOGACTIVE1(_L8("CSyncContactsWithICC::ConstructL()"));
       
   135 
       
   136 	//
       
   137 	// Create the phonebook data buffer.
       
   138 	//
       
   139 	iPhonebookData = HBufC8::NewL(KPBDataClientHeap);
       
   140 	iPhonebookDataPtr.Set(const_cast<unsigned char*>(iPhonebookData->Ptr()), 0, KPBDataClientHeap);
       
   141 
       
   142 	//
       
   143 	// Obtain a few bits of info now to save time later...
       
   144 	//
       
   145 	User::LeaveIfError(iPhonebookManager.GetPhoneBookInfo(iPhonebookUid, iPhBkInfo));
       
   146 	User::LeaveIfError(iPhonebookManager.GetPhoneBookStore(iPhonebookUid, iPhone, iPhonebookStore));
       
   147 
       
   148 	//
       
   149 	// Create a timer for use later if needed...
       
   150 	//
       
   151 	iTimer.CreateLocal();
       
   152 
       
   153 	CActiveScheduler::Add(this);
       
   154 	} // CSyncContactsWithICC::ConstructL
       
   155 
       
   156 
       
   157 /**
       
   158  *  Begin synchronising the ICC phonebook into the Contacts Database. This
       
   159  *  function begins the process be ensuring the Look-Up Table is upto date
       
   160  *  with the information from the Contacts DB. Any contact entires that are
       
   161  *  stored outside the slot range of the ICC (e.g. entries from previous ICCs)
       
   162  *  are removed.
       
   163  */
       
   164 void CSyncContactsWithICC::SyncContactsWithICCL()
       
   165 	{
       
   166 	LOGACTIVE1(_L8("CSyncContactsWithICC::SyncContactsWithICCL()"));
       
   167 
       
   168 	//
       
   169 	// Check that we are not in use!
       
   170 	//
       
   171 	if (iState != ESyncContactsWithICCStateIdle)
       
   172 		{
       
   173 		PhBkSyncPanic(EPhBkSyncPanicDoMultipleReadError);
       
   174 		}
       
   175 
       
   176 	//
       
   177 	// Fetch all current database entries into the Look-Up Table. Also we
       
   178 	// need to delete all entires outside the size of the phonebook. Start by
       
   179 	// getting the size of the phonebook and clearing the current table data.
       
   180 	//
       
   181 	TInt  phonebookSize;
       
   182 	
       
   183 	User::LeaveIfError(iPhonebookManager.GetLookUpTableSize(iPhonebookUid,
       
   184 															phonebookSize));
       
   185 	User::LeaveIfError(iPhonebookManager.ClearLookUpTable(iPhonebookUid));
       
   186 
       
   187 	//
       
   188 	// Get the Group ID to search for entries. If no ID exists then the
       
   189 	// database does not contain any entries.
       
   190 	//
       
   191 	TContactItemId  groupId;
       
   192 	
       
   193 	User::LeaveIfError(iPhonebookManager.GetGroupId(iPhonebookUid, groupId));
       
   194 
       
   195  	
       
   196  	//
       
   197  	// Populate the lookup table with entries from the contacts database...
       
   198  	//
       
   199  	if (groupId != KNullContactId  &&  groupId != KGoldenTemplateId)
       
   200 		{
       
   201  		CContactItem*  group = iDb.ReadContactLC(groupId);
       
   202  		const CContactIdArray*  members = static_cast<CContactGroup*>(group)->ItemsContained();
       
   203  		const TInt  count = members->Count();
       
   204 
       
   205 		TContactTextDefItem  iccSlotFieldType(KUidContactFieldICCSlot);
       
   206 		CContactTextDef*  iccSlotFieldTextDef = CContactTextDef::NewLC();
       
   207 		iccSlotFieldTextDef->AppendL(iccSlotFieldType);
       
   208 
       
   209 		for (TInt item = 0;  item < count;  item++)
       
   210 			{
       
   211 			//
       
   212 			// Read the item from the database and add to the Look-Up Table.
       
   213 			// The state is unconfirmed until the synchronisation is complete.
       
   214 			//
       
   215 			TBuf<KTemplateNumberLength>  iccSlotField;
       
   216 
       
   217 			iDb.ReadContactTextDefL((*members)[item], iccSlotField,
       
   218 									iccSlotFieldTextDef);
       
   219 			TLex  input(iccSlotField);
       
   220 			TInt  slotNum = 0;
       
   221 			input.Val(slotNum);
       
   222 
       
   223 			//
       
   224 			// Delete entries that are in slots exceeding the ICC slot range,
       
   225 			// otherwise add them to the Look Up Table.
       
   226 			//
       
   227 			if (slotNum > phonebookSize)
       
   228 				{
       
   229 				iDb.DeleteContactL((*members)[item]);
       
   230 				}
       
   231 			else
       
   232 				{
       
   233 				User::LeaveIfError(iPhonebookManager.UpdateEntryInTable(iPhonebookUid,
       
   234 																		slotNum,
       
   235 																		(*members)[item],
       
   236 																		ESlotUnconfirmed));
       
   237 				}
       
   238 			}
       
   239 
       
   240 		CleanupStack::PopAndDestroy(2, group);
       
   241  		}
       
   242 
       
   243 	//
       
   244 	// Now begin the process of reading entries and writting them to the database.
       
   245 	//
       
   246 	ReadICCEntries();
       
   247 	} // CSyncContactsWithICC::SyncContactsWithICCL
       
   248 
       
   249 
       
   250 /** 
       
   251  *  Issues a read of one or more ICC entries.
       
   252  */
       
   253 void CSyncContactsWithICC::ReadICCEntries()
       
   254 	{
       
   255 	LOGACTIVE1(_L8("CSyncContactsWithICC::ReadICCEntries()"));
       
   256 
       
   257 	//
       
   258 	// Now issue the ICC read and set the object Active...
       
   259 	//
       
   260 	iPhonebookStore.Read(iStatus, iSlotNum, 1, iPhonebookDataPtr);
       
   261 	iState = ESyncContactsWithICCStateWaitForRead;
       
   262 	iDbAccessRetryCount=0;
       
   263 	iICCReadRetryCount=0;
       
   264 	SetActive();
       
   265 
       
   266 	LOGACTIVETIMESTAMP();
       
   267 	} // CSyncContactsWithICC::ReadICCEntries
       
   268 
       
   269 
       
   270 /** 
       
   271  *  Standard Active Object RunL() method to process the various sync requests.
       
   272  */
       
   273 void CSyncContactsWithICC::RunL()
       
   274 	{
       
   275 	LOGACTIVE2(_L8("CSyncContactsWithICC::RunL() iStatus=%d)"),
       
   276 			   iStatus.Int());
       
   277 
       
   278 	switch (iState)
       
   279 		{
       
   280 		case ESyncContactsWithICCStateWaitForRead:
       
   281 			{
       
   282 			//
       
   283 			// If the request was completed, cancelled or no more entries were found...
       
   284 			//
       
   285 			if (iStatus.Int() == KErrNone  ||
       
   286 				iStatus.Int() == KErrCancel  || 
       
   287 			    iStatus.Int() == KErrNotFound)
       
   288 				{
       
   289 				TInt  ret(iStatus.Int());
       
   290 
       
   291 				iICCReadRetryCount=0;
       
   292 
       
   293 				//
       
   294 				// Now decode received phonebook data and store it in Contacts DB...
       
   295 				//
       
   296 				TRAPD(decodeErr, DecodeICCAndStoreToDbL(iSlotNum, iReceivedEntries));
       
   297 				if (decodeErr != KErrNone)
       
   298 					{
       
   299 					iSession.Server().RollbackIccTransaction();
       
   300 
       
   301 					if (iDbAccessRetryCount < KMaxDbAccessRetryCount  &&
       
   302 						(decodeErr == KErrInUse  ||  decodeErr == KErrLocked))
       
   303 						{					
       
   304 						iDbAccessRetryCount++;			
       
   305 						LOGACTIVE2(_L8("iDbAccessErrorCount is %d"),iDbAccessRetryCount);
       
   306 
       
   307 						iTimer.After(iStatus, KReadRetryDelayBase*iDbAccessRetryCount);//increase the delay each time
       
   308 						SetActive();
       
   309 						LOGACTIVETIMESTAMP();
       
   310 						}
       
   311 					else
       
   312 						{
       
   313 						iSession.Server().CompleteDoSync(decodeErr);
       
   314 						}
       
   315 						
       
   316 					return;
       
   317 					}
       
   318 
       
   319 				iDbAccessRetryCount = 0; // reset the DB retry counter
       
   320 
       
   321 				//
       
   322 				// Have we finished reading yet?
       
   323 				//
       
   324 				if ((iPhBkInfo.iUsedEntries < 0  ||  iReceivedEntries < iPhBkInfo.iUsedEntries)  &&
       
   325 				    iSlotNum < iPhBkInfo.iTotalEntries)
       
   326 					{
       
   327 					//
       
   328 					// Increment the slot number and read some more...
       
   329 					//
       
   330 					iSlotNum++;
       
   331 					ReadICCEntries();
       
   332 					}
       
   333 				else
       
   334 					{
       
   335 					//
       
   336 					// All entries have been read. It is okay to not find an
       
   337 					// entry in the case where the TSY could not tell you how
       
   338 					// many entries were used. If there was an error return now.
       
   339 					//
       
   340 					if (ret != KErrNone  &&  ret != KErrNotFound)
       
   341 						{
       
   342 						iState = ESyncContactsWithICCStateIdle;
       
   343 						iSession.Server().CompleteDoSync(ret);
       
   344 						return;
       
   345 						}
       
   346 
       
   347 					//
       
   348 					// Request the list of unconfirmed entries to remove...
       
   349 					//
       
   350 					TInt  result;
       
   351 					
       
   352 					result = iPhonebookManager.GetMatchingEntries(iPhonebookUid,
       
   353 																  ESlotUnconfirmed,
       
   354 																  iUnconfirmedEntries);
       
   355 					if (result != KErrNone)
       
   356 						{
       
   357 						iSession.Server().CompleteDoSync(result);
       
   358 						return;
       
   359 						}
       
   360 
       
   361 					//
       
   362 					// Yield and continue processing in the next RunL call.
       
   363 					//
       
   364 					iState = ESyncContactsWithICCStateRemoveUnconfirmedEntries;
       
   365 					YieldToOtherActiveObjects();
       
   366 					}
       
   367 				}
       
   368 			else
       
   369 				{
       
   370 				if (iICCReadRetryCount < KMaxICCReadRetryCnt)
       
   371 					{					
       
   372 					iICCReadRetryCount++;
       
   373 					iPhonebookDataPtr.Zero();	
       
   374 					iPhonebookStore.Read(iStatus, iSlotNum, 1, iPhonebookDataPtr);
       
   375 					SetActive();
       
   376 					LOGACTIVETIMESTAMP();
       
   377 					}
       
   378 				else
       
   379 					{
       
   380 					iSession.Server().CompleteDoSync(iStatus.Int());
       
   381 					return;
       
   382 					}
       
   383 				}
       
   384 			}
       
   385 			break;
       
   386 
       
   387 		case ESyncContactsWithICCStateRemoveUnconfirmedEntries:
       
   388 			{
       
   389 			//
       
   390 			// If we have unconfirmed entries to remove, then delete one of
       
   391 			// them before yielding to the scheduler (so we don't spend too
       
   392 			// much time in the RunL() in one go). Otherwise we have finished.
       
   393 			//
       
   394 			if (iUnconfirmedEntries.Count() > 0)
       
   395 				{
       
   396 				//
       
   397 				// Get the contact ID for the entry we are going to delete...
       
   398 				//
       
   399 				TContactItemId  contactId;
       
   400 				TInt  result;
       
   401 				
       
   402 				result = iPhonebookManager.GetContactIdFromSlotNum(iPhonebookUid,
       
   403 																   iUnconfirmedEntries[0],
       
   404 																   contactId);
       
   405 				if (result != KErrNone)
       
   406 					{
       
   407 					iSession.Server().CompleteDoSync(result);
       
   408 					return;
       
   409 					}
       
   410 
       
   411 				//
       
   412 				// Delete the entry...
       
   413 				//				
       
   414 				TRAP(result, iDb.DeleteContactL(contactId));
       
   415 				if (result != KErrNone)
       
   416 					{
       
   417 					iSession.Server().CompleteDoSync(result);
       
   418 					return;
       
   419 					}
       
   420 
       
   421 				//
       
   422 				// Reset the Look-Up Table entry...
       
   423 				//
       
   424 				result = iPhonebookManager.UpdateEntryInTable(iPhonebookUid,
       
   425 															  iUnconfirmedEntries[0],
       
   426 															  KNullContactId,
       
   427 															  ESlotEmpty);
       
   428 				if (result != KErrNone)
       
   429 					{
       
   430 					iSession.Server().CompleteDoSync(result);
       
   431 					return;
       
   432 					}
       
   433 				
       
   434 				//
       
   435 				// Remove this entry from the list and yield...
       
   436 				//
       
   437 				iUnconfirmedEntries.Remove(0);
       
   438 				YieldToOtherActiveObjects();
       
   439 				}
       
   440 			else
       
   441 				{
       
   442 				//
       
   443 				// Compress the database if needed and we are finished!
       
   444 				//
       
   445 				if (iDb.CompressRequired())
       
   446 					{
       
   447 					TRAP_IGNORE(iDb.CompactL());
       
   448 					}
       
   449 
       
   450 				iState = ESyncContactsWithICCStateIdle;
       
   451 
       
   452 				iSession.Server().CompleteDoSync(KErrNone);
       
   453 				}
       
   454 			}
       
   455 			break;
       
   456 
       
   457 		case ESyncContactsWithICCStateWaitForCancel:
       
   458 			{
       
   459 			iState = ESyncContactsWithICCStateIdle;
       
   460 			iSession.Server().CompleteDoSync(iStatus.Int());
       
   461 			}
       
   462 			break;
       
   463 
       
   464 		default:
       
   465 			{
       
   466 			PhBkSyncPanic(EPhBkSyncPanicDoMultipleReadError);
       
   467 			}
       
   468 			break;
       
   469 		}
       
   470 	} // CSyncContactsWithICC::RunL
       
   471 
       
   472 
       
   473 /**
       
   474  *  Simple function that causes the Active Object to yield to the scheduler
       
   475  *  and let any other Active Objects (such as the engine) run if they want.
       
   476  */
       
   477 void CSyncContactsWithICC::YieldToOtherActiveObjects()
       
   478 	{
       
   479 	LOGACTIVE1(_L8("CSyncContactsWithICC::YieldToOtherActiveObjects()"));
       
   480 
       
   481 	//
       
   482 	// Post a dummy request...
       
   483 	//
       
   484 	iStatus = KRequestPending;
       
   485 	SetActive();
       
   486 	LOGACTIVETIMESTAMP();
       
   487 
       
   488 	//
       
   489 	// Now complete the dummy request...
       
   490 	//
       
   491 	TRequestStatus*  reqStatusPtr = &iStatus;
       
   492 
       
   493 	User::RequestComplete(reqStatusPtr, KErrNone);
       
   494 	} // CSyncContactsWithICC::YieldToOtherActiveObjects
       
   495 
       
   496 
       
   497 /**
       
   498  *  Decode the phonebook entries supplied in iPhoneData. The entries are
       
   499  *  converted from TLV (Tag-Length-Value) format into the phonebook server internal
       
   500  *  (CSyncContactICCEntry) format and then written to the Contacts Database.
       
   501  *  Once they are written to the DB, the server's look-up table is updated
       
   502  *  accordingly.
       
   503  *
       
   504  *  @param aIndex            Returns the slot number of the last decoded
       
   505  *                           phonebook entry.
       
   506  *  @param aReceivedEntries  Returns the number of the received entries.
       
   507  */
       
   508 void CSyncContactsWithICC::DecodeICCAndStoreToDbL(TInt& aIndex,
       
   509 												  TInt& aReceivedEntries)
       
   510 	{
       
   511 	LOGACTIVE1(_L8("CSyncContactsWithICC::DecodeICCAndStoreToDbL()"));
       
   512 
       
   513 	TBuf16<KPBDataClientBuf>  buffer;
       
   514 	TPtrC16  bufPtr(buffer);
       
   515 
       
   516 	TUint8  tagValue(0);
       
   517 	TInt  entryCount(0);
       
   518 	CPhoneBookBuffer::TPhBkTagType  dataType;
       
   519 
       
   520 	TBool  isAdditionalNumber(EFalse); // Used to indicate beginning of an Additional Number 
       
   521 	CSyncContactICCEntry::TSyncAdditionalNumber  additionalNumber;
       
   522 
       
   523 	//
       
   524 	// Allocate an ICC Entry...
       
   525 	//
       
   526 	CSyncContactICCEntry*  iccEntry = CSyncContactICCEntry::NewL();
       
   527 	CleanupStack::PushL(iccEntry);
       
   528 
       
   529 	//
       
   530 	// Create a CPhoneBookBuffer ready to decode the entries...
       
   531 	//
       
   532 	CPhoneBookBuffer*  pbBuffer = new(ELeave) CPhoneBookBuffer();
       
   533 	CleanupStack::PushL(pbBuffer);
       
   534 	pbBuffer->Set(&iPhonebookDataPtr);
       
   535 
       
   536 	//
       
   537 	// Now start decoding the phonebook data received in TLV format...
       
   538 	//
       
   539 	pbBuffer->StartRead();
       
   540 
       
   541 	while (pbBuffer->GetTagAndType(tagValue, dataType) == KErrNone)
       
   542 		{
       
   543 		switch (tagValue)
       
   544 			{
       
   545 			case RMobilePhoneBookStore::ETagPBAdnIndex:
       
   546 				{
       
   547 				entryCount++;     // Don't increment this until we find the index
       
   548 								  // So that we wait for whole entry to be received
       
   549 				TUint16  index;
       
   550 				pbBuffer->GetValue(index);			
       
   551 				iccEntry->iSlotNum = (TInt) index;
       
   552 				aIndex = iccEntry->iSlotNum;
       
   553 				}
       
   554 				break;
       
   555 
       
   556 			case RMobilePhoneBookStore::ETagPBTonNpi:
       
   557 				{
       
   558 				TUint8  tonNpi;
       
   559 
       
   560 				pbBuffer->GetValue(tonNpi);			
       
   561 				if (isAdditionalNumber)
       
   562 					{
       
   563 					additionalNumber.iTON = ConvertTypeOfNumber(tonNpi); // TON associated with additional number
       
   564 					
       
   565 					// We have rearched to the end of one additional number. So, 
       
   566 				    // we add the complete additionNumber into the list and set 
       
   567 					// the flag as EFalse. Note we will get a ETagPBAnrStart for
       
   568 					// each additional number.
       
   569 					iccEntry->iNumberList->AppendL(additionalNumber);
       
   570 					isAdditionalNumber = EFalse;
       
   571 					}
       
   572 				else
       
   573 					{
       
   574 					// TON associated with first (default) number
       
   575 					iccEntry->iTON = ConvertTypeOfNumber(tonNpi);
       
   576 					}
       
   577 				}
       
   578 				break;
       
   579 
       
   580 			case RMobilePhoneBookStore::ETagPBText:
       
   581 				{
       
   582 				pbBuffer->GetValue(bufPtr);
       
   583 				if (isAdditionalNumber)
       
   584 					{
       
   585 					// For additional number bufPtr contains number alpha string
       
   586 					additionalNumber.iNumberString.Copy(bufPtr);
       
   587 					}
       
   588 				else
       
   589 					{
       
   590 					iccEntry->iName.Copy(bufPtr);
       
   591 					}
       
   592 				}
       
   593 				break;
       
   594 
       
   595 			case RMobilePhoneBookStore::ETagPBSecondName:
       
   596 				{
       
   597 				pbBuffer->GetValue(bufPtr);			
       
   598 				iccEntry->iSecondName.Copy(bufPtr);
       
   599 				}
       
   600 				break;
       
   601 
       
   602 			case RMobilePhoneBookStore::ETagPBNumber:
       
   603 				{
       
   604 				pbBuffer->GetValue(bufPtr);	
       
   605 				if (isAdditionalNumber)
       
   606 					{
       
   607 					additionalNumber.iNumber.Copy(bufPtr);
       
   608 					}
       
   609 				else
       
   610 					{
       
   611 					// First number so this will be used as default number
       
   612 					iccEntry->iNumber.Append(bufPtr);
       
   613 					}
       
   614 				}
       
   615 				break;
       
   616 
       
   617 			case RMobilePhoneBookStore::ETagPBAnrStart:
       
   618 				{
       
   619 				// This tag should precede every additional number entry
       
   620 				isAdditionalNumber = ETrue;
       
   621 				}
       
   622 				break;
       
   623 
       
   624 			case RMobilePhoneBookStore::ETagPBGroupName:
       
   625 				{
       
   626 				pbBuffer->GetValue(bufPtr);	
       
   627 				iccEntry->iGroupList->AppendL(bufPtr);
       
   628 				}
       
   629 				break;
       
   630 
       
   631 			case RMobilePhoneBookStore::ETagPBEmailAddress:
       
   632 				{
       
   633 				pbBuffer->GetValue(bufPtr);
       
   634 				iccEntry->iEmailList->AppendL(bufPtr);
       
   635 				}
       
   636 				break;
       
   637 
       
   638 			case RMobilePhoneBookStore::ETagPBHiddenInfo:
       
   639 				{
       
   640 	 			TUint8  hidden;
       
   641 				
       
   642 				pbBuffer->GetValue(hidden);
       
   643 				if (hidden != 0)
       
   644 					{
       
   645 					iccEntry->iIsHidden = ETrue;
       
   646 					}
       
   647 				}
       
   648 				break;
       
   649 
       
   650 			case RMobilePhoneBookStore::ETagPBNewEntry:
       
   651 				{
       
   652 				//
       
   653 				// This signals the end of the entry and is a special case
       
   654 				// which will be handled below.
       
   655 				//
       
   656 				}
       
   657 				break;
       
   658 
       
   659 			default:
       
   660 				{
       
   661 				//
       
   662 				// An unsupported field type - just skip this value
       
   663 				//
       
   664 				pbBuffer->SkipValue(dataType);
       
   665 				}
       
   666 				break;
       
   667 			}
       
   668 
       
   669 		//
       
   670 		// Has the whole entry been extracted?
       
   671 		//
       
   672 		if ((tagValue == RMobilePhoneBookStore::ETagPBNewEntry  &&  entryCount > 0) ||
       
   673 			(pbBuffer->RemainingReadLength() == 0  &&  entryCount > 0))
       
   674 			{
       
   675 			iccEntry->iPhonebookUid = iPhonebookUid;
       
   676 
       
   677 #ifdef _DEBUG
       
   678 			iccEntry->LogSyncContactICCEntry();
       
   679 #endif
       
   680 			
       
   681 			//
       
   682 			// Write the entry to the Contacts Database...
       
   683 			//
       
   684 			TContactItemId id(KNullContactId);
       
   685 			TPhonebookSlotState slotState(ESlotUsedAvailable);
       
   686 			if (iccEntry->iIsHidden)
       
   687 				// Hidden entry so ignore all fields for that entry, since they will not 
       
   688 				// be stored in Contacts database
       
   689 				{
       
   690 				slotState = ESlotHiddenNotAvailable;
       
   691 				// remove any existing entry for this slot from database
       
   692 				TInt  result = iPhonebookManager.GetContactIdFromSlotNum(iPhonebookUid,
       
   693 																		  iccEntry->iSlotNum,
       
   694 																		  id);
       
   695 				if (result == KErrNone)
       
   696 					{
       
   697 					iDb.DeleteContactL(id);
       
   698 					id = KNullContactId;
       
   699 					// Populate the phonebook look-up table 
       
   700 					User::LeaveIfError(iPhonebookManager.UpdateEntryInTable(iPhonebookUid,
       
   701 																			iccEntry->iSlotNum,
       
   702 																			id, slotState));
       
   703 					}
       
   704 				}
       
   705 			else // Not hidden entry or it used to be hidden but its not anymore 
       
   706 				{
       
   707 				// So add this entry to Contacts database 
       
   708 				
       
   709 				id = iSession.Server().WriteICCContactToDBL(*iccEntry);
       
   710 				}
       
   711 
       
   712 			// ICC entry successfully written Contacts DB, so update look-up table
       
   713 			if((id!=KNullContactId) || (iccEntry->iIsHidden)) 
       
   714 				{
       
   715 				// Populate the phonebook look-up table 
       
   716 				User::LeaveIfError(iPhonebookManager.UpdateEntryInTable(iPhonebookUid,
       
   717 																		iccEntry->iSlotNum,
       
   718 																		id, slotState));
       
   719 				}
       
   720 
       
   721 			//
       
   722 			// Loop again...
       
   723 			//
       
   724 			iccEntry->Reset();
       
   725 			aReceivedEntries++;
       
   726 			} 
       
   727 		}
       
   728 
       
   729 	iPhonebookDataPtr.Zero();
       
   730 
       
   731 	CleanupStack::PopAndDestroy(2, iccEntry);
       
   732 	} // CSyncContactsWithICC::DecodeICCAndStoreToDbL
       
   733 
       
   734 
       
   735 /**
       
   736  *  Converts an ETSI Type-Of-Number value to a RMobilePhone::TMobileTON.
       
   737  *
       
   738  *  @param aValue  An ETSI Type-Of-Number field.
       
   739  *
       
   740  *  @return The equivalent RMobilePhone::TMobileTON value.
       
   741  */
       
   742 RMobilePhone::TMobileTON CSyncContactsWithICC::ConvertTypeOfNumber(TUint8 aValue) const
       
   743 	{
       
   744 	//
       
   745 	// Mask off NPI and move TON to least-sig byte...
       
   746 	//
       
   747 	TUint8  aTon = (aValue & KEtsiTonPosition) >> 4;
       
   748 
       
   749 	//
       
   750 	// The below 'magic numbers' come from the ETSI 03.40
       
   751 	// specification for Address Fields (section 9.1.2.5)
       
   752 	//
       
   753 	RMobilePhone::TMobileTON  result;
       
   754 
       
   755 	switch(aTon)
       
   756 		{
       
   757 		case 0:
       
   758 			{
       
   759 			result = RMobilePhone::EUnknownNumber;
       
   760 			}
       
   761 			break;
       
   762 
       
   763 		case 1:		
       
   764 			{
       
   765 			result = RMobilePhone::EInternationalNumber;
       
   766 			}
       
   767 			break;
       
   768 
       
   769 		case 2:
       
   770 			{
       
   771 			result = RMobilePhone::ENationalNumber;
       
   772 			}
       
   773 			break;
       
   774 
       
   775 		case 3:
       
   776 			{
       
   777 			result = RMobilePhone::ENetworkSpecificNumber;
       
   778 			}
       
   779 			break;
       
   780 
       
   781 		case 4:
       
   782 			{
       
   783 			result = RMobilePhone::ESubscriberNumber;
       
   784 			}
       
   785 			break;
       
   786 
       
   787 		default:
       
   788 			{
       
   789 			result = RMobilePhone::EUnknownNumber;
       
   790 			}
       
   791 			break;
       
   792 		}
       
   793 		
       
   794 	return result;
       
   795 	} // CSyncContactsWithICC::ConvertTypeOfNumber
       
   796 
       
   797 
       
   798 /** 
       
   799  *  Standard Active Object DoCancel method called when the objects Cancel()
       
   800  *  method is called.
       
   801  */
       
   802 void CSyncContactsWithICC::DoCancel()
       
   803 	{
       
   804 	if (iState == ESyncContactsWithICCStateWaitForRead)
       
   805 		{
       
   806 		iPhonebookStore.CancelAsyncRequest(EMobilePhoneBookStoreRead);
       
   807 		iState = ESyncContactsWithICCStateWaitForCancel;
       
   808 		}
       
   809 	} // CSyncContactsWithICC::DoCancel
       
   810 
       
   811 
       
   812 /**
       
   813  *  Standard Active Object RunError method called when the objects RunL()
       
   814  *  method leaves.
       
   815  *
       
   816  *  Hopefully this method should never be called.
       
   817  *
       
   818  *  @param aError  Leave code from the RunL().
       
   819  *
       
   820  *  @return  KErrNone is returned although the server will panic first.
       
   821  */
       
   822 TInt CSyncContactsWithICC::RunError(TInt aError)
       
   823 	{
       
   824 #ifdef _DEBUG
       
   825 	LOGACTIVE2(_L8("CSyncContactsWithICC::RunError(%d)"), aError);
       
   826 #else
       
   827 	(void) aError;
       
   828 #endif
       
   829 
       
   830 	PhBkSyncPanic(EPhBkSyncPanicUnexpectedLeave);
       
   831 
       
   832 	return KErrNone;	
       
   833 	} // CSyncContactsWithICC::RunError