diff --git a/dom/system/gonk/RadioInterfaceLayer.js b/dom/system/gonk/RadioInterfaceLayer.js index af2ebe8b275a..dc4695103613 100644 --- a/dom/system/gonk/RadioInterfaceLayer.js +++ b/dom/system/gonk/RadioInterfaceLayer.js @@ -422,12 +422,14 @@ RadioInterfaceLayer.prototype = { handleSmsSent: function handleSmsSent(message) { debug("handleSmsSent: " + JSON.stringify(message)); let timestamp = Date.now(); - let id = gSmsDatabaseService.saveSentMessage(message.number, message.body, timestamp); + let id = gSmsDatabaseService.saveSentMessage(message.number, + message.fullBody, + timestamp); let sms = gSmsService.createSmsMessage(id, DOM_SMS_DELIVERY_SENT, null, message.number, - message.body, + message.fullBody, timestamp); //TODO handle errors (bug 727319) gSmsRequestManager.notifySmsSent(message.requestId, sms); @@ -548,6 +550,19 @@ RadioInterfaceLayer.prototype = { */ segmentRef16Bit: false, + /** + * Get valid SMS concatenation reference number. + */ + _segmentRef: 0, + get nextSegmentRef() { + let ref = this._segmentRef++; + + this._segmentRef %= (this.segmentRef16Bit ? 65535 : 255); + + // 0 is not a valid SMS concatenation reference number. + return ref + 1; + }, + /** * Calculate encoded length using specified locking/single shift table * @@ -610,7 +625,7 @@ RadioInterfaceLayer.prototype = { * a message string to be encoded. * * @return null or an options object with attributes `dcs`, - * `userDataHeaderLength`, `encodedBodyLength`, `langIndex`, + * `userDataHeaderLength`, `encodedFullBodyLength`, `langIndex`, * `langShiftIndex`, `segmentMaxSeq` set. * * @see #_calculateUserDataLength(). @@ -664,7 +679,7 @@ RadioInterfaceLayer.prototype = { options = { dcs: RIL.PDU_DCS_MSG_CODING_7BITS_ALPHABET, - encodedBodyLength: bodySeptets, + encodedFullBodyLength: bodySeptets, userDataHeaderLength: headerLen, langIndex: langIndex, langShiftIndex: langShiftIndex, @@ -682,7 +697,7 @@ RadioInterfaceLayer.prototype = { * a message string to be encoded. * * @return an options object with attributes `dcs`, `userDataHeaderLength`, - * `encodedBodyLength`, `segmentMaxSeq` set. + * `encodedFullBodyLength`, `segmentMaxSeq` set. * * @see #_calculateUserDataLength(). */ @@ -705,7 +720,7 @@ RadioInterfaceLayer.prototype = { return { dcs: RIL.PDU_DCS_MSG_CODING_16BITS_ALPHABET, - encodedBodyLength: bodyChars * 2, + encodedFullBodyLength: bodyChars * 2, userDataHeaderLength: headerLen, segmentMaxSeq: segments, }; @@ -722,12 +737,12 @@ RadioInterfaceLayer.prototype = { * @param dcs * Data coding scheme. One of the PDU_DCS_MSG_CODING_*BITS_ALPHABET * constants. - * @param body - * Original text message. + * @param fullBody + * Original unfragmented text message. * @param userDataHeaderLength * Length of embedded user data header, in bytes. The whole header * size will be userDataHeaderLength + 1; 0 for no header. - * @param encodedBodyLength + * @param encodedFullBodyLength * Length of the message body when encoded with the given DCS. For * UCS2, in bytes; for 7-bit, in septets. * @param langIndex @@ -746,7 +761,7 @@ RadioInterfaceLayer.prototype = { } if (options) { - options.body = message; + options.fullBody = message; } debug("_calculateUserDataLength: " + JSON.stringify(options)); @@ -868,11 +883,11 @@ RadioInterfaceLayer.prototype = { if (options.dcs == RIL.PDU_DCS_MSG_CODING_7BITS_ALPHABET) { const langTable = RIL.PDU_NL_LOCKING_SHIFT_TABLES[options.langIndex]; const langShiftTable = RIL.PDU_NL_SINGLE_SHIFT_TABLES[options.langShiftIndex]; - options.segments = this._fragmentText7Bit(options.body, + options.segments = this._fragmentText7Bit(options.fullBody, langTable, langShiftTable, options.userDataHeaderLength); } else { - options.segments = this._fragmentTextUCS2(options.body, + options.segments = this._fragmentTextUCS2(options.fullBody, options.userDataHeaderLength); } @@ -893,6 +908,12 @@ RadioInterfaceLayer.prototype = { options.requestId = requestId; options.processId = processId; + this._fragmentText(message, options); + if (options.segmentMaxSeq > 1) { + options.segmentRef16Bit = this.segmentRef16Bit; + options.segmentRef = this.nextSegmentRef; + } + this.worker.postMessage(options); }, diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index e09b19a3da82..65c59a559a0a 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -982,6 +982,18 @@ let RIL = { //TODO: verify values on 'options' + if (options.segmentMaxSeq > 1) { + if (!options.segmentSeq) { + // Fist segment to send + options.segmentSeq = 1; + options.body = options.segments[0].body; + options.encodedBodyLength = options.segments[0].encodedBodyLength; + } + } else { + options.body = options.fullBody; + options.encodedBodyLength = options.encodedFullBodyLength; + } + Buf.newParcel(REQUEST_SEND_SMS, options); Buf.writeUint32(2); Buf.writeString(options.SMSC); @@ -1655,6 +1667,20 @@ RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) { options.messageRef = Buf.readUint32(); options.ackPDU = Buf.readString(); options.errorCode = Buf.readUint32(); + + //TODO handle errors (bug 727319) + if ((options.segmentMaxSeq > 1) + && (options.segmentSeq < options.segmentMaxSeq)) { + // Setup attributes for sending next segment + let next = options.segmentSeq; + options.body = options.segments[next].body; + options.encodedBodyLength = options.segments[next].encodedBodyLength; + options.segmentSeq = next + 1; + + this.sendSMS(options); + return; + } + options.type = "sms-sent"; this.sendDOMMessage(options); }; @@ -2441,6 +2467,20 @@ let GsmPDUHelper = { writeUserDataHeader: function writeUserDataHeader(options) { this.writeHexOctet(options.userDataHeaderLength); + if (options.segmentMaxSeq > 1) { + if (options.segmentRef16Bit) { + this.writeHexOctet(PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT); + this.writeHexOctet(4); + this.writeHexOctet((options.segmentRef >> 8) & 0xFF); + } else { + this.writeHexOctet(PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT); + this.writeHexOctet(3); + } + this.writeHexOctet(options.segmentRef & 0xFF); + this.writeHexOctet(options.segmentMaxSeq & 0xFF); + this.writeHexOctet(options.segmentSeq & 0xFF); + } + if (options.langIndex != PDU_NL_IDENTIFIER_DEFAULT) { this.writeHexOctet(PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT); this.writeHexOctet(1); diff --git a/dom/system/gonk/tests/test_ril_worker_sms.js b/dom/system/gonk/tests/test_ril_worker_sms.js index e7796e9b725d..53c0196f2005 100644 --- a/dom/system/gonk/tests/test_ril_worker_sms.js +++ b/dom/system/gonk/tests/test_ril_worker_sms.js @@ -144,7 +144,7 @@ add_test(function test_RadioInterfaceLayer__calculateUserDataLength() { let options = ril._calculateUserDataLength(str); do_check_eq(expected[0], options.dcs); - do_check_eq(expected[1], options.encodedBodyLength); + do_check_eq(expected[1], options.encodedFullBodyLength); do_check_eq(expected[2], options.userDataHeaderLength); do_check_eq(expected[3], options.langIndex); do_check_eq(expected[4], options.langShiftIndex); @@ -224,7 +224,7 @@ add_test(function test_RadioInterfaceLayer__calculateUserDataLength7Bit_multipar function test_calc(str, expected) { let options = ril._calculateUserDataLength7Bit(str); - do_check_eq(expected[0], options.encodedBodyLength); + do_check_eq(expected[0], options.encodedFullBodyLength); do_check_eq(expected[1], options.userDataHeaderLength); do_check_eq(expected[2], options.segmentMaxSeq); }