|
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 used to write a |
|
15 // Contact to the ICC. |
|
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 "WriteContactToICC.h" |
|
34 |
|
35 |
|
36 /** |
|
37 * Static factory method used to create a CWriteContactToICC object. |
|
38 * |
|
39 * @param aBufferSize Size of ICC Entry buffer passed in the request. |
|
40 * @param aSession Handle to the engine session. |
|
41 * @param aPhonebookManager Pointer to the Phonebook Manager which stores all |
|
42 * the phonebook parameters. |
|
43 * @param aPhone Handle to the phone object. |
|
44 * @param aPhonebookUid Phonebook UID for the contact to be deleted from. |
|
45 * @param aClientMessage Handle to the engine message request. |
|
46 * |
|
47 * @return Pointer to the created CWriteContactToICC object, or NULL. |
|
48 */ |
|
49 CWriteContactToICC* CWriteContactToICC::NewL(CSyncEngineSession& aSession, |
|
50 TInt aBufferSize, |
|
51 CPhoneBookManager& aPhonebookManager, |
|
52 RMobilePhone& aPhone, |
|
53 TUid aPhonebookUid, |
|
54 const RMessage2& aClientMessage) |
|
55 { |
|
56 CWriteContactToICC* self = new(ELeave) CWriteContactToICC(aSession, |
|
57 aPhonebookManager, |
|
58 aPhone, |
|
59 aPhonebookUid, |
|
60 aClientMessage); |
|
61 CleanupStack::PushL(self); |
|
62 self->ConstructL(aBufferSize); |
|
63 CleanupStack::Pop(self); |
|
64 |
|
65 return self; |
|
66 } // CWriteContactToICC::NewL |
|
67 |
|
68 |
|
69 /** |
|
70 * Standard constructor. |
|
71 * |
|
72 * @param aSession Handle to the engine session. |
|
73 * @param aPhonebookManager Pointer to the Phonebook Manager which stores all |
|
74 * the phonebook parameters. |
|
75 * @param aPhone Handle to the phone object. |
|
76 * @param aPhonebookUid Phonebook UID for the contact to be deleted from. |
|
77 * @param aClientMessage Handle to the engine message request. |
|
78 */ |
|
79 CWriteContactToICC::CWriteContactToICC(CSyncEngineSession& aSession, |
|
80 CPhoneBookManager& aPhonebookManager, |
|
81 RMobilePhone& aPhone, |
|
82 TUid aPhonebookUid, |
|
83 const RMessage2& aClientMessage) |
|
84 : CActive(EPriorityNormal), |
|
85 iSession(aSession), |
|
86 iPhonebookManager(aPhonebookManager), |
|
87 iPhone(aPhone), |
|
88 iPhonebookUid(aPhonebookUid), |
|
89 iClientMessage(aClientMessage), |
|
90 iIccEntryBuf(NULL), |
|
91 iIccEntryPtr(NULL, 0), |
|
92 iPhonebookDataPtr(NULL,0), |
|
93 iIccWriteState(EPBSyncIccWriteIdle), |
|
94 iIsUsedSlot(EFalse) |
|
95 { |
|
96 // NOP |
|
97 } // CWriteContactToICC::CWriteContactToICC |
|
98 |
|
99 |
|
100 /** |
|
101 * Standard destructor. This will cancel any pending active requests and |
|
102 * free any allocated memory. |
|
103 */ |
|
104 CWriteContactToICC::~CWriteContactToICC() |
|
105 { |
|
106 LOGACTIVE1(_L8("~CWriteContactToICC()")); |
|
107 |
|
108 Cancel(); |
|
109 |
|
110 delete iPhonebookBuffer; |
|
111 delete iIccEntry; |
|
112 delete iIccEntryBuf; |
|
113 delete iPhonebookData; |
|
114 } // CWriteContactToICC::~CWriteContactToICC |
|
115 |
|
116 |
|
117 /** |
|
118 * Second phase constructor. |
|
119 */ |
|
120 void CWriteContactToICC::ConstructL(TInt aBufferSize) |
|
121 { |
|
122 // |
|
123 // Create the phonebook buffer for writing to the ICC... |
|
124 // |
|
125 iPhonebookBuffer = new(ELeave) CPhoneBookBuffer(); |
|
126 |
|
127 // |
|
128 // Create the ICC Entry and phonebook buffer... |
|
129 // |
|
130 iIccEntry = CSyncContactICCEntry::NewL(); |
|
131 |
|
132 iIccEntryBuf = CBufFlat::NewL(1); |
|
133 iIccEntryBuf->ResizeL(aBufferSize); |
|
134 iIccEntryPtr.Set(iIccEntryBuf->Ptr(0)); |
|
135 iPhonebookData = HBufC8::NewL(KPBDataClientHeap); // Create client buffer to store write data |
|
136 iPhonebookDataPtr.Set(const_cast<unsigned char*>(iPhonebookData->Ptr()), 0, KPBDataClientHeap); |
|
137 iPhonebookBuffer->Set(&iPhonebookDataPtr); // Set iPBBuffer to point to the phonebook data buffer |
|
138 |
|
139 // |
|
140 // Get the PhBkStore & PhBkInfo for later use... |
|
141 // |
|
142 User::LeaveIfError(iPhonebookManager.GetPhoneBookStore(iPhonebookUid, iPhone, iPhonebookStore)); |
|
143 User::LeaveIfError(iPhonebookManager.GetPhoneBookInfo(iPhonebookUid, iPhBkInfoV5)); |
|
144 |
|
145 // |
|
146 // Read the ICC Entry streamed buffer... |
|
147 // |
|
148 iClientMessage.ReadL(3, iIccEntryPtr); |
|
149 |
|
150 CActiveScheduler::Add(this); |
|
151 } // CWriteContactToICC::ConstructL |
|
152 |
|
153 |
|
154 /** |
|
155 * Method to write to ICC after checking slot is empty and memory is available. |
|
156 */ |
|
157 void CWriteContactToICC::DoIccWriteL() |
|
158 { |
|
159 LOGACTIVE1(_L8("CWriteContactToICC::DoIccWriteL()")); |
|
160 |
|
161 // |
|
162 // Check that we are not in use! |
|
163 // |
|
164 if (iIccWriteState != EPBSyncIccWriteIdle) |
|
165 { |
|
166 PhBkSyncPanic(EPhBkSyncPanicDoIccWriteError); |
|
167 } |
|
168 |
|
169 // |
|
170 // Restore streamed contact data... |
|
171 // |
|
172 iIccEntry->RestoreL(iIccEntryPtr); |
|
173 iIccEntry->iPhonebookUid = iPhonebookUid; |
|
174 |
|
175 #ifdef _DEBUG |
|
176 iIccEntry->LogSyncContactICCEntry(); |
|
177 #endif |
|
178 |
|
179 // |
|
180 // Determine if the requested write is to add a new entry, edit an |
|
181 // existing entry, or move an existing entry from one slot to another. |
|
182 // |
|
183 if (iIccEntry->iContactId == KNullContactId || |
|
184 iIccEntry->iContactId == KGoldenTemplateId) |
|
185 { |
|
186 iTypeOfWrite = CWriteContactToICC::EWriteAddNew; |
|
187 } |
|
188 else |
|
189 { |
|
190 User::LeaveIfError(iPhonebookManager.GetSlotNumFromContactId(iPhonebookUid, |
|
191 iIccEntry->iContactId, |
|
192 iOldSlot)); |
|
193 |
|
194 if (iOldSlot != iIccEntry->iSlotNum) |
|
195 { |
|
196 iTypeOfWrite = CWriteContactToICC::EWriteEditSlotNumber; |
|
197 } |
|
198 else |
|
199 { |
|
200 iTypeOfWrite = CWriteContactToICC::EWriteEdit; |
|
201 } |
|
202 } |
|
203 |
|
204 // |
|
205 // Check if a destination slot is specified and if that slot is already used... |
|
206 // |
|
207 if (iIccEntry->iSlotNum != KSyncIndexNotSupplied) |
|
208 { |
|
209 TContactItemId tempId; |
|
210 TInt result; |
|
211 |
|
212 result = iPhonebookManager.GetContactIdFromSlotNum(iIccEntry->iPhonebookUid, |
|
213 iIccEntry->iSlotNum, |
|
214 tempId); |
|
215 if (result != KErrNotFound) |
|
216 { |
|
217 iIsUsedSlot = ETrue; |
|
218 } |
|
219 } |
|
220 |
|
221 // |
|
222 // This is an entry requiring an empty slot... |
|
223 // |
|
224 if (iIccEntry->iSlotNum == KSyncIndexNotSupplied) |
|
225 { |
|
226 TInt result; |
|
227 |
|
228 result = iPhonebookManager.GetFirstEmptySlot(iIccEntry->iPhonebookUid, |
|
229 iIccEntry->iSlotNum); |
|
230 |
|
231 if (result != KErrNone) |
|
232 { |
|
233 // |
|
234 // No empty slots exist... |
|
235 // |
|
236 LOGACTIVE1(_L8("CWriteContactToICC::DoIccWriteL(): No empty slots found.")); |
|
237 iSession.Server().CompleteWriteContactToICC(KErrNoMemory); |
|
238 return; |
|
239 } |
|
240 } |
|
241 |
|
242 // |
|
243 // Encode ICC entry into TLV format... |
|
244 // |
|
245 TRAPD(ret, EncodeICCEntryL()); |
|
246 if (ret != KErrNone) |
|
247 { |
|
248 // |
|
249 // Complete client request with the error... |
|
250 // |
|
251 iSession.Server().CompleteWriteContactToICC(ret); |
|
252 return; |
|
253 } |
|
254 |
|
255 // |
|
256 // Write the entry to the ICC... |
|
257 // |
|
258 iPhonebookStore.Write(iStatus, iPhonebookDataPtr, iIccEntry->iSlotNum); |
|
259 iIccWriteState = EPBSyncIccWriteWaitForIccWrite; |
|
260 SetActive(); |
|
261 |
|
262 LOGACTIVETIMESTAMP(); |
|
263 } // CWriteContactToICC::DoIccWriteL |
|
264 |
|
265 |
|
266 /** |
|
267 * Encodes the iIccEnty into the TLV format used by the ETel server. |
|
268 */ |
|
269 void CWriteContactToICC::EncodeICCEntryL() |
|
270 { |
|
271 // |
|
272 // First add new entry tag... |
|
273 // |
|
274 User::LeaveIfError(iPhonebookBuffer->AddNewEntryTag()); |
|
275 |
|
276 TInt i; |
|
277 |
|
278 // Get first representation of name |
|
279 // convert text into TLV format and append it to allocated buffer |
|
280 User::LeaveIfError(iPhonebookBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBText, iIccEntry->iName)); |
|
281 |
|
282 // Get second representation of name |
|
283 // convert text into TLV format and append it to allocated buffer |
|
284 User::LeaveIfError(iPhonebookBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBSecondName, iIccEntry->iSecondName)); |
|
285 |
|
286 // Get default number and its TON |
|
287 // First convert number into TLV format and append it to allocated buffer |
|
288 User::LeaveIfError(iPhonebookBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBNumber, iIccEntry->iNumber)); |
|
289 |
|
290 // convert type into TLV format and append it to allocated buffer |
|
291 User::LeaveIfError(iPhonebookBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBTonNpi, ConvertTonNpiByte(iIccEntry->iTON))); |
|
292 |
|
293 // Get list of additional numbers |
|
294 TInt count = iIccEntry->iNumberList->Count(); |
|
295 for(i=0; i < count; ++i) |
|
296 { |
|
297 CSyncContactICCEntry::TSyncAdditionalNumber additionalNumber; |
|
298 additionalNumber = iIccEntry->iNumberList->At(i); |
|
299 |
|
300 // Mark the beginning of an additional number |
|
301 User::LeaveIfError(iPhonebookBuffer->AddNewNumberTag()); |
|
302 |
|
303 // convert text into TLV format and append it to allocated buffer |
|
304 if (iPhBkInfoV5.iMaxTextLengthAdditionalNumber > 0) |
|
305 { |
|
306 User::LeaveIfError(iPhonebookBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBText, additionalNumber.iNumberString)); |
|
307 } |
|
308 |
|
309 // First convert number into TLV format and append it to allocated buffer |
|
310 User::LeaveIfError(iPhonebookBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBNumber, additionalNumber.iNumber)); |
|
311 |
|
312 // convert type into TLV format and append it to allocated buffer |
|
313 User::LeaveIfError(iPhonebookBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBTonNpi, ConvertTonNpiByte(additionalNumber.iTON))); |
|
314 } |
|
315 |
|
316 // Get list of groups |
|
317 count = iIccEntry->iGroupList->Count(); |
|
318 for(i=0; i < count; ++i) |
|
319 { |
|
320 CSyncContactICCEntry::TSyncEntryName group(iIccEntry->iGroupList->At(i)); |
|
321 // convert group into TLV format and append it to allocated buffer |
|
322 User::LeaveIfError(iPhonebookBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBGroupName, group)); |
|
323 } |
|
324 |
|
325 // Get list of e-mails |
|
326 count = iIccEntry->iEmailList->Count(); |
|
327 for(i=0; i < count; ++i) |
|
328 { |
|
329 CSyncContactICCEntry::TSyncEntryName email; |
|
330 email.Append(iIccEntry->iEmailList->At(i)); |
|
331 // convert e-mail into TLV format and append it to allocated buffer |
|
332 User::LeaveIfError(iPhonebookBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBEmailAddress, email)); |
|
333 } |
|
334 |
|
335 // Append hidden entry info here - this can only be added when V2 format is being used |
|
336 if (iSession.Server().IsV2Tsy()) |
|
337 { |
|
338 User::LeaveIfError(iPhonebookBuffer->PutTagAndValue(RMobilePhoneBookStore::ETagPBHiddenInfo,(TUint8)iIccEntry->iIsHidden)); |
|
339 } |
|
340 } // CWriteContactToICC::EncodeICCEntryL |
|
341 |
|
342 |
|
343 /** |
|
344 * Standard Active Object RunL() method to process the write request. |
|
345 */ |
|
346 void CWriteContactToICC::RunL() |
|
347 { |
|
348 LOGACTIVE2(_L8("CWriteContactToICC::RunL(): iStatus=%d"), iStatus.Int()); |
|
349 LOGACTIVETIMESTAMP(); |
|
350 |
|
351 switch (iIccWriteState) |
|
352 { |
|
353 case EPBSyncIccWriteWaitForIccWrite: |
|
354 { |
|
355 if (iStatus.Int() == KErrNone) |
|
356 { |
|
357 // |
|
358 // Update server's look-up table... |
|
359 // |
|
360 User::LeaveIfError(iPhonebookManager.UpdateEntryInTable(iPhonebookUid, iIccEntry->iSlotNum, |
|
361 KNullContactId, ESlotUsedAvailable)); |
|
362 |
|
363 if (iTypeOfWrite != EWriteAddNew) |
|
364 { |
|
365 // If this is a new entry the ID will be set by the contact model |
|
366 // If this is an edit the ID needs to be set here |
|
367 User::LeaveIfError(iPhonebookManager.UpdateEntryInTable(iPhonebookUid, iIccEntry->iSlotNum, iIccEntry->iContactId)); |
|
368 } |
|
369 |
|
370 // Are we editing slot number and need to remove entry at old slot? |
|
371 if (iTypeOfWrite == EWriteEditSlotNumber && |
|
372 iOldSlot != KErrNotFound) |
|
373 { |
|
374 // Decrement the number of used entries for the phonebook |
|
375 User::LeaveIfError(iPhonebookManager.AdjustPhoneBookInfoUsedEntries(iIccEntry->iPhonebookUid, -1)); |
|
376 |
|
377 iIccWriteState = EPBSyncIccWriteDeleteOldSlot;//need to delete entry at old slot |
|
378 iPhonebookStore.Delete(iStatus, iOldSlot); |
|
379 SetActive(); |
|
380 } |
|
381 else |
|
382 { |
|
383 iIccWriteState = EPBSyncIccWriteIdle; |
|
384 // If the entry is written to an unused slot increment the number of entries for the phonebook |
|
385 |
|
386 if (!iIsUsedSlot) |
|
387 { |
|
388 User::LeaveIfError(iPhonebookManager.AdjustPhoneBookInfoUsedEntries(iIccEntry->iPhonebookUid, 1)); |
|
389 } |
|
390 |
|
391 iSession.Server().CompleteWriteContactToICC(iStatus.Int()); |
|
392 } |
|
393 } |
|
394 else |
|
395 { |
|
396 iIccWriteState = EPBSyncIccWriteIdle; |
|
397 iSession.Server().CompleteWriteContactToICC(iStatus.Int()); |
|
398 } |
|
399 } |
|
400 break; |
|
401 |
|
402 case EPBSyncIccWriteDeleteOldSlot: |
|
403 { |
|
404 // |
|
405 // The client has requested to change the slot number of an entry |
|
406 // after the entry has been written at the new slot. |
|
407 // |
|
408 // Update the look up table even if the delete was not successful |
|
409 // (It would be very bad to have 2 entries with the same UID on |
|
410 // the table). |
|
411 // |
|
412 User::LeaveIfError(iPhonebookManager.UpdateEntryInTable(iPhonebookUid, iOldSlot, |
|
413 KNullContactId, ESlotEmpty)); |
|
414 |
|
415 // |
|
416 // If the entry is written to an unused slot increment the number |
|
417 // of entries for the phonebook... |
|
418 // |
|
419 if (iIsUsedSlot == EFalse) |
|
420 { |
|
421 User::LeaveIfError(iPhonebookManager.AdjustPhoneBookInfoUsedEntries(iIccEntry->iPhonebookUid, 1)); |
|
422 } |
|
423 |
|
424 iIccWriteState = EPBSyncIccWriteIdle; |
|
425 iSession.Server().CompleteWriteContactToICC(iStatus.Int()); |
|
426 } |
|
427 break; |
|
428 |
|
429 case EPBSyncIccWriteWaitForCancel: |
|
430 { |
|
431 iIccWriteState = EPBSyncIccWriteIdle; |
|
432 iSession.Server().CompleteWriteContactToICC(iStatus.Int()); |
|
433 } |
|
434 break; |
|
435 |
|
436 default: |
|
437 { |
|
438 PhBkSyncPanic(EPhBkSyncPanicDoIccWriteError); |
|
439 } |
|
440 break; |
|
441 } |
|
442 } // CWriteContactToICC::RunL |
|
443 |
|
444 |
|
445 /** |
|
446 * Standard Active Object DoCancel method called when the objects Cancel() |
|
447 * method is called. |
|
448 */ |
|
449 void CWriteContactToICC::DoCancel() |
|
450 { |
|
451 if (iIccWriteState == EPBSyncIccWriteWaitForIccWrite) |
|
452 { |
|
453 iPhonebookStore.CancelAsyncRequest(EMobilePhoneBookStoreWrite); |
|
454 iIccWriteState = EPBSyncIccWriteWaitForCancel; |
|
455 } |
|
456 else if(iIccWriteState == EPBSyncIccWriteDeleteOldSlot) |
|
457 { |
|
458 // |
|
459 // Don't change the state here. We will still need to update the look |
|
460 // up table if the entry is not deleted from the ICC in order not to |
|
461 // have 2 entries with the same UID. |
|
462 // |
|
463 iPhonebookStore.CancelAsyncRequest(EMobilePhoneStoreDelete); |
|
464 } |
|
465 } // CWriteContactToICC::DoCancel |
|
466 |
|
467 |
|
468 /** |
|
469 * Standard Active Object RunError method called when the objects RunL() |
|
470 * method leaves. |
|
471 * |
|
472 * Hopefully this method should never be called. |
|
473 * |
|
474 * @param aError Leave code from the RunL(). |
|
475 * |
|
476 * @return KErrNone is returned although the server will panic first. |
|
477 */ |
|
478 TInt CWriteContactToICC::RunError(TInt aError) |
|
479 { |
|
480 #ifdef _DEBUG |
|
481 LOGACTIVE2(_L8("CWriteContactToICC::RunError(%d)"), aError); |
|
482 #else |
|
483 (void) aError; |
|
484 #endif |
|
485 |
|
486 PhBkSyncPanic(EPhBkSyncPanicUnexpectedLeave); |
|
487 |
|
488 return KErrNone; |
|
489 } // CWriteContactToICC::RunError |
|
490 |
|
491 |
|
492 /** |
|
493 * Convert a ETel TON to an ICC TON value. |
|
494 * |
|
495 * @param aTon Should be an ETSI Type-Of-Number field. |
|
496 * |
|
497 * @return The equivalent RMobilePhone::TMobileTON value for aValue |
|
498 */ |
|
499 TUint8 CWriteContactToICC::ConvertTonNpiByte(RMobilePhone::TMobileTON aTon) |
|
500 { |
|
501 TUint8 result(0x81); |
|
502 |
|
503 // |
|
504 // The below 'magic numbers' come from the ETSI 03.40 |
|
505 // specification for Address Fields (section 9.1.2.5) |
|
506 // |
|
507 switch (aTon) |
|
508 { |
|
509 case RMobilePhone::EUnknownNumber: |
|
510 { |
|
511 result = 0x81; |
|
512 } |
|
513 break; |
|
514 |
|
515 case RMobilePhone::EInternationalNumber: |
|
516 { |
|
517 result = 0x91; |
|
518 } |
|
519 break; |
|
520 |
|
521 case RMobilePhone::ENationalNumber: |
|
522 { |
|
523 result = 0xA1; |
|
524 } |
|
525 break; |
|
526 |
|
527 case RMobilePhone::ENetworkSpecificNumber: |
|
528 { |
|
529 result = 0xB1; |
|
530 } |
|
531 break; |
|
532 |
|
533 case RMobilePhone::ESubscriberNumber: |
|
534 { |
|
535 result = 0xC1; |
|
536 } |
|
537 break; |
|
538 |
|
539 default: |
|
540 { |
|
541 result = 0x81; |
|
542 } |
|
543 break; |
|
544 } |
|
545 |
|
546 return result; |
|
547 } // CWriteContactToICC::ConvertTonNpiByte |
|
548 |