Bug 1122376 - Support read SIM contact dialling number exceed 20 digits. r=echen

This commit is contained in:
John Dai 2015-09-20 19:48:00 +02:00
parent a7678de912
commit e0d48f95b5
4 changed files with 260 additions and 18 deletions

View File

@ -9,8 +9,9 @@ function testReadContacts(aIcc, aType) {
let iccId = aIcc.iccInfo.iccid;
return aIcc.readContacts(aType)
.then((aResult) => {
is(Array.isArray(aResult), true);
is(aResult.length, 4, "Check contact number.");
is(aResult.length, 6, "Check contact number.");
// Alpha Id(Encoded with GSM 8 bit): "Mozilla", Dialling Number: 15555218201
is(aResult[0].name[0], "Mozilla");
@ -31,6 +32,18 @@ function testReadContacts(aIcc, aType) {
is(aResult[3].name[0], "Huang 黃");
is(aResult[3].tel[0].value, "15555218204");
is(aResult[3].id, iccId + "4");
// Alpha Id(Encoded with GSM 8 bit): "Contact001",
// Dialling Number: 9988776655443322110001234567890123456789
is(aResult[4].name[0], "Contact001");
is(aResult[4].tel[0].value, "9988776655443322110001234567890123456789");
is(aResult[4].id, iccId + "5");
// Alpha Id(Encoded with GSM 8 bit): "Contact002",
// Dialling Number: 0123456789012345678999887766554433221100
is(aResult[5].name[0], "Contact002");
is(aResult[5].tel[0].value, "0123456789012345678999887766554433221100");
is(aResult[5].id, iccId + "6");
}, (aError) => {
ok(false, "Cannot get " + aType + " contacts");
});

View File

@ -574,6 +574,12 @@ this.ADN_MAX_BCD_NUMBER_BYTES = 11;
// Maximum digits of the Dialling Number in ADN.
// See TS 151.011 clause 10.5.1 EF_ADN, 'Dialling Number'.
this.ADN_MAX_NUMBER_DIGITS = 20;
// Maximum size of BCD numbers in EXT.
// See TS 151.011 clause 10.5.10 EF_EXT1, 'Extension data'.
this.EXT_MAX_BCD_NUMBER_BYTES = 10;
// Maximum digits of the Dialling Number in EXT.
// See TS 151.011 clause 10.5.10 EF_EXT1, 'Extension data'.
this.EXT_MAX_NUMBER_DIGITS = 20;
// READ_RECORD mode, TS 102.221
this.READ_RECORD_ABSOLUTE_MODE = 4;
@ -1262,10 +1268,13 @@ this.GECKO_ICC_SERVICES = {
FDN: 3,
PLMNSEL: 7,
MSISDN: 9,
EXT1: 10,
EXT2: 11,
CBMI: 14,
GID1: 15,
SPN: 17,
SDN: 18,
EXT3: 19,
DATA_DOWNLOAD_SMS_CB: 25,
DATA_DOWNLOAD_SMS_PP: 26,
CBMIR: 30,
@ -1280,7 +1289,9 @@ this.GECKO_ICC_SERVICES = {
// @see 3GPP TS 31.102 4.2.8 (USIM).
usim: {
FDN: 2,
EXT2: 3,
SDN: 4,
EXT3: 5,
BDN: 6,
CBMI: 15,
CBMIR: 16,
@ -1300,8 +1311,11 @@ this.GECKO_ICC_SERVICES = {
ruim: {
FDN: 3,
ENHANCED_PHONEBOOK: 6,
EXT1: 10,
EXT2: 11,
SPN: 17,
SDN: 18
SDN: 18,
EXT3: 19,
},
// @see B.3.1.1 CPHS Information in CPHS Phase 2:
// Indicates which of the CPHS 'optional' data-fields are present in the SIM card:

View File

@ -11108,6 +11108,9 @@ ICCFileHelperObject.prototype = {
case ICC_EF_FDN:
case ICC_EF_MSISDN:
case ICC_EF_SMS:
case ICC_EF_EXT1:
case ICC_EF_EXT2:
case ICC_EF_EXT3:
return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
case ICC_EF_AD:
case ICC_EF_MBDN:
@ -11177,6 +11180,9 @@ ICCFileHelperObject.prototype = {
case ICC_EF_CSIM_SPN:
return EF_PATH_MF_SIM + EF_PATH_DF_CDMA;
case ICC_EF_FDN:
case ICC_EF_EXT1:
case ICC_EF_EXT2:
case ICC_EF_EXT3:
return EF_PATH_MF_SIM + EF_PATH_DF_TELECOM;
default:
return null;
@ -11582,24 +11588,20 @@ ICCRecordHelperObject.prototype = {
/**
* Read ICC ADN like EF, i.e. EF_ADN, EF_FDN.
*
* @param fileId EF id of the ADN or FDN.
* @param fileId EF id of the ADN, FDN or SDN.
* @param extFileId EF id of the EXT.
* @param onsuccess Callback to be called when success.
* @param onerror Callback to be called when error.
*/
readADNLike: function(fileId, onsuccess, onerror) {
readADNLike: function(fileId, extFileId, onsuccess, onerror) {
let ICCIOHelper = this.context.ICCIOHelper;
function callback(options) {
let contact =
this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
if (contact) {
contact.recordId = options.p1;
contacts.push(contact);
}
if (options.p1 < options.totalRecords) {
ICCIOHelper.loadNextRecord(options);
} else {
let loadNextContactRecord = () => {
if (options.p1 < options.totalRecords) {
ICCIOHelper.loadNextRecord(options);
return;
}
if (DEBUG) {
for (let i = 0; i < contacts.length; i++) {
this.context.debug("contact [" + i + "] " +
@ -11609,7 +11611,29 @@ ICCRecordHelperObject.prototype = {
if (onsuccess) {
onsuccess(contacts);
}
};
let contact =
this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
if (contact) {
let record = {
recordId: options.p1,
alphaId: contact.alphaId,
number: contact.number
};
contacts.push(record);
if (extFileId && contact.extRecordNumber != 0xff) {
this.readExtension(extFileId, contact.extRecordNumber, (number) => {
if (number) {
record.number += number;
}
loadNextContactRecord();
}, () => loadNextContactRecord());
return;
}
}
loadNextContactRecord();
}
let contacts = [];
@ -12084,6 +12108,64 @@ ICCRecordHelperObject.prototype = {
callback: callback.bind(this),
onerror: onerror});
},
/**
* Read Extension Number from TS 151.011 clause 10.5.10, TS 31.102, clause 4.4.2.4
*
* @param fileId EF Extension id
* @param recordNumber The number of the record shall be loaded.
* @param onsuccess Callback to be called when success.
* @param onerror Callback to be called when error.
*/
readExtension: function(fileId, recordNumber, onsuccess, onerror) {
let callback = (options) => {
let Buf = this.context.Buf;
let length = Buf.readInt32();
let recordType = this.context.GsmPDUHelper.readHexOctet();
let number = "";
// TS 31.102, clause 4.4.2.4 EFEXT1
// Case 1, Extension1 record is additional data
if (recordType & 0x02) {
let numLen = this.context.GsmPDUHelper.readHexOctet();
if (numLen != 0xff) {
if (numLen > EXT_MAX_BCD_NUMBER_BYTES) {
if (DEBUG) {
this.context.debug(
"Error: invalid length of BCD number/SSC contents - " + numLen);
}
// +1 to skip Identifier
Buf.seekIncoming((EXT_MAX_BCD_NUMBER_BYTES + 1) * Buf.PDU_HEX_OCTET_SIZE);
Buf.readStringDelimiter(length);
onerror();
return;
}
number = this.context.GsmPDUHelper.readSwappedNibbleExtendedBcdString(numLen);
if (DEBUG) this.context.debug("Contact Extension Number: "+ number);
Buf.seekIncoming((EXT_MAX_BCD_NUMBER_BYTES - numLen) * Buf.PDU_HEX_OCTET_SIZE);
} else {
Buf.seekIncoming(EXT_MAX_BCD_NUMBER_BYTES * Buf.PDU_HEX_OCTET_SIZE);
}
} else {
// Don't support Case 2, Extension1 record is Called Party Subaddress.
// +1 skip numLen
Buf.seekIncoming((EXT_MAX_BCD_NUMBER_BYTES + 1) * Buf.PDU_HEX_OCTET_SIZE);
}
// Skip Identifier
Buf.seekIncoming(Buf.PDU_HEX_OCTET_SIZE);
Buf.readStringDelimiter(length);
onsuccess(number);
}
this.context.ICCIOHelper.loadLinearFixedEF({
fileId: fileId,
recordNumber: recordNumber,
callback: callback,
onerror: onerror
});
},
};
/**
@ -13994,7 +14076,9 @@ ICCContactHelperObject.prototype = {
switch (contactType) {
case GECKO_CARDCONTACT_TYPE_ADN:
if (!this.hasDfPhoneBook(appType)) {
ICCRecordHelper.readADNLike(ICC_EF_ADN, onsuccess, onerror);
ICCRecordHelper.readADNLike(ICC_EF_ADN,
(ICCUtilsHelper.isICCServiceAvailable("EXT1")) ? ICC_EF_EXT1 : null,
onsuccess, onerror);
} else {
this.readUSimContacts(onsuccess, onerror);
}
@ -14004,7 +14088,9 @@ ICCContactHelperObject.prototype = {
onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
break;
}
ICCRecordHelper.readADNLike(ICC_EF_FDN, onsuccess, onerror);
ICCRecordHelper.readADNLike(ICC_EF_FDN,
(ICCUtilsHelper.isICCServiceAvailable("EXT2")) ? ICC_EF_EXT2 : null,
onsuccess, onerror);
break;
case GECKO_CARDCONTACT_TYPE_SDN:
if (!ICCUtilsHelper.isICCServiceAvailable("SDN")) {
@ -14012,7 +14098,9 @@ ICCContactHelperObject.prototype = {
break;
}
ICCRecordHelper.readADNLike(ICC_EF_SDN, onsuccess, onerror);
ICCRecordHelper.readADNLike(ICC_EF_SDN,
(ICCUtilsHelper.isICCServiceAvailable("EXT3")) ? ICC_EF_EXT3 : null,
onsuccess, onerror);
break;
default:
if (DEBUG) {
@ -14224,11 +14312,13 @@ ICCContactHelperObject.prototype = {
* @param onerror Callback to be called when error.
*/
readPhonebookSet: function(pbr, onsuccess, onerror) {
let ICCRecordHelper = this.context.ICCRecordHelper;
let gotAdnCb = function gotAdnCb(contacts) {
this.readSupportedPBRFields(pbr, contacts, onsuccess, onerror);
}.bind(this);
this.context.ICCRecordHelper.readADNLike(pbr.adn.fileId, gotAdnCb, onerror);
ICCRecordHelper.readADNLike(pbr.adn.fileId,
(pbr.ext1) ? pbr.ext1.fileId : null, gotAdnCb, onerror);
},
/**

View File

@ -494,6 +494,74 @@ add_test(function test_update_iap() {
do_test([1, 2]);
});
/**
* Verify ICCRecordHelper.readADNLike.
*/
add_test(function test_read_adn_like() {
const RECORD_SIZE = 0x20;
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let helper = context.GsmPDUHelper;
let record = context.ICCRecordHelper;
let buf = context.Buf;
let io = context.ICCIOHelper;
let ril = context.RIL;
function do_test(extFileId, rawEF, expectedExtRecordNumber, expectedNumber) {
io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
// Write data size
buf.writeInt32(rawEF.length * 2);
// Write adn
for (let i = 0; i < rawEF.length; i += 2) {
helper.writeHexOctet(parseInt(rawEF.substr(i, 2), 16));
}
// Write string delimiter
buf.writeStringDelimiter(rawEF.length * 2);
options.p1 = 1;
options.recordSize = RECORD_SIZE;
options.totalRecords = 1;
if (options.callback) {
options.callback(options);
}
};
record.readExtension = function(fileId, recordNumber, onsuccess, onerror) {
onsuccess("1234");
}
let successCb = function successCb(contacts) {
ok(contacts[0].number == expectedNumber);
};
let errorCb = function errorCb(errorMsg) {
do_print("Reading ADNLike failed, msg = " + errorMsg);
ok(false);
};
record.readADNLike(ICC_EF_ADN, extFileId, successCb, errorCb);
}
ril.appType = CARD_APPTYPE_SIM;
// Valid extension
do_test(ICC_EF_EXT1,"436f6e74616374303031ffffffffffffffff0b8199887766554433221100ff01",
0x01,"998877665544332211001234");
// Empty extension
do_test(ICC_EF_EXT1,"436f6e74616374303031ffffffffffffffff0b8199887766554433221100ffff",
0xff, "99887766554433221100");
// Unsupport extension
do_test(null,"436f6e74616374303031ffffffffffffffff0b8199887766554433221100ffff",
0xff, "99887766554433221100");
// Empty dialling number contact
do_test(null,"436f6e74616374303031ffffffffffffffffffffffffffffffffffffffffffff",
0xff, null);
run_next_test();
});
/**
* Verify ICCRecordHelper.updateADNLike.
*/
@ -721,3 +789,60 @@ add_test(function test_handling_iccid() {
run_next_test();
});
/**
* Verify ICCRecordHelper.readExtension
*/
add_test(function test_read_extension() {
let worker = newUint8Worker();
let context = worker.ContextPool._contexts[0];
let helper = context.GsmPDUHelper;
let record = context.ICCRecordHelper;
let buf = context.Buf;
let io = context.ICCIOHelper;
function do_test(rawExtension, expectedExtensionNumber) {
io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
// Write data size
buf.writeInt32(rawExtension.length * 2);
// Write ext
for (let i = 0; i < rawExtension.length; i += 2) {
helper.writeHexOctet(parseInt(rawExtension.substr(i, 2), 16));
}
// Write string delimiter
buf.writeStringDelimiter(rawExtension.length);
if (options.callback) {
options.callback(options);
}
};
let successCb = function successCb(number) {
do_print("extension number:" + number);
equal(number, expectedExtensionNumber);
};
let errorCb = function errorCb() {
ok(expectedExtensionNumber == null);
};
record.readExtension(0x6f4a, 1, successCb, errorCb);
}
// Test unsupported record type 0x01
do_test("010a10325476981032547698ff", "");
// Test invalid length 0xc1
do_test("020c10325476981032547698ff", null);
// Test extension chain which we don't support
do_test("020a1032547698103254769802", "01234567890123456789");
// Test valid Extension
do_test("020a10325476981032547698ff", "01234567890123456789");
// Test valid Extension
do_test("0209103254769810325476ffff", "012345678901234567");
// Test empty Extension
do_test("02ffffffffffffffffffffffff", "");
run_next_test();
});