Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
4 subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
6 function run_test() {
7 run_next_test();
8 }
10 /**
11 * Helper function.
12 */
13 function newUint8Worker() {
14 let worker = newWorker();
15 let index = 0; // index for read
16 let buf = [];
18 let context = worker.ContextPool._contexts[0];
19 context.Buf.writeUint8 = function(value) {
20 buf.push(value);
21 };
23 context.Buf.readUint8 = function() {
24 return buf[index++];
25 };
27 context.Buf.seekIncoming = function(offset) {
28 index += offset;
29 };
31 context.Buf.getReadAvailable = function() {
32 return buf.length - index;
33 };
35 worker.debug = do_print;
37 return worker;
38 }
40 /**
41 * Verify ICCPDUHelper#readICCUCS2String()
42 */
43 add_test(function test_read_icc_ucs2_string() {
44 let worker = newUint8Worker();
45 let context = worker.ContextPool._contexts[0];
46 let helper = context.GsmPDUHelper;
47 let iccHelper = context.ICCPDUHelper;
49 // 0x80
50 let text = "TEST";
51 helper.writeUCS2String(text);
52 // Also write two unused octets.
53 let ffLen = 2;
54 for (let i = 0; i < ffLen; i++) {
55 helper.writeHexOctet(0xff);
56 }
57 do_check_eq(iccHelper.readICCUCS2String(0x80, (2 * text.length) + ffLen), text);
59 // 0x81
60 let array = [0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca,
61 0xff, 0xff];
62 let len = array.length;
63 for (let i = 0; i < len; i++) {
64 helper.writeHexOctet(array[i]);
65 }
66 do_check_eq(iccHelper.readICCUCS2String(0x81, len), "Mozilla\u694a");
68 // 0x82
69 let array2 = [0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61,
70 0xca, 0xff, 0xff];
71 let len2 = array2.length;
72 for (let i = 0; i < len2; i++) {
73 helper.writeHexOctet(array2[i]);
74 }
75 do_check_eq(iccHelper.readICCUCS2String(0x82, len2), "Mozilla\u694a");
77 run_next_test();
78 });
80 /**
81 * Verify ICCPDUHelper#readDiallingNumber
82 */
83 add_test(function test_read_dialling_number() {
84 let worker = newUint8Worker();
85 let context = worker.ContextPool._contexts[0];
86 let helper = context.GsmPDUHelper;
87 let iccHelper = context.ICCPDUHelper;
88 let str = "123456789";
90 helper.readHexOctet = function() {
91 return 0x81;
92 };
94 helper.readSwappedNibbleBcdString = function(len) {
95 return str.substring(0, len);
96 };
98 for (let i = 0; i < str.length; i++) {
99 do_check_eq(str.substring(0, i - 1), // -1 for the TON
100 iccHelper.readDiallingNumber(i));
101 }
103 run_next_test();
104 });
106 /**
107 * Verify ICCPDUHelper#read8BitUnpackedToString
108 */
109 add_test(function test_read_8bit_unpacked_to_string() {
110 let worker = newUint8Worker();
111 let context = worker.ContextPool._contexts[0];
112 let helper = context.GsmPDUHelper;
113 let iccHelper = context.ICCPDUHelper;
114 const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
115 const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
117 // Test 1: Read GSM alphabets.
118 // Write alphabets before ESCAPE.
119 for (let i = 0; i < PDU_NL_EXTENDED_ESCAPE; i++) {
120 helper.writeHexOctet(i);
121 }
123 // Write two ESCAPEs to make it become ' '.
124 helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
125 helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
127 for (let i = PDU_NL_EXTENDED_ESCAPE + 1; i < langTable.length; i++) {
128 helper.writeHexOctet(i);
129 }
131 // Also write two unused fields.
132 let ffLen = 2;
133 for (let i = 0; i < ffLen; i++) {
134 helper.writeHexOctet(0xff);
135 }
137 do_check_eq(iccHelper.read8BitUnpackedToString(PDU_NL_EXTENDED_ESCAPE),
138 langTable.substring(0, PDU_NL_EXTENDED_ESCAPE));
139 do_check_eq(iccHelper.read8BitUnpackedToString(2), " ");
140 do_check_eq(iccHelper.read8BitUnpackedToString(langTable.length -
141 PDU_NL_EXTENDED_ESCAPE - 1 + ffLen),
142 langTable.substring(PDU_NL_EXTENDED_ESCAPE + 1));
144 // Test 2: Read GSM extended alphabets.
145 for (let i = 0; i < langShiftTable.length; i++) {
146 helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
147 helper.writeHexOctet(i);
148 }
150 // Read string before RESERVED_CONTROL.
151 do_check_eq(iccHelper.read8BitUnpackedToString(PDU_NL_RESERVED_CONTROL * 2),
152 langShiftTable.substring(0, PDU_NL_RESERVED_CONTROL));
153 // ESCAPE + RESERVED_CONTROL will become ' '.
154 do_check_eq(iccHelper.read8BitUnpackedToString(2), " ");
155 // Read string between RESERVED_CONTROL and EXTENDED_ESCAPE.
156 do_check_eq(iccHelper.read8BitUnpackedToString(
157 (PDU_NL_EXTENDED_ESCAPE - PDU_NL_RESERVED_CONTROL - 1) * 2),
158 langShiftTable.substring(PDU_NL_RESERVED_CONTROL + 1,
159 PDU_NL_EXTENDED_ESCAPE));
160 // ESCAPE + ESCAPE will become ' '.
161 do_check_eq(iccHelper.read8BitUnpackedToString(2), " ");
162 // Read remaining string.
163 do_check_eq(iccHelper.read8BitUnpackedToString(
164 (langShiftTable.length - PDU_NL_EXTENDED_ESCAPE - 1) * 2),
165 langShiftTable.substring(PDU_NL_EXTENDED_ESCAPE + 1));
167 run_next_test();
168 });
170 /**
171 * Verify ICCPDUHelper#writeStringTo8BitUnpacked.
172 *
173 * Test writing GSM 8 bit alphabets.
174 */
175 add_test(function test_write_string_to_8bit_unpacked() {
176 let worker = newUint8Worker();
177 let context = worker.ContextPool._contexts[0];
178 let helper = context.GsmPDUHelper;
179 let iccHelper = context.ICCPDUHelper;
180 const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
181 const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
182 // Length of trailing 0xff.
183 let ffLen = 2;
184 let str;
186 // Test 1, write GSM alphabets.
187 iccHelper.writeStringTo8BitUnpacked(langTable.length + ffLen, langTable);
189 for (let i = 0; i < langTable.length; i++) {
190 do_check_eq(helper.readHexOctet(), i);
191 }
193 for (let i = 0; i < ffLen; i++) {
194 do_check_eq(helper.readHexOctet(), 0xff);
195 }
197 // Test 2, write GSM extended alphabets.
198 str = "\u000c\u20ac";
199 iccHelper.writeStringTo8BitUnpacked(4, str);
201 do_check_eq(iccHelper.read8BitUnpackedToString(4), str);
203 // Test 3, write GSM and GSM extended alphabets.
204 // \u000c, \u20ac are from gsm extended alphabets.
205 // \u00a3 is from gsm alphabet.
206 str = "\u000c\u20ac\u00a3";
208 // 2 octets * 2 = 4 octets for 2 gsm extended alphabets,
209 // 1 octet for 1 gsm alphabet,
210 // 2 octes for trailing 0xff.
211 // "Totally 7 octets are to be written."
212 iccHelper.writeStringTo8BitUnpacked(7, str);
214 do_check_eq(iccHelper.read8BitUnpackedToString(7), str);
216 run_next_test();
217 });
219 /**
220 * Verify ICCPDUHelper#writeStringTo8BitUnpacked with maximum octets written.
221 */
222 add_test(function test_write_string_to_8bit_unpacked_with_max_octets_written() {
223 let worker = newUint8Worker();
224 let context = worker.ContextPool._contexts[0];
225 let helper = context.GsmPDUHelper;
226 let iccHelper = context.ICCPDUHelper;
227 const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
228 const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
230 // The maximum of the number of octets that can be written is 3.
231 // Only 3 characters shall be written even the length of the string is 4.
232 iccHelper.writeStringTo8BitUnpacked(3, langTable.substring(0, 4));
233 helper.writeHexOctet(0xff); // dummy octet.
234 for (let i = 0; i < 3; i++) {
235 do_check_eq(helper.readHexOctet(), i);
236 }
237 do_check_false(helper.readHexOctet() == 4);
239 // \u000c is GSM extended alphabet, 2 octets.
240 // \u00a3 is GSM alphabet, 1 octet.
241 let str = "\u000c\u00a3";
242 iccHelper.writeStringTo8BitUnpacked(3, str);
243 do_check_eq(iccHelper.read8BitUnpackedToString(3), str);
245 str = "\u00a3\u000c";
246 iccHelper.writeStringTo8BitUnpacked(3, str);
247 do_check_eq(iccHelper.read8BitUnpackedToString(3), str);
249 // 2 GSM extended alphabets cost 4 octets, but maximum is 3, so only the 1st
250 // alphabet can be written.
251 str = "\u000c\u000c";
252 iccHelper.writeStringTo8BitUnpacked(3, str);
253 helper.writeHexOctet(0xff); // dummy octet.
254 do_check_eq(iccHelper.read8BitUnpackedToString(4), str.substring(0, 1));
256 run_next_test();
257 });
259 /**
260 * Verify ICCPDUHelper.readAlphaIdentifier
261 */
262 add_test(function test_read_alpha_identifier() {
263 let worker = newUint8Worker();
264 let context = worker.ContextPool._contexts[0];
265 let helper = context.GsmPDUHelper;
266 let iccHelper = context.ICCPDUHelper;
268 // UCS2: 0x80
269 let text = "TEST";
270 helper.writeHexOctet(0x80);
271 helper.writeUCS2String(text);
272 // Also write two unused octets.
273 let ffLen = 2;
274 for (let i = 0; i < ffLen; i++) {
275 helper.writeHexOctet(0xff);
276 }
277 do_check_eq(iccHelper.readAlphaIdentifier(1 + (2 * text.length) + ffLen), text);
279 // UCS2: 0x81
280 let array = [0x81, 0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff];
281 for (let i = 0; i < array.length; i++) {
282 helper.writeHexOctet(array[i]);
283 }
284 do_check_eq(iccHelper.readAlphaIdentifier(array.length), "Mozilla\u694a");
286 // UCS2: 0x82
287 let array2 = [0x82, 0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff];
288 for (let i = 0; i < array2.length; i++) {
289 helper.writeHexOctet(array2[i]);
290 }
291 do_check_eq(iccHelper.readAlphaIdentifier(array2.length), "Mozilla\u694a");
293 // GSM 8 Bit Unpacked
294 const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
295 for (let i = 0; i < PDU_NL_EXTENDED_ESCAPE; i++) {
296 helper.writeHexOctet(i);
297 }
298 do_check_eq(iccHelper.readAlphaIdentifier(PDU_NL_EXTENDED_ESCAPE),
299 langTable.substring(0, PDU_NL_EXTENDED_ESCAPE));
301 run_next_test();
302 });
304 /**
305 * Verify ICCPDUHelper.writeAlphaIdentifier
306 */
307 add_test(function test_write_alpha_identifier() {
308 let worker = newUint8Worker();
309 let context = worker.ContextPool._contexts[0];
310 let helper = context.GsmPDUHelper;
311 let iccHelper = context.ICCPDUHelper;
312 // Length of trailing 0xff.
313 let ffLen = 2;
315 // Removal
316 iccHelper.writeAlphaIdentifier(10, null);
317 do_check_eq(iccHelper.readAlphaIdentifier(10), "");
319 // GSM 8 bit
320 let str = "Mozilla";
321 iccHelper.writeAlphaIdentifier(str.length + ffLen, str);
322 do_check_eq(iccHelper.readAlphaIdentifier(str.length + ffLen), str);
324 // UCS2
325 str = "Mozilla\u694a";
326 iccHelper.writeAlphaIdentifier(str.length * 2 + ffLen, str);
327 // * 2 for each character will be encoded to UCS2 alphabets.
328 do_check_eq(iccHelper.readAlphaIdentifier(str.length * 2 + ffLen), str);
330 // Test with maximum octets written.
331 // 1 coding scheme (0x80) and 1 UCS2 character, total 3 octets.
332 str = "\u694a";
333 iccHelper.writeAlphaIdentifier(3, str);
334 do_check_eq(iccHelper.readAlphaIdentifier(3), str);
336 // 1 coding scheme (0x80) and 2 UCS2 characters, total 5 octets.
337 // numOctets is limited to 4, so only 1 UCS2 character can be written.
338 str = "\u694a\u694a";
339 iccHelper.writeAlphaIdentifier(4, str);
340 helper.writeHexOctet(0xff); // dummy octet.
341 do_check_eq(iccHelper.readAlphaIdentifier(5), str.substring(0, 1));
343 // Write 0 octet.
344 iccHelper.writeAlphaIdentifier(0, "1");
345 helper.writeHexOctet(0xff); // dummy octet.
346 do_check_eq(iccHelper.readAlphaIdentifier(1), "");
348 run_next_test();
349 });
351 /**
352 * Verify ICCPDUHelper.readAlphaIdDiallingNumber
353 */
354 add_test(function test_read_alpha_id_dialling_number() {
355 let worker = newUint8Worker();
356 let context = worker.ContextPool._contexts[0];
357 let helper = context.GsmPDUHelper;
358 let iccHelper = context.ICCPDUHelper;
359 let buf = context.Buf;
360 const recordSize = 32;
362 function testReadAlphaIdDiallingNumber(contact) {
363 iccHelper.readAlphaIdentifier = function() {
364 return contact.alphaId;
365 };
367 iccHelper.readNumberWithLength = function() {
368 return contact.number;
369 };
371 let strLen = recordSize * 2;
372 buf.writeInt32(strLen); // fake length
373 helper.writeHexOctet(0xff); // fake CCP
374 helper.writeHexOctet(0xff); // fake EXT1
375 buf.writeStringDelimiter(strLen);
377 let contactR = iccHelper.readAlphaIdDiallingNumber(recordSize);
378 if (contact.alphaId == "" && contact.number == "") {
379 do_check_eq(contactR, null);
380 } else {
381 do_check_eq(contactR.alphaId, contact.alphaId);
382 do_check_eq(contactR.number, contact.number);
383 }
384 }
386 testReadAlphaIdDiallingNumber({alphaId: "AlphaId", number: "0987654321"});
387 testReadAlphaIdDiallingNumber({alphaId: "", number: ""});
389 run_next_test();
390 });
392 /**
393 * Verify ICCPDUHelper.writeAlphaIdDiallingNumber
394 */
395 add_test(function test_write_alpha_id_dialling_number() {
396 let worker = newUint8Worker();
397 let context = worker.ContextPool._contexts[0];
398 let helper = context.ICCPDUHelper;
399 const recordSize = 32;
401 // Write a normal contact.
402 let contactW = {
403 alphaId: "Mozilla",
404 number: "1234567890"
405 };
406 helper.writeAlphaIdDiallingNumber(recordSize, contactW.alphaId,
407 contactW.number);
409 let contactR = helper.readAlphaIdDiallingNumber(recordSize);
410 do_check_eq(contactW.alphaId, contactR.alphaId);
411 do_check_eq(contactW.number, contactR.number);
413 // Write a contact with alphaId encoded in UCS2 and number has '+'.
414 let contactUCS2 = {
415 alphaId: "火狐",
416 number: "+1234567890"
417 };
418 helper.writeAlphaIdDiallingNumber(recordSize, contactUCS2.alphaId,
419 contactUCS2.number);
420 contactR = helper.readAlphaIdDiallingNumber(recordSize);
421 do_check_eq(contactUCS2.alphaId, contactR.alphaId);
422 do_check_eq(contactUCS2.number, contactR.number);
424 // Write a null contact (Removal).
425 helper.writeAlphaIdDiallingNumber(recordSize);
426 contactR = helper.readAlphaIdDiallingNumber(recordSize);
427 do_check_eq(contactR, null);
429 // Write a longer alphaId/dialling number
430 // Dialling Number : Maximum 20 digits(10 octets).
431 // Alpha Identifier: 32(recordSize) - 14 (10 octets for Dialling Number, 1
432 // octet for TON/NPI, 1 for number length octet, and 2 for
433 // Ext) = Maximum 18 octets.
434 let longContact = {
435 alphaId: "AAAAAAAAABBBBBBBBBCCCCCCCCC",
436 number: "123456789012345678901234567890",
437 };
438 helper.writeAlphaIdDiallingNumber(recordSize, longContact.alphaId,
439 longContact.number);
440 contactR = helper.readAlphaIdDiallingNumber(recordSize);
441 do_check_eq(contactR.alphaId, "AAAAAAAAABBBBBBBBB");
442 do_check_eq(contactR.number, "12345678901234567890");
444 // Add '+' to number and test again.
445 longContact.number = "+123456789012345678901234567890";
446 helper.writeAlphaIdDiallingNumber(recordSize, longContact.alphaId,
447 longContact.number);
448 contactR = helper.readAlphaIdDiallingNumber(recordSize);
449 do_check_eq(contactR.alphaId, "AAAAAAAAABBBBBBBBB");
450 do_check_eq(contactR.number, "+12345678901234567890");
452 run_next_test();
453 });
455 /**
456 * Verify ICCPDUHelper.writeDiallingNumber
457 */
458 add_test(function test_write_dialling_number() {
459 let worker = newUint8Worker();
460 let context = worker.ContextPool._contexts[0];
461 let helper = context.ICCPDUHelper;
463 // with +
464 let number = "+123456";
465 let len = 4;
466 helper.writeDiallingNumber(number);
467 do_check_eq(helper.readDiallingNumber(len), number);
469 // without +
470 number = "987654";
471 len = 4;
472 helper.writeDiallingNumber(number);
473 do_check_eq(helper.readDiallingNumber(len), number);
475 number = "9876543";
476 len = 5;
477 helper.writeDiallingNumber(number);
478 do_check_eq(helper.readDiallingNumber(len), number);
480 run_next_test();
481 });
483 /**
484 * Verify ICCPDUHelper.readNumberWithLength
485 */
486 add_test(function test_read_number_with_length() {
487 let worker = newUint8Worker();
488 let context = worker.ContextPool._contexts[0];
489 let helper = context.GsmPDUHelper;
490 let iccHelper = context.ICCPDUHelper;
491 let number = "123456789";
493 iccHelper.readDiallingNumber = function(numLen) {
494 return number.substring(0, numLen);
495 };
497 helper.writeHexOctet(number.length + 1);
498 helper.writeHexOctet(PDU_TOA_ISDN);
499 do_check_eq(iccHelper.readNumberWithLength(), number);
501 helper.writeHexOctet(0xff);
502 do_check_eq(iccHelper.readNumberWithLength(), null);
504 run_next_test();
505 });
507 /**
508 * Verify ICCPDUHelper.writeNumberWithLength
509 */
510 add_test(function test_write_number_with_length() {
511 let worker = newUint8Worker();
512 let context = worker.ContextPool._contexts[0];
513 let helper = context.GsmPDUHelper;
514 let iccHelper = context.ICCPDUHelper;
516 function test(number, expectedNumber) {
517 expectedNumber = expectedNumber || number;
518 iccHelper.writeNumberWithLength(number);
519 let numLen = helper.readHexOctet();
520 do_check_eq(expectedNumber, iccHelper.readDiallingNumber(numLen));
521 for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES - numLen); i++) {
522 do_check_eq(0xff, helper.readHexOctet());
523 }
524 }
526 // without +
527 test("123456789");
529 // with +
530 test("+987654321");
532 // extended BCD coding
533 test("1*2#3,4*5#6,");
535 // with + and extended BCD coding
536 test("+1*2#3,4*5#6,");
538 // non-supported characters should not be written.
539 test("(1)23-456+789", "123456789");
541 test("++(01)2*3-4#5,6+7(8)9*0#1,", "+012*34#5,6789*0#1,");
543 // null
544 iccHelper.writeNumberWithLength(null);
545 for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES + 1); i++) {
546 do_check_eq(0xff, helper.readHexOctet());
547 }
549 run_next_test();
550 });
552 /**
553 * Verify GsmPDUHelper.writeTimestamp
554 */
555 add_test(function test_write_timestamp() {
556 let worker = newUint8Worker();
557 let context = worker.ContextPool._contexts[0];
558 let helper = context.GsmPDUHelper;
560 // current date
561 let dateInput = new Date();
562 let dateOutput = new Date();
563 helper.writeTimestamp(dateInput);
564 dateOutput.setTime(helper.readTimestamp());
566 do_check_eq(dateInput.getFullYear(), dateOutput.getFullYear());
567 do_check_eq(dateInput.getMonth(), dateOutput.getMonth());
568 do_check_eq(dateInput.getDate(), dateOutput.getDate());
569 do_check_eq(dateInput.getHours(), dateOutput.getHours());
570 do_check_eq(dateInput.getMinutes(), dateOutput.getMinutes());
571 do_check_eq(dateInput.getSeconds(), dateOutput.getSeconds());
572 do_check_eq(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
574 // 2034-01-23 12:34:56 -0800 GMT
575 let time = Date.UTC(2034, 1, 23, 12, 34, 56);
576 time = time - (8 * 60 * 60 * 1000);
577 dateInput.setTime(time);
578 helper.writeTimestamp(dateInput);
579 dateOutput.setTime(helper.readTimestamp());
581 do_check_eq(dateInput.getFullYear(), dateOutput.getFullYear());
582 do_check_eq(dateInput.getMonth(), dateOutput.getMonth());
583 do_check_eq(dateInput.getDate(), dateOutput.getDate());
584 do_check_eq(dateInput.getHours(), dateOutput.getHours());
585 do_check_eq(dateInput.getMinutes(), dateOutput.getMinutes());
586 do_check_eq(dateInput.getSeconds(), dateOutput.getSeconds());
587 do_check_eq(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
589 run_next_test();
590 });
592 /**
593 * Verify GsmPDUHelper.octectToBCD and GsmPDUHelper.BCDToOctet
594 */
595 add_test(function test_octect_BCD() {
596 let worker = newUint8Worker();
597 let context = worker.ContextPool._contexts[0];
598 let helper = context.GsmPDUHelper;
600 // 23
601 let number = 23;
602 let octet = helper.BCDToOctet(number);
603 do_check_eq(helper.octetToBCD(octet), number);
605 // 56
606 number = 56;
607 octet = helper.BCDToOctet(number);
608 do_check_eq(helper.octetToBCD(octet), number);
610 // 0x23
611 octet = 0x23;
612 number = helper.octetToBCD(octet);
613 do_check_eq(helper.BCDToOctet(number), octet);
615 // 0x56
616 octet = 0x56;
617 number = helper.octetToBCD(octet);
618 do_check_eq(helper.BCDToOctet(number), octet);
620 run_next_test();
621 });
623 /**
624 * Verify ICCUtilsHelper.isICCServiceAvailable.
625 */
626 add_test(function test_is_icc_service_available() {
627 let worker = newUint8Worker();
628 let context = worker.ContextPool._contexts[0];
629 let ICCUtilsHelper = context.ICCUtilsHelper;
630 let RIL = context.RIL;
632 function test_table(sst, geckoService, simEnabled, usimEnabled) {
633 RIL.iccInfoPrivate.sst = sst;
634 RIL.appType = CARD_APPTYPE_SIM;
635 do_check_eq(ICCUtilsHelper.isICCServiceAvailable(geckoService), simEnabled);
636 RIL.appType = CARD_APPTYPE_USIM;
637 do_check_eq(ICCUtilsHelper.isICCServiceAvailable(geckoService), usimEnabled);
638 }
640 test_table([0x08], "ADN", true, false);
641 test_table([0x08], "FDN", false, false);
642 test_table([0x08], "SDN", false, true);
644 run_next_test();
645 });
647 /**
648 * Verify ICCUtilsHelper.isGsm8BitAlphabet
649 */
650 add_test(function test_is_gsm_8bit_alphabet() {
651 let worker = newUint8Worker();
652 let context = worker.ContextPool._contexts[0];
653 let ICCUtilsHelper = context.ICCUtilsHelper;
654 const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
655 const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
657 do_check_eq(ICCUtilsHelper.isGsm8BitAlphabet(langTable), true);
658 do_check_eq(ICCUtilsHelper.isGsm8BitAlphabet(langShiftTable), true);
659 do_check_eq(ICCUtilsHelper.isGsm8BitAlphabet("\uaaaa"), false);
661 run_next_test();
662 });
664 /**
665 * Verify RIL.iccGetCardLockState("fdn")
666 */
667 add_test(function test_icc_get_card_lock_state_fdn() {
668 let worker = newUint8Worker();
669 let context = worker.ContextPool._contexts[0];
670 let ril = context.RIL;
671 let buf = context.Buf;
673 buf.sendParcel = function() {
674 // Request Type.
675 do_check_eq(this.readInt32(), REQUEST_QUERY_FACILITY_LOCK)
677 // Token : we don't care.
678 this.readInt32();
680 // String Array Length.
681 do_check_eq(this.readInt32(), ril.v5Legacy ? 3 : 4);
683 // Facility.
684 do_check_eq(this.readString(), ICC_CB_FACILITY_FDN);
686 // Password.
687 do_check_eq(this.readString(), "");
689 // Service class.
690 do_check_eq(this.readString(), (ICC_SERVICE_CLASS_VOICE |
691 ICC_SERVICE_CLASS_DATA |
692 ICC_SERVICE_CLASS_FAX).toString());
694 if (!ril.v5Legacy) {
695 // AID. Ignore because it's from modem.
696 this.readInt32();
697 }
699 run_next_test();
700 };
702 ril.iccGetCardLockState({lockType: "fdn"});
703 });
705 add_test(function test_get_network_name_from_icc() {
706 let worker = newUint8Worker();
707 let context = worker.ContextPool._contexts[0];
708 let RIL = context.RIL;
709 let ICCUtilsHelper = context.ICCUtilsHelper;
711 function testGetNetworkNameFromICC(operatorData, expectedResult) {
712 let result = ICCUtilsHelper.getNetworkNameFromICC(operatorData.mcc,
713 operatorData.mnc,
714 operatorData.lac);
716 if (expectedResult == null) {
717 do_check_eq(result, expectedResult);
718 } else {
719 do_check_eq(result.fullName, expectedResult.longName);
720 do_check_eq(result.shortName, expectedResult.shortName);
721 }
722 }
724 // Before EF_OPL and EF_PNN have been loaded.
725 testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000}, null);
726 testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x2000}, null);
728 // Set HPLMN
729 RIL.iccInfo.mcc = 123;
730 RIL.iccInfo.mnc = 456;
732 RIL.voiceRegistrationState = {
733 cell: {
734 gsmLocationAreaCode: 0x1000
735 }
736 };
737 RIL.operator = {};
739 // Set EF_PNN
740 RIL.iccInfoPrivate = {
741 PNN: [
742 {"fullName": "PNN1Long", "shortName": "PNN1Short"},
743 {"fullName": "PNN2Long", "shortName": "PNN2Short"},
744 {"fullName": "PNN3Long", "shortName": "PNN3Short"},
745 {"fullName": "PNN4Long", "shortName": "PNN4Short"}
746 ]
747 };
749 // EF_OPL isn't available and current isn't in HPLMN,
750 testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x1000}, null);
752 // EF_OPL isn't available and current is in HPLMN,
753 // the first record of PNN should be returned.
754 testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000},
755 {longName: "PNN1Long", shortName: "PNN1Short"});
757 // Set EF_OPL
758 RIL.iccInfoPrivate.OPL = [
759 {
760 "mcc": 123,
761 "mnc": 456,
762 "lacTacStart": 0,
763 "lacTacEnd": 0xFFFE,
764 "pnnRecordId": 4
765 },
766 {
767 "mcc": 321,
768 "mnc": 654,
769 "lacTacStart": 0,
770 "lacTacEnd": 0x0010,
771 "pnnRecordId": 3
772 },
773 {
774 "mcc": 321,
775 "mnc": 654,
776 "lacTacStart": 0x0100,
777 "lacTacEnd": 0x1010,
778 "pnnRecordId": 2
779 }
780 ];
782 // Both EF_PNN and EF_OPL are presented, and current PLMN is HPLMN,
783 testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000},
784 {longName: "PNN4Long", shortName: "PNN4Short"});
786 // Current PLMN is not HPLMN, and according to LAC, we should get
787 // the second PNN record.
788 testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x1000},
789 {longName: "PNN2Long", shortName: "PNN2Short"});
791 // Current PLMN is not HPLMN, and according to LAC, we should get
792 // the thrid PNN record.
793 testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x0001},
794 {longName: "PNN3Long", shortName: "PNN3Short"});
796 run_next_test();
797 });
799 add_test(function test_path_id_for_spid_and_spn() {
800 let worker = newWorker({
801 postRILMessage: function(data) {
802 // Do nothing
803 },
804 postMessage: function(message) {
805 // Do nothing
806 }});
807 let context = worker.ContextPool._contexts[0];
808 let RIL = context.RIL;
809 let ICCFileHelper = context.ICCFileHelper;
811 // Test SIM
812 RIL.appType = CARD_APPTYPE_SIM;
813 do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
814 EF_PATH_MF_SIM + EF_PATH_DF_GSM);
815 do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPN),
816 EF_PATH_MF_SIM + EF_PATH_DF_GSM);
818 // Test USIM
819 RIL.appType = CARD_APPTYPE_USIM;
820 do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
821 EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
822 do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
823 EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
824 run_next_test();
825 });
827 /**
828 * Verify ICCUtilsHelper.parsePbrTlvs
829 */
830 add_test(function test_parse_pbr_tlvs() {
831 let worker = newUint8Worker();
832 let context = worker.ContextPool._contexts[0];
833 let buf = context.Buf;
835 let pbrTlvs = [
836 {tag: ICC_USIM_TYPE1_TAG,
837 length: 0x0F,
838 value: [{tag: ICC_USIM_EFADN_TAG,
839 length: 0x03,
840 value: [0x4F, 0x3A, 0x02]},
841 {tag: ICC_USIM_EFIAP_TAG,
842 length: 0x03,
843 value: [0x4F, 0x25, 0x01]},
844 {tag: ICC_USIM_EFPBC_TAG,
845 length: 0x03,
846 value: [0x4F, 0x09, 0x04]}]
847 },
848 {tag: ICC_USIM_TYPE2_TAG,
849 length: 0x05,
850 value: [{tag: ICC_USIM_EFEMAIL_TAG,
851 length: 0x03,
852 value: [0x4F, 0x50, 0x0B]},
853 {tag: ICC_USIM_EFANR_TAG,
854 length: 0x03,
855 value: [0x4F, 0x11, 0x02]},
856 {tag: ICC_USIM_EFANR_TAG,
857 length: 0x03,
858 value: [0x4F, 0x12, 0x03]}]
859 },
860 {tag: ICC_USIM_TYPE3_TAG,
861 length: 0x0A,
862 value: [{tag: ICC_USIM_EFCCP1_TAG,
863 length: 0x03,
864 value: [0x4F, 0x3D, 0x0A]},
865 {tag: ICC_USIM_EFEXT1_TAG,
866 length: 0x03,
867 value: [0x4F, 0x4A, 0x03]}]
868 },
869 ];
871 let pbr = context.ICCUtilsHelper.parsePbrTlvs(pbrTlvs);
872 do_check_eq(pbr.adn.fileId, 0x4F3a);
873 do_check_eq(pbr.iap.fileId, 0x4F25);
874 do_check_eq(pbr.pbc.fileId, 0x4F09);
875 do_check_eq(pbr.email.fileId, 0x4F50);
876 do_check_eq(pbr.anr0.fileId, 0x4f11);
877 do_check_eq(pbr.anr1.fileId, 0x4f12);
878 do_check_eq(pbr.ccp1.fileId, 0x4F3D);
879 do_check_eq(pbr.ext1.fileId, 0x4F4A);
881 run_next_test();
882 });
884 /**
885 * Verify ICCIOHelper.loadLinearFixedEF with recordSize.
886 */
887 add_test(function test_load_linear_fixed_ef() {
888 let worker = newUint8Worker();
889 let context = worker.ContextPool._contexts[0];
890 let ril = context.RIL;
891 let io = context.ICCIOHelper;
893 io.getResponse = function fakeGetResponse(options) {
894 // When recordSize is provided, loadLinearFixedEF should call iccIO directly.
895 do_check_true(false);
896 run_next_test();
897 };
899 ril.iccIO = function fakeIccIO(options) {
900 do_check_true(true);
901 run_next_test();
902 };
904 io.loadLinearFixedEF({recordSize: 0x20});
905 });
907 /**
908 * Verify ICCIOHelper.loadLinearFixedEF without recordSize.
909 */
910 add_test(function test_load_linear_fixed_ef() {
911 let worker = newUint8Worker();
912 let context = worker.ContextPool._contexts[0];
913 let ril = context.RIL;
914 let io = context.ICCIOHelper;
916 io.getResponse = function fakeGetResponse(options) {
917 do_check_true(true);
918 run_next_test();
919 };
921 ril.iccIO = function fakeIccIO(options) {
922 // When recordSize is not provided, loadLinearFixedEF should call getResponse.
923 do_check_true(false);
924 run_next_test();
925 };
927 io.loadLinearFixedEF({});
928 });
930 /**
931 * Verify ICCRecordHelper.readPBR
932 */
933 add_test(function test_read_pbr() {
934 let worker = newUint8Worker();
935 let context = worker.ContextPool._contexts[0];
936 let helper = context.GsmPDUHelper;
937 let record = context.ICCRecordHelper;
938 let buf = context.Buf;
939 let io = context.ICCIOHelper;
941 io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
942 let pbr_1 = [
943 0xa8, 0x05, 0xc0, 0x03, 0x4f, 0x3a, 0x01
944 ];
946 // Write data size
947 buf.writeInt32(pbr_1.length * 2);
949 // Write pbr
950 for (let i = 0; i < pbr_1.length; i++) {
951 helper.writeHexOctet(pbr_1[i]);
952 }
954 // Write string delimiter
955 buf.writeStringDelimiter(pbr_1.length * 2);
957 options.totalRecords = 2;
958 if (options.callback) {
959 options.callback(options);
960 }
961 };
963 io.loadNextRecord = function fakeLoadNextRecord(options) {
964 let pbr_2 = [
965 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
966 ];
968 options.p1++;
969 if (options.callback) {
970 options.callback(options);
971 }
972 };
974 let successCb = function successCb(pbrs) {
975 do_check_eq(pbrs[0].adn.fileId, 0x4f3a);
976 do_check_eq(pbrs.length, 1);
977 };
979 let errorCb = function errorCb(errorMsg) {
980 do_print("Reading EF_PBR failed, msg = " + errorMsg);
981 do_check_true(false);
982 };
984 record.readPBR(successCb, errorCb);
986 // Check cache pbrs when 2nd call
987 let ifLoadEF = false;
988 io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
989 ifLoadEF = true;
990 }
991 record.readPBR(successCb, errorCb);
992 do_check_false(ifLoadEF);
994 run_next_test();
995 });
997 /**
998 * Verify ICCRecordHelper.readEmail
999 */
1000 add_test(function test_read_email() {
1001 let worker = newUint8Worker();
1002 let context = worker.ContextPool._contexts[0];
1003 let helper = context.GsmPDUHelper;
1004 let record = context.ICCRecordHelper;
1005 let buf = context.Buf;
1006 let io = context.ICCIOHelper;
1007 let recordSize;
1009 io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
1010 let email_1 = [
1011 0x65, 0x6D, 0x61, 0x69, 0x6C,
1012 0x00, 0x6D, 0x6F, 0x7A, 0x69,
1013 0x6C, 0x6C, 0x61, 0x2E, 0x63,
1014 0x6F, 0x6D, 0x02, 0x23];
1016 // Write data size
1017 buf.writeInt32(email_1.length * 2);
1019 // Write email
1020 for (let i = 0; i < email_1.length; i++) {
1021 helper.writeHexOctet(email_1[i]);
1022 }
1024 // Write string delimiter
1025 buf.writeStringDelimiter(email_1.length * 2);
1027 recordSize = email_1.length;
1028 options.recordSize = recordSize;
1029 if (options.callback) {
1030 options.callback(options);
1031 }
1032 };
1034 function doTestReadEmail(type, expectedResult) {
1035 let fileId = 0x6a75;
1036 let recordNumber = 1;
1038 // fileId and recordNumber are dummy arguments.
1039 record.readEmail(fileId, type, recordNumber, function(email) {
1040 do_check_eq(email, expectedResult);
1041 });
1042 };
1044 doTestReadEmail(ICC_USIM_TYPE1_TAG, "email@mozilla.com$#");
1045 doTestReadEmail(ICC_USIM_TYPE2_TAG, "email@mozilla.com");
1046 do_check_eq(record._emailRecordSize, recordSize);
1048 run_next_test();
1049 });
1051 /**
1052 * Verify ICCRecordHelper.updateEmail
1053 */
1054 add_test(function test_update_email() {
1055 const recordSize = 0x20;
1056 const recordNumber = 1;
1057 const fileId = 0x4f50;
1058 const NUM_TESTS = 2;
1059 let worker = newUint8Worker();
1060 let context = worker.ContextPool._contexts[0];
1061 let pduHelper = context.GsmPDUHelper;
1062 let iccHelper = context.ICCPDUHelper;
1063 let ril = context.RIL;
1064 ril.appType = CARD_APPTYPE_USIM;
1065 let recordHelper = context.ICCRecordHelper;
1066 let buf = context.Buf;
1067 let ioHelper = context.ICCIOHelper;
1068 let pbr = {email: {fileId: fileId, fileType: ICC_USIM_TYPE1_TAG},
1069 adn: {sfi: 1}};
1070 let count = 0;
1072 // Override.
1073 ioHelper.updateLinearFixedEF = function(options) {
1074 options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
1075 options.command = ICC_COMMAND_UPDATE_RECORD;
1076 options.p1 = options.recordNumber;
1077 options.p2 = READ_RECORD_ABSOLUTE_MODE;
1078 options.p3 = recordSize;
1079 ril.iccIO(options);
1080 };
1082 function do_test(pbr, expectedEmail, expectedAdnRecordId) {
1083 buf.sendParcel = function() {
1084 count++;
1086 // Request Type.
1087 do_check_eq(this.readInt32(), REQUEST_SIM_IO);
1089 // Token : we don't care
1090 this.readInt32();
1092 // command.
1093 do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
1095 // fileId.
1096 do_check_eq(this.readInt32(), fileId);
1098 // pathId.
1099 do_check_eq(this.readString(),
1100 EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
1102 // p1.
1103 do_check_eq(this.readInt32(), recordNumber);
1105 // p2.
1106 do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
1108 // p3.
1109 do_check_eq(this.readInt32(), recordSize);
1111 // data.
1112 let strLen = this.readInt32();
1113 let email;
1114 if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
1115 email = iccHelper.read8BitUnpackedToString(recordSize);
1116 } else {
1117 email = iccHelper.read8BitUnpackedToString(recordSize - 2);
1118 do_check_eq(pduHelper.readHexOctet(), pbr.adn.sfi);
1119 do_check_eq(pduHelper.readHexOctet(), expectedAdnRecordId);
1120 }
1121 this.readStringDelimiter(strLen);
1122 do_check_eq(email, expectedEmail);
1124 // pin2.
1125 do_check_eq(this.readString(), null);
1127 if (!ril.v5Legacy) {
1128 // AID. Ignore because it's from modem.
1129 this.readInt32();
1130 }
1132 if (count == NUM_TESTS) {
1133 run_next_test();
1134 }
1135 };
1136 recordHelper.updateEmail(pbr, recordNumber, expectedEmail, expectedAdnRecordId);
1137 }
1139 do_test(pbr, "test@mail.com");
1140 pbr.email.fileType = ICC_USIM_TYPE2_TAG;
1141 do_test(pbr, "test@mail.com", 1);
1142 });
1144 /**
1145 * Verify ICCRecordHelper.readANR
1146 */
1147 add_test(function test_read_anr() {
1148 let worker = newUint8Worker();
1149 let context = worker.ContextPool._contexts[0];
1150 let helper = context.GsmPDUHelper;
1151 let record = context.ICCRecordHelper;
1152 let buf = context.Buf;
1153 let io = context.ICCIOHelper;
1154 let recordSize;
1156 io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
1157 let anr_1 = [
1158 0x01, 0x05, 0x81, 0x10, 0x32,
1159 0x54, 0xF6, 0xFF, 0xFF];
1161 // Write data size
1162 buf.writeInt32(anr_1.length * 2);
1164 // Write anr
1165 for (let i = 0; i < anr_1.length; i++) {
1166 helper.writeHexOctet(anr_1[i]);
1167 }
1169 // Write string delimiter
1170 buf.writeStringDelimiter(anr_1.length * 2);
1172 recordSize = anr_1.length;
1173 options.recordSize = recordSize;
1174 if (options.callback) {
1175 options.callback(options);
1176 }
1177 };
1179 function doTestReadAnr(fileType, expectedResult) {
1180 let fileId = 0x4f11;
1181 let recordNumber = 1;
1183 // fileId and recordNumber are dummy arguments.
1184 record.readANR(fileId, fileType, recordNumber, function(anr) {
1185 do_check_eq(anr, expectedResult);
1186 });
1187 };
1189 doTestReadAnr(ICC_USIM_TYPE1_TAG, "0123456");
1190 do_check_eq(record._anrRecordSize, recordSize);
1192 run_next_test();
1193 });
1195 /**
1196 * Verify ICCRecordHelper.updateANR
1197 */
1198 add_test(function test_update_anr() {
1199 const recordSize = 0x20;
1200 const recordNumber = 1;
1201 const fileId = 0x4f11;
1202 const NUM_TESTS = 2;
1203 let worker = newUint8Worker();
1204 let context = worker.ContextPool._contexts[0];
1205 let pduHelper = context.GsmPDUHelper;
1206 let iccHelper = context.ICCPDUHelper;
1207 let ril = context.RIL;
1208 ril.appType = CARD_APPTYPE_USIM;
1209 let recordHelper = context.ICCRecordHelper;
1210 let buf = context.Buf;
1211 let ioHelper = context.ICCIOHelper;
1212 let pbr = {anr0: {fileId: fileId, fileType: ICC_USIM_TYPE1_TAG},
1213 adn: {sfi: 1}};
1214 let count = 0;
1216 // Override.
1217 ioHelper.updateLinearFixedEF = function(options) {
1218 options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
1219 options.command = ICC_COMMAND_UPDATE_RECORD;
1220 options.p1 = options.recordNumber;
1221 options.p2 = READ_RECORD_ABSOLUTE_MODE;
1222 options.p3 = recordSize;
1223 ril.iccIO(options);
1224 };
1226 function do_test(pbr, expectedANR, expectedAdnRecordId) {
1227 buf.sendParcel = function() {
1228 count++;
1230 // Request Type.
1231 do_check_eq(this.readInt32(), REQUEST_SIM_IO);
1233 // Token : we don't care
1234 this.readInt32();
1236 // command.
1237 do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
1239 // fileId.
1240 do_check_eq(this.readInt32(), fileId);
1242 // pathId.
1243 do_check_eq(this.readString(),
1244 EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
1246 // p1.
1247 do_check_eq(this.readInt32(), recordNumber);
1249 // p2.
1250 do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
1252 // p3.
1253 do_check_eq(this.readInt32(), recordSize);
1255 // data.
1256 let strLen = this.readInt32();
1257 // EF_AAS, ignore.
1258 pduHelper.readHexOctet();
1259 do_check_eq(iccHelper.readNumberWithLength(), expectedANR);
1260 // EF_CCP, ignore.
1261 pduHelper.readHexOctet();
1262 // EF_EXT1, ignore.
1263 pduHelper.readHexOctet();
1264 if (pbr.anr0.fileType === ICC_USIM_TYPE2_TAG) {
1265 do_check_eq(pduHelper.readHexOctet(), pbr.adn.sfi);
1266 do_check_eq(pduHelper.readHexOctet(), expectedAdnRecordId);
1267 }
1268 this.readStringDelimiter(strLen);
1270 // pin2.
1271 do_check_eq(this.readString(), null);
1273 if (!ril.v5Legacy) {
1274 // AID. Ignore because it's from modem.
1275 this.readInt32();
1276 }
1278 if (count == NUM_TESTS) {
1279 run_next_test();
1280 }
1281 };
1282 recordHelper.updateANR(pbr, recordNumber, expectedANR, expectedAdnRecordId);
1283 }
1285 do_test(pbr, "+123456789");
1286 pbr.anr0.fileType = ICC_USIM_TYPE2_TAG;
1287 do_test(pbr, "123456789", 1);
1288 });
1290 /**
1291 * Verify ICCRecordHelper.readIAP
1292 */
1293 add_test(function test_read_iap() {
1294 let worker = newUint8Worker();
1295 let context = worker.ContextPool._contexts[0];
1296 let helper = context.GsmPDUHelper;
1297 let record = context.ICCRecordHelper;
1298 let buf = context.Buf;
1299 let io = context.ICCIOHelper;
1300 let recordSize;
1302 io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
1303 let iap_1 = [0x01, 0x02];
1305 // Write data size/
1306 buf.writeInt32(iap_1.length * 2);
1308 // Write iap.
1309 for (let i = 0; i < iap_1.length; i++) {
1310 helper.writeHexOctet(iap_1[i]);
1311 }
1313 // Write string delimiter.
1314 buf.writeStringDelimiter(iap_1.length * 2);
1316 recordSize = iap_1.length;
1317 options.recordSize = recordSize;
1318 if (options.callback) {
1319 options.callback(options);
1320 }
1321 };
1323 function doTestReadIAP(expectedIAP) {
1324 const fileId = 0x4f17;
1325 const recordNumber = 1;
1327 let successCb = function successCb(iap) {
1328 for (let i = 0; i < iap.length; i++) {
1329 do_check_eq(expectedIAP[i], iap[i]);
1330 }
1331 run_next_test();
1332 }.bind(this);
1334 let errorCb = function errorCb(errorMsg) {
1335 do_print(errorMsg);
1336 do_check_true(false);
1337 run_next_test();
1338 }.bind(this);
1340 record.readIAP(fileId, recordNumber, successCb, errorCb);
1341 };
1343 doTestReadIAP([1, 2]);
1344 });
1346 /**
1347 * Verify ICCRecordHelper.updateIAP
1348 */
1349 add_test(function test_update_iap() {
1350 const recordSize = 2;
1351 const recordNumber = 1;
1352 const fileId = 0x4f17;
1353 let worker = newUint8Worker();
1354 let context = worker.ContextPool._contexts[0];
1355 let pduHelper = context.GsmPDUHelper;
1356 let ril = context.RIL;
1357 ril.appType = CARD_APPTYPE_USIM;
1358 let recordHelper = context.ICCRecordHelper;
1359 let buf = context.Buf;
1360 let ioHelper = context.ICCIOHelper;
1361 let count = 0;
1363 // Override.
1364 ioHelper.updateLinearFixedEF = function(options) {
1365 options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
1366 options.command = ICC_COMMAND_UPDATE_RECORD;
1367 options.p1 = options.recordNumber;
1368 options.p2 = READ_RECORD_ABSOLUTE_MODE;
1369 options.p3 = recordSize;
1370 ril.iccIO(options);
1371 };
1373 function do_test(expectedIAP) {
1374 buf.sendParcel = function() {
1375 // Request Type.
1376 do_check_eq(this.readInt32(), REQUEST_SIM_IO);
1378 // Token : we don't care
1379 this.readInt32();
1381 // command.
1382 do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
1384 // fileId.
1385 do_check_eq(this.readInt32(), fileId);
1387 // pathId.
1388 do_check_eq(this.readString(),
1389 EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
1391 // p1.
1392 do_check_eq(this.readInt32(), recordNumber);
1394 // p2.
1395 do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
1397 // p3.
1398 do_check_eq(this.readInt32(), recordSize);
1400 // data.
1401 let strLen = this.readInt32();
1402 for (let i = 0; i < recordSize; i++) {
1403 do_check_eq(expectedIAP[i], pduHelper.readHexOctet());
1404 }
1405 this.readStringDelimiter(strLen);
1407 // pin2.
1408 do_check_eq(this.readString(), null);
1410 if (!ril.v5Legacy) {
1411 // AID. Ignore because it's from modem.
1412 this.readInt32();
1413 }
1415 run_next_test();
1416 };
1417 recordHelper.updateIAP(fileId, recordNumber, expectedIAP);
1418 }
1420 do_test([1, 2]);
1421 });
1423 /**
1424 * Verify ICCRecordHelper.updateADNLike.
1425 */
1426 add_test(function test_update_adn_like() {
1427 let worker = newUint8Worker();
1428 let context = worker.ContextPool._contexts[0];
1429 let ril = context.RIL;
1430 let record = context.ICCRecordHelper;
1431 let io = context.ICCIOHelper;
1432 let pdu = context.ICCPDUHelper;
1433 let buf = context.Buf;
1435 ril.appType = CARD_APPTYPE_SIM;
1436 const recordSize = 0x20;
1437 let fileId;
1439 // Override.
1440 io.updateLinearFixedEF = function(options) {
1441 options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
1442 options.command = ICC_COMMAND_UPDATE_RECORD;
1443 options.p1 = options.recordNumber;
1444 options.p2 = READ_RECORD_ABSOLUTE_MODE;
1445 options.p3 = recordSize;
1446 ril.iccIO(options);
1447 };
1449 buf.sendParcel = function() {
1450 // Request Type.
1451 do_check_eq(this.readInt32(), REQUEST_SIM_IO);
1453 // Token : we don't care
1454 this.readInt32();
1456 // command.
1457 do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
1459 // fileId.
1460 do_check_eq(this.readInt32(), fileId);
1462 // pathId.
1463 do_check_eq(this.readString(), EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
1465 // p1.
1466 do_check_eq(this.readInt32(), 1);
1468 // p2.
1469 do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
1471 // p3.
1472 do_check_eq(this.readInt32(), 0x20);
1474 // data.
1475 let contact = pdu.readAlphaIdDiallingNumber(0x20);
1476 do_check_eq(contact.alphaId, "test");
1477 do_check_eq(contact.number, "123456");
1479 // pin2.
1480 if (fileId == ICC_EF_ADN) {
1481 do_check_eq(this.readString(), null);
1482 } else {
1483 do_check_eq(this.readString(), "1111");
1484 }
1486 if (!ril.v5Legacy) {
1487 // AID. Ignore because it's from modem.
1488 this.readInt32();
1489 }
1491 if (fileId == ICC_EF_FDN) {
1492 run_next_test();
1493 }
1494 };
1496 fileId = ICC_EF_ADN;
1497 record.updateADNLike(fileId,
1498 {recordId: 1, alphaId: "test", number: "123456"});
1500 fileId = ICC_EF_FDN;
1501 record.updateADNLike(fileId,
1502 {recordId: 1, alphaId: "test", number: "123456"},
1503 "1111");
1504 });
1506 /**
1507 * Verify ICCRecordHelper.findFreeRecordId.
1508 */
1509 add_test(function test_find_free_record_id() {
1510 let worker = newUint8Worker();
1511 let context = worker.ContextPool._contexts[0];
1512 let pduHelper = context.GsmPDUHelper;
1513 let recordHelper = context.ICCRecordHelper;
1514 let buf = context.Buf;
1515 let io = context.ICCIOHelper;
1517 function writeRecord (record) {
1518 // Write data size
1519 buf.writeInt32(record.length * 2);
1521 for (let i = 0; i < record.length; i++) {
1522 pduHelper.writeHexOctet(record[i]);
1523 }
1525 // Write string delimiter
1526 buf.writeStringDelimiter(record.length * 2);
1527 }
1529 io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
1530 // Some random data.
1531 let record = [0x12, 0x34, 0x56, 0x78, 0x90];
1532 options.p1 = 1;
1533 options.totalRecords = 2;
1534 writeRecord(record);
1535 if (options.callback) {
1536 options.callback(options);
1537 }
1538 };
1540 io.loadNextRecord = function fakeLoadNextRecord(options) {
1541 // Unused bytes.
1542 let record = [0xff, 0xff, 0xff, 0xff, 0xff];
1543 options.p1++;
1544 writeRecord(record);
1545 if (options.callback) {
1546 options.callback(options);
1547 }
1548 };
1550 let fileId = 0x0000; // Dummy.
1551 recordHelper.findFreeRecordId(
1552 fileId,
1553 function(recordId) {
1554 do_check_eq(recordId, 2);
1555 run_next_test();
1556 }.bind(this),
1557 function(errorMsg) {
1558 do_print(errorMsg);
1559 do_check_true(false);
1560 run_next_test();
1561 }.bind(this));
1562 });
1564 /**
1565 * Verify ICCContactHelper.readICCContacts
1566 */
1567 add_test(function test_read_icc_contacts() {
1568 let worker = newUint8Worker();
1569 let context = worker.ContextPool._contexts[0];
1570 let record = context.ICCRecordHelper;
1571 let contactHelper = context.ICCContactHelper;
1572 let ril = context.RIL;
1574 function do_test(aSimType, aContactType, aExpectedContact, aEnhancedPhoneBook) {
1575 ril.appType = aSimType;
1576 ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
1577 ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ?
1578 [0x0, 0x0C, 0x0, 0x0, 0x0]:
1579 [0x0, 0x00, 0x0, 0x0, 0x0];
1581 // Override some functions to test.
1582 contactHelper.getContactFieldRecordId = function(pbr, contact, field, onsuccess, onerror) {
1583 onsuccess(1);
1584 };
1586 record.readPBR = function readPBR(onsuccess, onerror) {
1587 onsuccess([{adn:{fileId: 0x6f3a}, email: {}, anr0: {}}]);
1588 };
1590 record.readADNLike = function readADNLike(fileId, onsuccess, onerror) {
1591 onsuccess([{recordId: 1, alphaId: "name", number: "111111"}])
1592 };
1594 record.readEmail = function readEmail(fileId, fileType, recordNumber, onsuccess, onerror) {
1595 onsuccess("hello@mail.com");
1596 };
1598 record.readANR = function readANR(fileId, fileType, recordNumber, onsuccess, onerror) {
1599 onsuccess("123456");
1600 };
1602 let onsuccess = function onsuccess(contacts) {
1603 let contact = contacts[0];
1604 for (let key in contact) {
1605 do_print("check " + key);
1606 if (Array.isArray(contact[key])) {
1607 do_check_eq(contact[key][0], aExpectedContact[key]);
1608 } else {
1609 do_check_eq(contact[key], aExpectedContact[key]);
1610 }
1611 }
1612 };
1614 let onerror = function onerror(errorMsg) {
1615 do_print("readICCContacts failed: " + errorMsg);
1616 do_check_true(false);
1617 };
1619 contactHelper.readICCContacts(aSimType, aContactType, onsuccess, onerror);
1620 }
1622 let expectedContact1 = {
1623 pbrIndex: 0,
1624 recordId: 1,
1625 alphaId: "name",
1626 number: "111111"
1627 };
1629 let expectedContact2 = {
1630 pbrIndex: 0,
1631 recordId: 1,
1632 alphaId: "name",
1633 number: "111111",
1634 email: "hello@mail.com",
1635 anr: "123456"
1636 };
1638 // SIM
1639 do_print("Test read SIM adn contacts");
1640 do_test(CARD_APPTYPE_SIM, "adn", expectedContact1);
1642 do_print("Test read SIM fdn contacts");
1643 do_test(CARD_APPTYPE_SIM, "fdn", expectedContact1);
1645 // USIM
1646 do_print("Test read USIM adn contacts");
1647 do_test(CARD_APPTYPE_USIM, "adn", expectedContact2);
1649 do_print("Test read USIM fdn contacts");
1650 do_test(CARD_APPTYPE_USIM, "fdn", expectedContact1);
1652 // RUIM
1653 do_print("Test read RUIM adn contacts");
1654 do_test(CARD_APPTYPE_RUIM, "adn", expectedContact1);
1656 do_print("Test read RUIM fdn contacts");
1657 do_test(CARD_APPTYPE_RUIM, "fdn", expectedContact1);
1659 // RUIM with enhanced phone book
1660 do_print("Test read RUIM adn contacts with enhanced phone book");
1661 do_test(CARD_APPTYPE_RUIM, "adn", expectedContact2, true);
1663 do_print("Test read RUIM fdn contacts with enhanced phone book");
1664 do_test(CARD_APPTYPE_RUIM, "fdn", expectedContact1, true);
1666 run_next_test();
1667 });
1669 /**
1670 * Verify ICCContactHelper.updateICCContact with appType is CARD_APPTYPE_USIM.
1671 */
1672 add_test(function test_update_icc_contact() {
1673 const ADN_RECORD_ID = 100;
1674 const ADN_SFI = 1;
1675 const IAP_FILE_ID = 0x4f17;
1676 const EMAIL_FILE_ID = 0x4f50;
1677 const EMAIL_RECORD_ID = 20;
1678 const ANR0_FILE_ID = 0x4f11;
1679 const ANR0_RECORD_ID = 30;
1681 let worker = newUint8Worker();
1682 let context = worker.ContextPool._contexts[0];
1683 let recordHelper = context.ICCRecordHelper;
1684 let contactHelper = context.ICCContactHelper;
1685 let ril = context.RIL;
1687 function do_test(aSimType, aContactType, aContact, aPin2, aFileType, aHaveIapIndex, aEnhancedPhoneBook) {
1688 ril.appType = aSimType;
1689 ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
1690 ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ? [0x0, 0x0C, 0x0, 0x0, 0x0]
1691 : [0x0, 0x00, 0x0, 0x0, 0x0];
1693 recordHelper.readPBR = function(onsuccess, onerror) {
1694 if (aFileType === ICC_USIM_TYPE1_TAG) {
1695 onsuccess([{
1696 adn: {fileId: ICC_EF_ADN},
1697 email: {fileId: EMAIL_FILE_ID,
1698 fileType: ICC_USIM_TYPE1_TAG},
1699 anr0: {fileId: ANR0_FILE_ID,
1700 fileType: ICC_USIM_TYPE1_TAG}
1701 }]);
1702 } else if (aFileType === ICC_USIM_TYPE2_TAG) {
1703 onsuccess([{
1704 adn: {fileId: ICC_EF_ADN,
1705 sfi: ADN_SFI},
1706 iap: {fileId: IAP_FILE_ID},
1707 email: {fileId: EMAIL_FILE_ID,
1708 fileType: ICC_USIM_TYPE2_TAG,
1709 indexInIAP: 0},
1710 anr0: {fileId: ANR0_FILE_ID,
1711 fileType: ICC_USIM_TYPE2_TAG,
1712 indexInIAP: 1}
1713 }]);
1714 }
1715 };
1717 recordHelper.updateADNLike = function(fileId, contact, pin2, onsuccess, onerror) {
1718 if (aContactType === "fdn") {
1719 do_check_eq(fileId, ICC_EF_FDN);
1720 } else if (aContactType === "adn") {
1721 do_check_eq(fileId, ICC_EF_ADN);
1722 }
1723 do_check_eq(pin2, aPin2);
1724 do_check_eq(contact.alphaId, aContact.alphaId);
1725 do_check_eq(contact.number, aContact.number);
1726 onsuccess();
1727 };
1729 recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
1730 do_check_eq(fileId, IAP_FILE_ID);
1731 do_check_eq(recordNumber, ADN_RECORD_ID);
1732 onsuccess((aHaveIapIndex) ? [EMAIL_RECORD_ID, ANR0_RECORD_ID]
1733 : [0xff, 0xff]);
1734 };
1736 recordHelper.updateIAP = function(fileId, recordNumber, iap, onsuccess, onerror) {
1737 do_check_eq(fileId, IAP_FILE_ID);
1738 do_check_eq(recordNumber, ADN_RECORD_ID);
1739 onsuccess();
1740 };
1742 recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
1743 do_check_eq(pbr.email.fileId, EMAIL_FILE_ID);
1744 if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
1745 do_check_eq(recordNumber, ADN_RECORD_ID);
1746 } else if (pbr.email.fileType === ICC_USIM_TYPE2_TAG) {
1747 do_check_eq(recordNumber, EMAIL_RECORD_ID);
1748 }
1749 do_check_eq(email, aContact.email);
1750 onsuccess();
1751 };
1753 recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
1754 do_check_eq(pbr.anr0.fileId, ANR0_FILE_ID);
1755 if (pbr.anr0.fileType === ICC_USIM_TYPE1_TAG) {
1756 do_check_eq(recordNumber, ADN_RECORD_ID);
1757 } else if (pbr.anr0.fileType === ICC_USIM_TYPE2_TAG) {
1758 do_check_eq(recordNumber, ANR0_RECORD_ID);
1759 }
1760 if (Array.isArray(aContact.anr)) {
1761 do_check_eq(number, aContact.anr[0]);
1762 }
1763 onsuccess();
1764 };
1766 recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
1767 let recordId = 0;
1768 if (fileId === EMAIL_FILE_ID) {
1769 recordId = EMAIL_RECORD_ID;
1770 } else if (fileId === ANR0_FILE_ID) {
1771 recordId = ANR0_RECORD_ID;
1772 }
1773 onsuccess(recordId);
1774 };
1776 let isSuccess = false;
1777 let onsuccess = function onsuccess() {
1778 do_print("updateICCContact success");
1779 isSuccess = true;
1780 };
1782 let onerror = function onerror(errorMsg) {
1783 do_print("updateICCContact failed: " + errorMsg);
1784 };
1786 contactHelper.updateICCContact(aSimType, aContactType, aContact, aPin2, onsuccess, onerror);
1787 do_check_true(isSuccess);
1788 }
1790 let contacts = [
1791 {
1792 pbrIndex: 0,
1793 recordId: ADN_RECORD_ID,
1794 alphaId: "test",
1795 number: "123456",
1796 email: "test@mail.com",
1797 anr: ["+654321"]
1798 },
1799 // a contact without email and anr.
1800 {
1801 pbrIndex: 0,
1802 recordId: ADN_RECORD_ID,
1803 alphaId: "test2",
1804 number: "123456",
1805 },
1806 // a contact with email but no anr.
1807 {
1808 pbrIndex: 0,
1809 recordId: ADN_RECORD_ID,
1810 alphaId: "test3",
1811 number: "123456",
1812 email: "test@mail.com"
1813 },
1814 // a contact with anr but no email.
1815 {
1816 pbrIndex: 0,
1817 recordId: ADN_RECORD_ID,
1818 alphaId: "test4",
1819 number: "123456",
1820 anr: ["+654321"]
1821 }];
1823 for (let i = 0; i < contacts.length; i++) {
1824 let contact = contacts[i];
1825 // SIM
1826 do_print("Test update SIM adn contacts");
1827 do_test(CARD_APPTYPE_SIM, "adn", contact);
1829 do_print("Test update SIM fdn contacts");
1830 do_test(CARD_APPTYPE_SIM, "fdn", contact, "1234");
1832 // USIM
1833 do_print("Test update USIM adn contacts");
1834 do_test(CARD_APPTYPE_USIM, "adn", contact, null, ICC_USIM_TYPE1_TAG);
1835 do_test(CARD_APPTYPE_USIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, true);
1836 do_test(CARD_APPTYPE_USIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, false);
1838 do_print("Test update USIM fdn contacts");
1839 do_test(CARD_APPTYPE_USIM, "fdn", contact, "1234");
1841 // RUIM
1842 do_print("Test update RUIM adn contacts");
1843 do_test(CARD_APPTYPE_RUIM, "adn", contact);
1845 do_print("Test update RUIM fdn contacts");
1846 do_test(CARD_APPTYPE_RUIM, "fdn", contact, "1234");
1848 // RUIM with enhanced phone book
1849 do_print("Test update RUIM adn contacts with enhanced phone book");
1850 do_test(CARD_APPTYPE_RUIM, "adn", contact, null, ICC_USIM_TYPE1_TAG, null, true);
1851 do_test(CARD_APPTYPE_RUIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, true, true);
1852 do_test(CARD_APPTYPE_RUIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, false, true);
1854 do_print("Test update RUIM fdn contacts with enhanced phone book");
1855 do_test(CARD_APPTYPE_RUIM, "fdn", contact, "1234", null, true);
1856 }
1858 run_next_test();
1859 });
1861 /**
1862 * Verify updateICCContact with removal of anr and email with File Type 1.
1863 */
1864 add_test(function test_update_icc_contact_with_remove_type1_attr() {
1865 const ADN_RECORD_ID = 100;
1866 const IAP_FILE_ID = 0x4f17;
1867 const EMAIL_FILE_ID = 0x4f50;
1868 const EMAIL_RECORD_ID = 20;
1869 const ANR0_FILE_ID = 0x4f11;
1870 const ANR0_RECORD_ID = 30;
1872 let worker = newUint8Worker();
1873 let context = worker.ContextPool._contexts[0];
1874 let recordHelper = context.ICCRecordHelper;
1875 let contactHelper = context.ICCContactHelper;
1877 recordHelper.updateADNLike = function(fileId, contact, pin2, onsuccess, onerror) {
1878 onsuccess();
1879 };
1881 let contact = {
1882 pbrIndex: 0,
1883 recordId: ADN_RECORD_ID,
1884 alphaId: "test2",
1885 number: "123456",
1886 };
1888 recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
1889 onsuccess([EMAIL_RECORD_ID, ANR0_RECORD_ID]);
1890 };
1892 recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
1893 do_check_true(email == null);
1894 onsuccess();
1895 };
1897 recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
1898 do_check_true(number == null);
1899 onsuccess();
1900 };
1902 function do_test(type) {
1903 recordHelper.readPBR = function(onsuccess, onerror) {
1904 if (type == ICC_USIM_TYPE1_TAG) {
1905 onsuccess([{
1906 adn: {fileId: ICC_EF_ADN},
1907 email: {fileId: EMAIL_FILE_ID,
1908 fileType: ICC_USIM_TYPE1_TAG},
1909 anr0: {fileId: ANR0_FILE_ID,
1910 fileType: ICC_USIM_TYPE1_TAG}}]);
1911 } else {
1912 onsuccess([{
1913 adn: {fileId: ICC_EF_ADN},
1914 iap: {fileId: IAP_FILE_ID},
1915 email: {fileId: EMAIL_FILE_ID,
1916 fileType: ICC_USIM_TYPE2_TAG,
1917 indexInIAP: 0},
1918 anr0: {fileId: ANR0_FILE_ID,
1919 fileType: ICC_USIM_TYPE2_TAG,
1920 indexInIAP: 1}}]);
1921 }
1922 };
1924 let successCb = function() {
1925 do_check_true(true);
1926 };
1928 let errorCb = function(errorMsg) {
1929 do_print(errorMsg);
1930 do_check_true(false);
1931 };
1933 contactHelper.updateICCContact(CARD_APPTYPE_USIM, "adn", contact, null, successCb, errorCb);
1934 }
1936 do_test(ICC_USIM_TYPE1_TAG);
1937 do_test(ICC_USIM_TYPE2_TAG);
1939 run_next_test();
1940 });
1942 /**
1943 * Verify ICCContactHelper.findFreeICCContact in SIM
1944 */
1945 add_test(function test_find_free_icc_contact_sim() {
1946 let worker = newUint8Worker();
1947 let context = worker.ContextPool._contexts[0];
1948 let recordHelper = context.ICCRecordHelper;
1949 let contactHelper = context.ICCContactHelper;
1950 // Correct record Id starts with 1, so put a null element at index 0.
1951 let records = [null];
1952 const MAX_RECORDS = 3;
1953 const PBR_INDEX = 0;
1955 recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
1956 if (records.length > MAX_RECORDS) {
1957 onerror("No free record found.");
1958 return;
1959 }
1961 onsuccess(records.length);
1962 };
1964 let successCb = function(pbrIndex, recordId) {
1965 do_check_eq(pbrIndex, PBR_INDEX);
1966 records[recordId] = {};
1967 };
1969 let errorCb = function(errorMsg) {
1970 do_print(errorMsg);
1971 do_check_true(false);
1972 };
1974 for (let i = 0; i < MAX_RECORDS; i++) {
1975 contactHelper.findFreeICCContact(CARD_APPTYPE_SIM, "adn", successCb, errorCb);
1976 }
1977 // The 1st element, records[0], is null.
1978 do_check_eq(records.length - 1, MAX_RECORDS);
1980 // Now the EF is full, so finding a free one should result failure.
1981 successCb = function(pbrIndex, recordId) {
1982 do_check_true(false);
1983 };
1985 errorCb = function(errorMsg) {
1986 do_check_true(errorMsg === "No free record found.");
1987 };
1988 contactHelper.findFreeICCContact(CARD_APPTYPE_SIM, "adn", successCb, errorCb);
1990 run_next_test();
1991 });
1993 /**
1994 * Verify ICCContactHelper.findFreeICCContact in USIM
1995 */
1996 add_test(function test_find_free_icc_contact_usim() {
1997 let worker = newUint8Worker();
1998 let context = worker.ContextPool._contexts[0];
1999 let recordHelper = context.ICCRecordHelper;
2000 let contactHelper = context.ICCContactHelper;
2001 const ADN1_FILE_ID = 0x6f3a;
2002 const ADN2_FILE_ID = 0x6f3b;
2003 const MAX_RECORDS = 3;
2005 // The adn in the first phonebook set has already two records, which means
2006 // only 1 free record remained.
2007 let pbrs = [{adn: {fileId: ADN1_FILE_ID, records: [null, {}, {}]}},
2008 {adn: {fileId: ADN2_FILE_ID, records: [null]}}];
2010 recordHelper.readPBR = function readPBR(onsuccess, onerror) {
2011 onsuccess(pbrs);
2012 };
2014 recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
2015 let pbr = (fileId == ADN1_FILE_ID ? pbrs[0]: pbrs[1]);
2016 if (pbr.adn.records.length > MAX_RECORDS) {
2017 onerror("No free record found.");
2018 return;
2019 }
2021 onsuccess(pbr.adn.records.length);
2022 };
2024 let successCb = function(pbrIndex, recordId) {
2025 do_check_eq(pbrIndex, 0);
2026 pbrs[pbrIndex].adn.records[recordId] = {};
2027 };
2029 let errorCb = function(errorMsg) {
2030 do_check_true(false);
2031 };
2033 contactHelper.findFreeICCContact(CARD_APPTYPE_USIM, "adn", successCb, errorCb);
2035 // Now the EF_ADN in the 1st phonebook set is full, so the next free contact
2036 // will come from the 2nd phonebook set.
2037 successCb = function(pbrIndex, recordId) {
2038 do_check_eq(pbrIndex, 1);
2039 do_check_eq(recordId, 1);
2040 }
2041 contactHelper.findFreeICCContact(CARD_APPTYPE_USIM, "adn", successCb, errorCb);
2043 run_next_test();
2044 });
2046 /**
2047 * Test error message returned in onerror for readICCContacts.
2048 */
2049 add_test(function test_error_message_read_icc_contact () {
2050 let worker = newUint8Worker();
2051 let context = worker.ContextPool._contexts[0];
2052 let ril = context.RIL;
2054 function do_test(options, expectedErrorMsg) {
2055 ril.sendChromeMessage = function(message) {
2056 do_check_eq(message.errorMsg, expectedErrorMsg);
2057 }
2058 ril.readICCContacts(options);
2059 }
2061 // Error 1, didn't specify correct contactType.
2062 do_test({}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
2064 // Error 2, specifying a non-supported contactType.
2065 ril.appType = CARD_APPTYPE_USIM;
2066 do_test({contactType: "sdn"}, CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
2068 // Error 3, suppose we update the supported PBR fields in USIM_PBR_FIELDS,
2069 // but forget to add implemenetations for it.
2070 USIM_PBR_FIELDS.push("pbc");
2071 do_test({contactType: "adn"}, CONTACT_ERR_FIELD_NOT_SUPPORTED);
2073 run_next_test();
2074 });
2076 /**
2077 * Test error message returned in onerror for updateICCContact.
2078 */
2079 add_test(function test_error_message_update_icc_contact() {
2080 let worker = newUint8Worker();
2081 let context = worker.ContextPool._contexts[0];
2082 let ril = context.RIL;
2084 const ICCID = "123456789";
2085 ril.iccInfo.iccid = ICCID;
2087 function do_test(options, expectedErrorMsg) {
2088 ril.sendChromeMessage = function(message) {
2089 do_check_eq(message.errorMsg, expectedErrorMsg);
2090 }
2091 ril.updateICCContact(options);
2092 }
2094 // Error 1, didn't specify correct contactType.
2095 do_test({}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
2097 // Error 2, specifying a correct contactType, but without providing 'contact'.
2098 do_test({contactType: "adn"}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
2100 // Error 3, specifying a non-supported contactType.
2101 ril.appType = CARD_APPTYPE_USIM;
2102 do_test({contactType: "sdn", contact: {}}, CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
2104 // Error 4, without supplying pin2.
2105 do_test({contactType: "fdn", contact: {contactId: ICCID + "1"}}, GECKO_ERROR_SIM_PIN2);
2107 // Error 5, No free record found in EF_ADN.
2108 let record = context.ICCRecordHelper;
2109 record.readPBR = function(onsuccess, onerror) {
2110 onsuccess([{adn: {fileId: 0x4f3a}}]);
2111 };
2113 let io = context.ICCIOHelper;
2114 io.loadLinearFixedEF = function(options) {
2115 options.totalRecords = 1;
2116 options.p1 = 1;
2117 options.callback(options);
2118 };
2120 do_test({contactType: "adn", contact: {}}, CONTACT_ERR_NO_FREE_RECORD_FOUND);
2122 // Error 6, ICC IO Error.
2123 io.loadLinearFixedEF = function(options) {
2124 ril[REQUEST_SIM_IO](0, {rilRequestError: ERROR_GENERIC_FAILURE});
2125 };
2126 do_test({contactType: "adn", contact: {contactId: ICCID + "1"}},
2127 GECKO_ERROR_GENERIC_FAILURE);
2129 // Error 7, suppose we update the supported PBR fields in USIM_PBR_FIELDS,
2130 // but forget to add implemenetations for it.
2131 USIM_PBR_FIELDS.push("pbc");
2132 do_test({contactType: "adn", contact: {contactId: ICCID + "1"}},
2133 CONTACT_ERR_FIELD_NOT_SUPPORTED);
2135 // Error 8, EF_PBR doesn't exist.
2136 record.readPBR = function(onsuccess, onerror) {
2137 onsuccess([]);
2138 };
2140 do_test({contactType: "adn", contact: {contactId: ICCID + "1"}},
2141 CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
2143 run_next_test();
2144 });
2146 add_test(function test_process_icc_io_error() {
2147 let worker = newUint8Worker();
2148 let context = worker.ContextPool._contexts[0];
2149 let ioHelper = context.ICCIOHelper;
2151 function do_test(errorCode, expectedErrorMsg) {
2152 let called = false;
2153 function errorCb(errorMsg) {
2154 called = true;
2155 do_check_eq(errorMsg, expectedErrorMsg);
2156 }
2158 ioHelper.processICCIOError({rilRequestError: errorCode,
2159 fileId: 0xffff,
2160 command: 0xff,
2161 sw1: 0xff,
2162 sw2: 0xff,
2163 onerror: errorCb});
2164 do_check_true(called);
2165 }
2167 for (let i = 0; i < ERROR_REJECTED_BY_REMOTE + 1; i++) {
2168 do_test(i, RIL_ERROR_TO_GECKO_ERROR[i]);
2169 }
2171 run_next_test();
2172 });
2174 add_test(function test_personalization_state() {
2175 let worker = newUint8Worker();
2176 let context = worker.ContextPool._contexts[0];
2177 let ril = context.RIL;
2179 context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
2181 function testPersonalization(isCdma, cardPersoState, geckoCardState) {
2182 let iccStatus = {
2183 cardState: CARD_STATE_PRESENT,
2184 gsmUmtsSubscriptionAppIndex: (!isCdma) ? 0 : -1,
2185 cdmaSubscriptionAppIndex: (isCdma) ? 0 : -1,
2186 apps: [
2187 {
2188 app_state: CARD_APPSTATE_SUBSCRIPTION_PERSO,
2189 perso_substate: cardPersoState
2190 }],
2191 };
2193 ril._isCdma = isCdma;
2194 ril._processICCStatus(iccStatus);
2195 do_check_eq(ril.cardState, geckoCardState);
2196 }
2198 // Test GSM personalization state.
2199 testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK,
2200 GECKO_CARDSTATE_NETWORK_LOCKED);
2201 testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE,
2202 GECKO_CARDSTATE_CORPORATE_LOCKED);
2203 testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
2204 GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED);
2205 testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_PUK,
2206 GECKO_CARDSTATE_NETWORK_PUK_REQUIRED);
2207 testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK,
2208 GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED);
2209 testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
2210 GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED);
2211 testPersonalization(false, CARD_PERSOSUBSTATE_READY,
2212 GECKO_CARDSTATE_PERSONALIZATION_READY);
2214 // Test CDMA personalization state.
2215 testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1,
2216 GECKO_CARDSTATE_NETWORK1_LOCKED);
2217 testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2,
2218 GECKO_CARDSTATE_NETWORK2_LOCKED);
2219 testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD,
2220 GECKO_CARDSTATE_HRPD_NETWORK_LOCKED);
2221 testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE,
2222 GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED);
2223 testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
2224 GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED);
2225 testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM,
2226 GECKO_CARDSTATE_RUIM_LOCKED);
2227 testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK,
2228 GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED);
2229 testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK,
2230 GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED);
2231 testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD_PUK,
2232 GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED);
2233 testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK,
2234 GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED);
2235 testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
2236 GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
2237 testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM_PUK,
2238 GECKO_CARDSTATE_RUIM_PUK_REQUIRED);
2240 run_next_test();
2241 });
2243 /**
2244 * Verify SIM app_state in _processICCStatus
2245 */
2246 add_test(function test_card_app_state() {
2247 let worker = newUint8Worker();
2248 let context = worker.ContextPool._contexts[0];
2249 let ril = context.RIL;
2251 context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
2253 function testCardAppState(cardAppState, geckoCardState) {
2254 let iccStatus = {
2255 cardState: CARD_STATE_PRESENT,
2256 gsmUmtsSubscriptionAppIndex: 0,
2257 apps: [
2258 {
2259 app_state: cardAppState
2260 }],
2261 };
2263 ril._processICCStatus(iccStatus);
2264 do_check_eq(ril.cardState, geckoCardState);
2265 }
2267 testCardAppState(CARD_APPSTATE_ILLEGAL,
2268 GECKO_CARDSTATE_ILLEGAL);
2269 testCardAppState(CARD_APPSTATE_PIN,
2270 GECKO_CARDSTATE_PIN_REQUIRED);
2271 testCardAppState(CARD_APPSTATE_PUK,
2272 GECKO_CARDSTATE_PUK_REQUIRED);
2273 testCardAppState(CARD_APPSTATE_READY,
2274 GECKO_CARDSTATE_READY);
2275 testCardAppState(CARD_APPSTATE_UNKNOWN,
2276 GECKO_CARDSTATE_UNKNOWN);
2277 testCardAppState(CARD_APPSTATE_DETECTED,
2278 GECKO_CARDSTATE_UNKNOWN);
2280 run_next_test();
2281 });
2283 /**
2284 * Verify permanent blocked for ICC.
2285 */
2286 add_test(function test_icc_permanent_blocked() {
2287 let worker = newUint8Worker();
2288 let context = worker.ContextPool._contexts[0];
2289 let ril = context.RIL;
2291 context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
2293 function testPermanentBlocked(pin1_replaced, universalPINState, pin1) {
2294 let iccStatus = {
2295 cardState: CARD_STATE_PRESENT,
2296 gsmUmtsSubscriptionAppIndex: 0,
2297 universalPINState: universalPINState,
2298 apps: [
2299 {
2300 pin1_replaced: pin1_replaced,
2301 pin1: pin1
2302 }]
2303 };
2305 ril._processICCStatus(iccStatus);
2306 do_check_eq(ril.cardState, GECKO_CARDSTATE_PERMANENT_BLOCKED);
2307 }
2309 testPermanentBlocked(1,
2310 CARD_PINSTATE_ENABLED_PERM_BLOCKED,
2311 CARD_PINSTATE_UNKNOWN);
2312 testPermanentBlocked(1,
2313 CARD_PINSTATE_ENABLED_PERM_BLOCKED,
2314 CARD_PINSTATE_ENABLED_PERM_BLOCKED);
2315 testPermanentBlocked(0,
2316 CARD_PINSTATE_UNKNOWN,
2317 CARD_PINSTATE_ENABLED_PERM_BLOCKED);
2319 run_next_test();
2320 });
2322 /**
2323 * Verify iccSetCardLock - Facility Lock.
2324 */
2325 add_test(function test_set_icc_card_lock_facility_lock() {
2326 let worker = newUint8Worker();
2327 let context = worker.ContextPool._contexts[0];
2328 let aid = "123456789";
2329 let ril = context.RIL;
2330 ril.aid = aid;
2331 ril.v5Legacy = false;
2332 let buf = context.Buf;
2334 let GECKO_CARDLOCK_TO_FACILITIY_LOCK = {};
2335 GECKO_CARDLOCK_TO_FACILITIY_LOCK[GECKO_CARDLOCK_PIN] = ICC_CB_FACILITY_SIM;
2336 GECKO_CARDLOCK_TO_FACILITIY_LOCK[GECKO_CARDLOCK_FDN] = ICC_CB_FACILITY_FDN;
2338 let GECKO_CARDLOCK_TO_PASSWORD_TYPE = {};
2339 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_PIN] = "pin";
2340 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_FDN] = "pin2";
2342 const pin = "1234";
2343 const pin2 = "4321";
2344 let GECKO_CARDLOCK_TO_PASSWORD = {};
2345 GECKO_CARDLOCK_TO_PASSWORD[GECKO_CARDLOCK_PIN] = pin;
2346 GECKO_CARDLOCK_TO_PASSWORD[GECKO_CARDLOCK_FDN] = pin2;
2348 const serviceClass = ICC_SERVICE_CLASS_VOICE |
2349 ICC_SERVICE_CLASS_DATA |
2350 ICC_SERVICE_CLASS_FAX;
2352 function do_test(aLock, aPassword, aEnabled) {
2353 buf.sendParcel = function fakeSendParcel () {
2354 // Request Type.
2355 do_check_eq(this.readInt32(), REQUEST_SET_FACILITY_LOCK);
2357 // Token : we don't care
2358 this.readInt32();
2360 let parcel = this.readStringList();
2361 do_check_eq(parcel.length, 5);
2362 do_check_eq(parcel[0], GECKO_CARDLOCK_TO_FACILITIY_LOCK[aLock]);
2363 do_check_eq(parcel[1], aEnabled ? "1" : "0");
2364 do_check_eq(parcel[2], GECKO_CARDLOCK_TO_PASSWORD[aLock]);
2365 do_check_eq(parcel[3], serviceClass.toString());
2366 do_check_eq(parcel[4], aid);
2367 };
2369 let lock = {lockType: aLock,
2370 enabled: aEnabled};
2371 lock[GECKO_CARDLOCK_TO_PASSWORD_TYPE[aLock]] = aPassword;
2373 ril.iccSetCardLock(lock);
2374 }
2376 do_test(GECKO_CARDLOCK_PIN, pin, true);
2377 do_test(GECKO_CARDLOCK_PIN, pin, false);
2378 do_test(GECKO_CARDLOCK_FDN, pin2, true);
2379 do_test(GECKO_CARDLOCK_FDN, pin2, false);
2381 run_next_test();
2382 });
2384 /**
2385 * Verify iccUnlockCardLock.
2386 */
2387 add_test(function test_unlock_card_lock_corporateLocked() {
2388 let worker = newUint8Worker();
2389 let context = worker.ContextPool._contexts[0];
2390 let ril = context.RIL;
2391 let buf = context.Buf;
2392 const pin = "12345678";
2393 const puk = "12345678";
2395 let GECKO_CARDLOCK_TO_PASSWORD_TYPE = {};
2396 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK] = "pin";
2397 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK1] = "pin";
2398 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK2] = "pin";
2399 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_HNCK] = "pin";
2400 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_CCK] = "pin";
2401 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_SPCK] = "pin";
2402 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RCCK] = "pin";
2403 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RSPCK] = "pin";
2404 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK_PUK] = "puk";
2405 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK1_PUK] = "puk";
2406 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK2_PUK] = "puk";
2407 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_HNCK_PUK] = "puk";
2408 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_CCK_PUK] = "puk";
2409 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_SPCK_PUK] = "puk";
2410 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RCCK_PUK] = "puk";
2411 GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RSPCK_PUK] = "puk";
2413 function do_test(aLock, aPassword) {
2414 buf.sendParcel = function fakeSendParcel () {
2415 // Request Type.
2416 do_check_eq(this.readInt32(), REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE);
2418 // Token : we don't care
2419 this.readInt32();
2421 let lockType = GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[aLock];
2422 // Lock Type
2423 do_check_eq(this.readInt32(), lockType);
2425 // Pin/Puk.
2426 do_check_eq(this.readString(), aPassword);
2427 };
2429 let lock = {lockType: aLock};
2430 lock[GECKO_CARDLOCK_TO_PASSWORD_TYPE[aLock]] = aPassword;
2431 ril.iccUnlockCardLock(lock);
2432 }
2434 do_test(GECKO_CARDLOCK_NCK, pin);
2435 do_test(GECKO_CARDLOCK_NCK1, pin);
2436 do_test(GECKO_CARDLOCK_NCK2, pin);
2437 do_test(GECKO_CARDLOCK_HNCK, pin);
2438 do_test(GECKO_CARDLOCK_CCK, pin);
2439 do_test(GECKO_CARDLOCK_SPCK, pin);
2440 do_test(GECKO_CARDLOCK_RCCK, pin);
2441 do_test(GECKO_CARDLOCK_RSPCK, pin);
2442 do_test(GECKO_CARDLOCK_NCK_PUK, puk);
2443 do_test(GECKO_CARDLOCK_NCK1_PUK, puk);
2444 do_test(GECKO_CARDLOCK_NCK2_PUK, puk);
2445 do_test(GECKO_CARDLOCK_HNCK_PUK, puk);
2446 do_test(GECKO_CARDLOCK_CCK_PUK, puk);
2447 do_test(GECKO_CARDLOCK_SPCK_PUK, puk);
2448 do_test(GECKO_CARDLOCK_RCCK_PUK, puk);
2449 do_test(GECKO_CARDLOCK_RSPCK_PUK, puk);
2451 run_next_test();
2452 });
2454 /**
2455 * Verify MCC and MNC parsing
2456 */
2457 add_test(function test_mcc_mnc_parsing() {
2458 let worker = newUint8Worker();
2459 let context = worker.ContextPool._contexts[0];
2460 let helper = context.ICCUtilsHelper;
2462 function do_test(imsi, mncLength, expectedMcc, expectedMnc) {
2463 let result = helper.parseMccMncFromImsi(imsi, mncLength);
2465 if (!imsi) {
2466 do_check_eq(result, null);
2467 return;
2468 }
2470 do_check_eq(result.mcc, expectedMcc);
2471 do_check_eq(result.mnc, expectedMnc);
2472 }
2474 // Test the imsi is null.
2475 do_test(null, null, null, null);
2477 // Test MCC is Taiwan
2478 do_test("466923202422409", 0x02, "466", "92");
2479 do_test("466923202422409", 0x03, "466", "923");
2480 do_test("466923202422409", null, "466", "92");
2482 // Test MCC is US
2483 do_test("310260542718417", 0x02, "310", "26");
2484 do_test("310260542718417", 0x03, "310", "260");
2485 do_test("310260542718417", null, "310", "260");
2487 run_next_test();
2488 });
2490 /**
2491 * Verify reading EF_AD and parsing MCC/MNC
2492 */
2493 add_test(function test_reading_ad_and_parsing_mcc_mnc() {
2494 let worker = newUint8Worker();
2495 let context = worker.ContextPool._contexts[0];
2496 let record = context.SimRecordHelper;
2497 let helper = context.GsmPDUHelper;
2498 let ril = context.RIL;
2499 let buf = context.Buf;
2500 let io = context.ICCIOHelper;
2502 function do_test(mncLengthInEf, imsi, expectedMcc, expectedMnc) {
2503 ril.iccInfoPrivate.imsi = imsi;
2505 io.loadTransparentEF = function fakeLoadTransparentEF(options) {
2506 let ad = [0x00, 0x00, 0x00];
2507 if (mncLengthInEf) {
2508 ad.push(mncLengthInEf);
2509 }
2511 // Write data size
2512 buf.writeInt32(ad.length * 2);
2514 // Write data
2515 for (let i = 0; i < ad.length; i++) {
2516 helper.writeHexOctet(ad[i]);
2517 }
2519 // Write string delimiter
2520 buf.writeStringDelimiter(ad.length * 2);
2522 if (options.callback) {
2523 options.callback(options);
2524 }
2525 };
2527 record.readAD();
2529 do_check_eq(ril.iccInfo.mcc, expectedMcc);
2530 do_check_eq(ril.iccInfo.mnc, expectedMnc);
2531 }
2533 do_test(undefined, "466923202422409", "466", "92" );
2534 do_test(0x03, "466923202422409", "466", "923");
2535 do_test(undefined, "310260542718417", "310", "260");
2536 do_test(0x02, "310260542718417", "310", "26" );
2538 run_next_test();
2539 });
2541 add_test(function test_reading_optional_efs() {
2542 let worker = newUint8Worker();
2543 let context = worker.ContextPool._contexts[0];
2544 let record = context.SimRecordHelper;
2545 let gsmPdu = context.GsmPDUHelper;
2546 let ril = context.RIL;
2547 let buf = context.Buf;
2548 let io = context.ICCIOHelper;
2550 function buildSST(supportedEf) {
2551 let sst = [];
2552 let len = supportedEf.length;
2553 for (let i = 0; i < len; i++) {
2554 let index, bitmask, iccService;
2555 if (ril.appType === CARD_APPTYPE_SIM) {
2556 iccService = GECKO_ICC_SERVICES.sim[supportedEf[i]];
2557 iccService -= 1;
2558 index = Math.floor(iccService / 4);
2559 bitmask = 2 << ((iccService % 4) << 1);
2560 } else if (ril.appType === CARD_APPTYPE_USIM){
2561 iccService = GECKO_ICC_SERVICES.usim[supportedEf[i]];
2562 iccService -= 1;
2563 index = Math.floor(iccService / 8);
2564 bitmask = 1 << ((iccService % 8) << 0);
2565 }
2567 if (sst) {
2568 sst[index] |= bitmask;
2569 }
2570 }
2571 return sst;
2572 }
2574 ril.updateCellBroadcastConfig = function fakeUpdateCellBroadcastConfig() {
2575 // Ignore updateCellBroadcastConfig after reading SST
2576 };
2578 function do_test(sst, supportedEf) {
2579 // Clone supportedEf to local array for testing
2580 let testEf = supportedEf.slice(0);
2582 record.readMSISDN = function fakeReadMSISDN() {
2583 testEf.splice(testEf.indexOf("MSISDN"), 1);
2584 };
2586 record.readMBDN = function fakeReadMBDN() {
2587 testEf.splice(testEf.indexOf("MDN"), 1);
2588 };
2590 record.readMWIS = function fakeReadMWIS() {
2591 testEf.splice(testEf.indexOf("MWIS"), 1);
2592 };
2594 io.loadTransparentEF = function fakeLoadTransparentEF(options) {
2595 // Write data size
2596 buf.writeInt32(sst.length * 2);
2598 // Write data
2599 for (let i = 0; i < sst.length; i++) {
2600 gsmPdu.writeHexOctet(sst[i] || 0);
2601 }
2603 // Write string delimiter
2604 buf.writeStringDelimiter(sst.length * 2);
2606 if (options.callback) {
2607 options.callback(options);
2608 }
2610 if (testEf.length !== 0) {
2611 do_print("Un-handled EF: " + JSON.stringify(testEf));
2612 do_check_true(false);
2613 }
2614 };
2616 record.readSST();
2617 }
2619 // TODO: Add all necessary optional EFs eventually
2620 let supportedEf = ["MSISDN", "MDN", "MWIS"];
2621 ril.appType = CARD_APPTYPE_SIM;
2622 do_test(buildSST(supportedEf), supportedEf);
2623 ril.appType = CARD_APPTYPE_USIM;
2624 do_test(buildSST(supportedEf), supportedEf);
2626 run_next_test();
2627 });
2629 /**
2630 * Verify fetchSimRecords.
2631 */
2632 add_test(function test_fetch_sim_recodes() {
2633 let worker = newWorker();
2634 let context = worker.ContextPool._contexts[0];
2635 let RIL = context.RIL;
2636 let iccRecord = context.ICCRecordHelper;
2637 let simRecord = context.SimRecordHelper;
2639 function testFetchSimRecordes(expectCalled) {
2640 let ifCalled = [];
2642 RIL.getIMSI = function() {
2643 ifCalled.push("getIMSI");
2644 };
2646 simRecord.readAD = function() {
2647 ifCalled.push("readAD");
2648 };
2650 simRecord.readSST = function() {
2651 ifCalled.push("readSST");
2652 };
2654 simRecord.fetchSimRecords();
2656 for (let i = 0; i < expectCalled.length; i++ ) {
2657 if (ifCalled[i] != expectCalled[i]) {
2658 do_print(expectCalled[i] + " is not called.");
2659 do_check_true(false);
2660 }
2661 }
2662 }
2664 let expectCalled = ["getIMSI", "readAD", "readSST"];
2665 testFetchSimRecordes(expectCalled);
2667 run_next_test();
2668 });
2670 add_test(function test_fetch_icc_recodes() {
2671 let worker = newWorker();
2672 let context = worker.ContextPool._contexts[0];
2673 let RIL = context.RIL;
2674 let iccRecord = context.ICCRecordHelper;
2675 let simRecord = context.SimRecordHelper;
2676 let ruimRecord = context.RuimRecordHelper;
2677 let fetchTag = 0x00;
2679 simRecord.fetchSimRecords = function() {
2680 fetchTag = 0x01;
2681 };
2683 ruimRecord.fetchRuimRecords = function() {
2684 fetchTag = 0x02;
2685 };
2687 RIL.appType = CARD_APPTYPE_SIM;
2688 iccRecord.fetchICCRecords();
2689 do_check_eq(fetchTag, 0x01);
2691 RIL.appType = CARD_APPTYPE_RUIM;
2692 iccRecord.fetchICCRecords();
2693 do_check_eq(fetchTag, 0x02);
2695 RIL.appType = CARD_APPTYPE_USIM;
2696 iccRecord.fetchICCRecords();
2697 do_check_eq(fetchTag, 0x01);
2699 run_next_test();
2700 });
2702 /**
2703 * Verify SimRecordHelper.readMWIS
2704 */
2705 add_test(function test_read_mwis() {
2706 let worker = newUint8Worker();
2707 let context = worker.ContextPool._contexts[0];
2708 let helper = context.GsmPDUHelper;
2709 let recordHelper = context.SimRecordHelper;
2710 let buf = context.Buf;
2711 let io = context.ICCIOHelper;
2712 let mwisData;
2713 let postedMessage;
2715 worker.postMessage = function fakePostMessage(message) {
2716 postedMessage = message;
2717 };
2719 io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
2720 if (mwisData) {
2721 // Write data size
2722 buf.writeInt32(mwisData.length * 2);
2724 // Write MWIS
2725 for (let i = 0; i < mwisData.length; i++) {
2726 helper.writeHexOctet(mwisData[i]);
2727 }
2729 // Write string delimiter
2730 buf.writeStringDelimiter(mwisData.length * 2);
2732 options.recordSize = mwisData.length;
2733 if (options.callback) {
2734 options.callback(options);
2735 }
2736 } else {
2737 do_print("mwisData[] is not set.");
2738 }
2739 };
2741 function buildMwisData(isActive, msgCount) {
2742 if (msgCount < 0 || msgCount === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) {
2743 msgCount = 0;
2744 } else if (msgCount > 255) {
2745 msgCount = 255;
2746 }
2748 mwisData = [ (isActive) ? 0x01 : 0x00,
2749 msgCount,
2750 0xFF, 0xFF, 0xFF ];
2751 }
2753 function do_test(isActive, msgCount) {
2754 buildMwisData(isActive, msgCount);
2755 recordHelper.readMWIS();
2757 do_check_eq("iccmwis", postedMessage.rilMessageType);
2758 do_check_eq(isActive, postedMessage.mwi.active);
2759 do_check_eq((isActive) ? msgCount : 0, postedMessage.mwi.msgCount);
2760 }
2762 do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN);
2763 do_test(true, 1);
2764 do_test(true, 255);
2766 do_test(false, 0);
2767 do_test(false, 255); // Test the corner case when mwi is disable with incorrect msgCount.
2769 run_next_test();
2770 });
2772 /**
2773 * Verify SimRecordHelper.updateMWIS
2774 */
2775 add_test(function test_update_mwis() {
2776 let worker = newUint8Worker();
2777 let context = worker.ContextPool._contexts[0];
2778 let pduHelper = context.GsmPDUHelper;
2779 let ril = context.RIL;
2780 ril.appType = CARD_APPTYPE_USIM;
2781 ril.iccInfoPrivate.mwis = [0x00, 0x00, 0x00, 0x00, 0x00];
2782 let recordHelper = context.SimRecordHelper;
2783 let buf = context.Buf;
2784 let ioHelper = context.ICCIOHelper;
2785 let recordSize = ril.iccInfoPrivate.mwis.length;
2786 let recordNum = 1;
2788 ioHelper.updateLinearFixedEF = function(options) {
2789 options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
2790 options.command = ICC_COMMAND_UPDATE_RECORD;
2791 options.p1 = options.recordNumber;
2792 options.p2 = READ_RECORD_ABSOLUTE_MODE;
2793 options.p3 = recordSize;
2794 ril.iccIO(options);
2795 };
2797 function do_test(isActive, count) {
2798 let mwis = ril.iccInfoPrivate.mwis;
2799 let isUpdated = false;
2801 function buildMwisData() {
2802 let result = mwis.slice(0);
2803 result[0] = isActive? (mwis[0] | 0x01) : (mwis[0] & 0xFE);
2804 result[1] = (count === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) ? 0 : count;
2806 return result;
2807 }
2809 buf.sendParcel = function() {
2810 isUpdated = true;
2812 // Request Type.
2813 do_check_eq(this.readInt32(), REQUEST_SIM_IO);
2815 // Token : we don't care
2816 this.readInt32();
2818 // command.
2819 do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
2821 // fileId.
2822 do_check_eq(this.readInt32(), ICC_EF_MWIS);
2824 // pathId.
2825 do_check_eq(this.readString(),
2826 EF_PATH_MF_SIM + ((ril.appType === CARD_APPTYPE_USIM) ? EF_PATH_ADF_USIM : EF_PATH_DF_GSM));
2828 // p1.
2829 do_check_eq(this.readInt32(), recordNum);
2831 // p2.
2832 do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
2834 // p3.
2835 do_check_eq(this.readInt32(), recordSize);
2837 // data.
2838 let strLen = this.readInt32();
2839 do_check_eq(recordSize * 2, strLen);
2840 let expectedMwis = buildMwisData();
2841 for (let i = 0; i < recordSize; i++) {
2842 do_check_eq(expectedMwis[i], pduHelper.readHexOctet());
2843 }
2844 this.readStringDelimiter(strLen);
2846 // pin2.
2847 do_check_eq(this.readString(), null);
2849 if (!ril.v5Legacy) {
2850 // AID. Ignore because it's from modem.
2851 this.readInt32();
2852 }
2853 };
2855 do_check_false(isUpdated);
2857 recordHelper.updateMWIS({ active: isActive,
2858 msgCount: count });
2860 do_check_true((ril.iccInfoPrivate.mwis) ? isUpdated : !isUpdated);
2861 }
2863 do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN);
2864 do_test(true, 1);
2865 do_test(true, 255);
2867 do_test(false, 0);
2869 // Test if Path ID is correct for SIM.
2870 ril.appType = CARD_APPTYPE_SIM;
2871 do_test(false, 0);
2873 // Test if loadLinearFixedEF() is not invoked in updateMWIS() when
2874 // EF_MWIS is not loaded/available.
2875 delete ril.iccInfoPrivate.mwis;
2876 do_test(false, 0);
2878 run_next_test();
2879 });
2881 /**
2882 * Verify the call flow of receiving Class 2 SMS stored in SIM:
2883 * 1. UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM.
2884 * 2. SimRecordHelper.readSMS().
2885 * 3. sendChromeMessage() with rilMessageType == "sms-received".
2886 */
2887 add_test(function test_read_new_sms_on_sim() {
2888 // Instead of reusing newUint8Worker defined in this file,
2889 // we define our own worker to fake the methods in WorkerBuffer dynamically.
2890 function newSmsOnSimWorkerHelper() {
2891 let _postedMessage;
2892 let _worker = newWorker({
2893 postRILMessage: function(data) {
2894 },
2895 postMessage: function(message) {
2896 _postedMessage = message;
2897 }
2898 });
2900 _worker.debug = do_print;
2902 return {
2903 get postedMessage() {
2904 return _postedMessage;
2905 },
2906 get worker() {
2907 return _worker;
2908 },
2909 fakeWokerBuffer: function() {
2910 let context = _worker.ContextPool._contexts[0];
2911 let index = 0; // index for read
2912 let buf = [];
2913 context.Buf.writeUint8 = function(value) {
2914 buf.push(value);
2915 };
2916 context.Buf.readUint8 = function() {
2917 return buf[index++];
2918 };
2919 context.Buf.seekIncoming = function(offset) {
2920 index += offset;
2921 };
2922 context.Buf.getReadAvailable = function() {
2923 return buf.length - index;
2924 };
2925 }
2926 };
2927 }
2929 let workerHelper = newSmsOnSimWorkerHelper();
2930 let worker = workerHelper.worker;
2931 let context = worker.ContextPool._contexts[0];
2933 context.ICCIOHelper.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
2934 // SimStatus: Unread, SMSC:+0123456789, Sender: +9876543210, Text: How are you?
2935 let SimSmsPduHex = "0306911032547698040A9189674523010000208062917314080CC8F71D14969741F977FD07"
2936 // In 4.2.25 EF_SMS Short Messages of 3GPP TS 31.102:
2937 // 1. Record length == 176 bytes.
2938 // 2. Any bytes in the record following the TPDU shall be filled with 'FF'.
2939 + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2940 + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2941 + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
2942 + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
2944 workerHelper.fakeWokerBuffer();
2946 context.Buf.writeString(SimSmsPduHex);
2948 options.recordSize = 176; // Record length is fixed to 176 bytes.
2949 if (options.callback) {
2950 options.callback(options);
2951 }
2952 };
2954 function newSmsOnSimParcel() {
2955 let data = new Uint8Array(4 + 4); // Int32List with 1 element.
2956 let offset = 0;
2958 function writeInt(value) {
2959 data[offset++] = value & 0xFF;
2960 data[offset++] = (value >> 8) & 0xFF;
2961 data[offset++] = (value >> 16) & 0xFF;
2962 data[offset++] = (value >> 24) & 0xFF;
2963 }
2965 writeInt(1); // Length of Int32List
2966 writeInt(1); // RecordNum = 1.
2968 return newIncomingParcel(-1,
2969 RESPONSE_TYPE_UNSOLICITED,
2970 UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM,
2971 data);
2972 }
2974 function do_test() {
2975 worker.onRILMessage(0, newSmsOnSimParcel());
2977 let postedMessage = workerHelper.postedMessage;
2979 do_check_eq("sms-received", postedMessage.rilMessageType);
2980 do_check_eq("+0123456789", postedMessage.SMSC);
2981 do_check_eq("+9876543210", postedMessage.sender);
2982 do_check_eq("How are you?", postedMessage.body);
2983 }
2985 do_test();
2987 run_next_test();
2988 });
2990 // Test ICC_COMMAND_GET_RESPONSE with FCP template format.
2991 /**
2992 * Verify transparent structure with FCP template format.
2993 */
2994 add_test(function test_fcp_template_for_transparent_structure() {
2995 let worker = newUint8Worker();
2996 let context = worker.ContextPool._contexts[0];
2997 let pduHelper = context.GsmPDUHelper;
2998 let berHelper = context.BerTlvHelper;
3000 let tag_test = [
3001 0x62,
3002 0x22,
3003 0x82, 0x02, 0x41, 0x21,
3004 0x83, 0x02, 0x2F, 0xE2,
3005 0xA5, 0x09, 0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00,
3006 0x8A, 0x01, 0x05,
3007 0x8B, 0x03, 0x2F, 0x06, 0x0B,
3008 0x80, 0x02, 0x00, 0x0A,
3009 0x88, 0x01, 0x10];
3011 for (let i = 0; i < tag_test.length; i++) {
3012 pduHelper.writeHexOctet(tag_test[i]);
3013 }
3015 let berTlv = berHelper.decode(tag_test.length);
3016 let iter = Iterator(berTlv.value);
3017 let tlv = berHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG, iter);
3018 do_check_eq(tlv.value.fileStructure, UICC_EF_STRUCTURE[EF_TYPE_TRANSPARENT]);
3020 tlv = berHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
3021 do_check_eq(tlv.value.fileId, 0x2FE2);
3023 tlv = berHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
3024 do_check_eq(tlv.value.fileSizeData, 0x0A);
3026 run_next_test();
3027 });
3029 /**
3030 * Verify linear fixed structure with FCP template format.
3031 */
3032 add_test(function test_fcp_template_for_linear_fixed_structure() {
3033 let worker = newUint8Worker();
3034 let context = worker.ContextPool._contexts[0];
3035 let pduHelper = context.GsmPDUHelper;
3036 let berHelper = context.BerTlvHelper;
3038 let tag_test = [
3039 0x62,
3040 0x1E,
3041 0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01,
3042 0x83, 0x02, 0x6F, 0x40,
3043 0xA5, 0x03, 0x92, 0x01, 0x00,
3044 0x8A, 0x01, 0x07,
3045 0x8B, 0x03, 0x6F, 0x06, 0x02,
3046 0x80, 0x02, 0x00, 0x1A,
3047 0x88, 0x00];
3049 for (let i = 0; i < tag_test.length; i++) {
3050 pduHelper.writeHexOctet(tag_test[i]);
3051 }
3053 let berTlv = berHelper.decode(tag_test.length);
3054 let iter = Iterator(berTlv.value);
3055 let tlv = berHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG, iter);
3056 do_check_eq(tlv.value.fileStructure, UICC_EF_STRUCTURE[EF_TYPE_LINEAR_FIXED]);
3057 do_check_eq(tlv.value.recordLength, 0x1A);
3058 do_check_eq(tlv.value.numOfRecords, 0x01);
3060 tlv = berHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
3061 do_check_eq(tlv.value.fileId, 0x6F40);
3063 tlv = berHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
3064 do_check_eq(tlv.value.fileSizeData, 0x1A);
3066 run_next_test();
3067 });
3069 add_test(function test_icc_io_get_response_for_transparent_structure() {
3070 let worker = newUint8Worker();
3071 let context = worker.ContextPool._contexts[0];
3072 let buf = context.Buf;
3073 let iccioHelper = context.ICCIOHelper;
3074 let pduHelper = context.GsmPDUHelper;
3076 let responseArray = [
3077 // SIM response.
3078 [0x00, 0x00, 0x00, 0x0A, 0x2F, 0xE2, 0x04, 0x00, 0x0A, 0xA0, 0xAA, 0x00,
3079 0x02, 0x00, 0x00],
3080 // USIM response.
3081 [0x62, 0x22, 0x82, 0x02, 0x41, 0x21, 0x83, 0x02, 0x2F, 0xE2, 0xA5, 0x09,
3082 0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x05,
3083 0x8B, 0x03, 0x2F, 0x06, 0x0B, 0x80, 0x02, 0x00, 0x0A, 0x88, 0x01, 0x10]
3084 ];
3086 for (let i = 0; i < responseArray.length; i++) {
3087 let strLen = responseArray[i].length * 2;
3088 buf.writeInt32(strLen);
3089 for (let j = 0; j < responseArray[i].length; j++) {
3090 pduHelper.writeHexOctet(responseArray[i][j]);
3091 }
3092 buf.writeStringDelimiter(strLen);
3094 let options = {fileId: ICC_EF_ICCID,
3095 type: EF_TYPE_TRANSPARENT};
3096 iccioHelper.processICCIOGetResponse(options);
3098 do_check_eq(options.fileSize, 0x0A);
3099 }
3101 run_next_test();
3102 });
3104 add_test(function test_icc_io_get_response_for_linear_fixed_structure() {
3105 let worker = newUint8Worker();
3106 let context = worker.ContextPool._contexts[0];
3107 let buf = context.Buf;
3108 let iccioHelper = context.ICCIOHelper;
3109 let pduHelper = context.GsmPDUHelper;
3111 let responseArray = [
3112 // SIM response.
3113 [0x00, 0x00, 0x00, 0x1A, 0x6F, 0x40, 0x04, 0x00, 0x11, 0xA0, 0xAA, 0x00,
3114 0x02, 0x01, 0x1A],
3115 // USIM response.
3116 [0x62, 0x1E, 0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01, 0x83, 0x02, 0x6F,
3117 0x40, 0xA5, 0x03, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x07, 0x8B, 0x03, 0x6F,
3118 0x06, 0x02, 0x80, 0x02, 0x00, 0x1A, 0x88, 0x00]
3119 ];
3121 for (let i = 0; i < responseArray.length; i++) {
3122 let strLen = responseArray[i].length * 2;
3123 buf.writeInt32(strLen);
3124 for (let j = 0; j < responseArray[i].length; j++) {
3125 pduHelper.writeHexOctet(responseArray[i][j]);
3126 }
3127 buf.writeStringDelimiter(strLen);
3129 let options = {fileId: ICC_EF_MSISDN,
3130 type: EF_TYPE_LINEAR_FIXED};
3131 iccioHelper.processICCIOGetResponse(options);
3133 do_check_eq(options.fileSize, 0x1A);
3134 do_check_eq(options.recordSize, 0x1A);
3135 do_check_eq(options.totalRecords, 0x01);
3136 }
3138 run_next_test();
3139 });
3141 /**
3142 * Verify reading EF_ICCID.
3143 */
3144 add_test(function test_handling_iccid() {
3145 let worker = newUint8Worker();
3146 let context = worker.ContextPool._contexts[0];
3147 let record = context.ICCRecordHelper;
3148 let helper = context.GsmPDUHelper;
3149 let ril = context.RIL;
3150 let buf = context.Buf;
3151 let io = context.ICCIOHelper;
3153 ril.reportStkServiceIsRunning = function fakeReportStkServiceIsRunning() {
3154 };
3156 function do_test(rawICCID, expectedICCID) {
3157 io.loadTransparentEF = function fakeLoadTransparentEF(options) {
3158 // Write data size
3159 buf.writeInt32(rawICCID.length);
3161 // Write data
3162 for (let i = 0; i < rawICCID.length; i += 2) {
3163 helper.writeHexOctet(parseInt(rawICCID.substr(i, 2), 16));
3164 }
3166 // Write string delimiter
3167 buf.writeStringDelimiter(rawICCID.length);
3169 if (options.callback) {
3170 options.callback(options);
3171 }
3172 };
3174 record.readICCID();
3176 do_check_eq(ril.iccInfo.iccid, expectedICCID);
3177 }
3179 // Invalid char at high nibbile + low nibbile contains 0xF.
3180 do_test("9868002E90909F001519", "89860020909");
3181 // Invalid char at low nibbile.
3182 do_test("986800E2909090001519", "8986002090909005191");
3183 // Valid ICCID.
3184 do_test("98101430121181157002", "89014103211118510720");
3186 run_next_test();
3187 });