Bug 720643 - B2G SMS: Notify SMS send success. r=qDot
authorPhilipp von Weitershausen <philipp@weitershausen.de>
Mon, 20 Feb 2012 00:44:29 +0100
changeset 87186 16c4770044a8e360c391e917c4f0e6be327664c5
parent 87185 7b757f2d70c4ce875e061e31ef8f347db849ff69
child 87187 f9145dab4be93acbc202f4c9515fd693bb3c8d0b
push id6240
push userpweitershausen@mozilla.com
push dateSun, 19 Feb 2012 23:45:02 +0000
treeherdermozilla-inbound@16c4770044a8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqDot
bugs720643
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 720643 - B2G SMS: Notify SMS send success. r=qDot
dom/sms/src/ril/SmsService.cpp
dom/system/b2g/RadioInterfaceLayer.js
dom/system/b2g/nsIRadioInterfaceLayer.idl
dom/system/b2g/ril_worker.js
--- a/dom/sms/src/ril/SmsService.cpp
+++ b/dom/sms/src/ril/SmsService.cpp
@@ -84,17 +84,17 @@ SmsService::Send(const nsAString& aNumbe
                  const nsAString& aMessage,
                  PRInt32 aRequestId,
                  PRUint64 aProcessId)
 {
   if (!mRIL) {
     return NS_OK;
   }
 
-  mRIL->SendSMS(aNumber, aMessage);
+  mRIL->SendSMS(aNumber, aMessage, aRequestId, aProcessId);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsService::CreateSmsMessage(PRInt32 aId,
                              const nsAString& aDelivery,
                              const nsAString& aSender,
                              const nsAString& aReceiver,
--- a/dom/system/b2g/RadioInterfaceLayer.js
+++ b/dom/system/b2g/RadioInterfaceLayer.js
@@ -54,21 +54,26 @@ const RADIOINTERFACELAYER_CID =
 const DATACALLINFO_CID =
   Components.ID("{ef474cd9-94f7-4c05-a31b-29b9de8a10d2}");
 
 const nsIAudioManager = Ci.nsIAudioManager;
 const nsIRadioInterfaceLayer = Ci.nsIRadioInterfaceLayer;
 
 const kSmsReceivedObserverTopic          = "sms-received";
 const DOM_SMS_DELIVERY_RECEIVED          = "received";
+const DOM_SMS_DELIVERY_SENT              = "sent";
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSmsService",
                                    "@mozilla.org/sms/smsservice;1",
                                    "nsISmsService");
 
+XPCOMUtils.defineLazyServiceGetter(this, "gSmsRequestManager",
+                                   "@mozilla.org/sms/smsrequestmanager;1",
+                                   "nsISmsRequestManager");
+
 function convertRILCallState(state) {
   switch (state) {
     case RIL.CALL_STATE_ACTIVE:
       return nsIRadioInterfaceLayer.CALL_STATE_CONNECTED;
     case RIL.CALL_STATE_HOLDING:
       return nsIRadioInterfaceLayer.CALL_STATE_HELD;
     case RIL.CALL_STATE_DIALING:
       return nsIRadioInterfaceLayer.CALL_STATE_DIALING;
@@ -196,16 +201,19 @@ RadioInterfaceLayer.prototype = {
         this.currentState.radioState = message.radioState;
         break;
       case "cardstatechange":
         this.currentState.cardState = message.cardState;
         break;
       case "sms-received":
         this.handleSmsReceived(message);
         return;
+      case "sms-sent":
+        this.handleSmsSent(message);
+        return;
       case "datacallstatechange":
         this.handleDataCallState(message.datacall);
         break;
       case "datacalllist":
         this.handleDataCallList(message);
         break;
       default:
         throw new Error("Don't know about this message type: " + message.type);
@@ -305,16 +313,28 @@ RadioInterfaceLayer.prototype = {
                                            DOM_SMS_DELIVERY_RECEIVED,
                                            message.sender || null,
                                            message.receiver || null,
                                            message.body || null,
                                            message.timestamp);
     Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null);
   },
 
+  handleSmsSent: function handleSmsSent(message) {
+    let message = gSmsService.createSmsMessage(-1,
+                                               DOM_SMS_DELIVERY_SENT,
+                                               message.SMSC,
+                                               message.number,
+                                               message.body,
+                                               Date.now());
+    //TODO At this point we should save the sms into the DB (bug 712809)
+    //TODO handle errors (bug XXX)
+    gSmsRequestManager.notifySmsSent(message.requestId, message);
+  },
+
   /**
    * Handle data call state changes.
    */
   handleDataCallState: function handleDataCallState(datacall) {
     this._deliverDataCallCallback("dataCallStateChanged",
                                   [datacall.cid, datacall.ifname, datacall.state]);
   },
 
@@ -397,20 +417,22 @@ RadioInterfaceLayer.prototype = {
 
   getNumberOfMessagesForText: function getNumberOfMessagesForText(text) {
     //TODO: this assumes 7bit encoding, which is incorrect. Need to look
     // for characters not supported by 7bit alphabets and then calculate
     // length in UCS2 encoding.
     return Math.ceil(text.length / 160);
   },
 
-  sendSMS: function sendSMS(number, message) {
+  sendSMS: function sendSMS(number, message, requestId, processId) {
     this.worker.postMessage({type: "sendSMS",
                              number: number,
-                             body: message});
+                             body: message,
+                             requestId: requestId,
+                             processId: processId});
   },
 
   _callbacks: null,
   _enumerationCallbacks: null,
 
   registerCallback: function registerCallback(callback) {
     if (this._callbacks) {
       if (this._callbacks.indexOf(callback) != -1) {
--- a/dom/system/b2g/nsIRadioInterfaceLayer.idl
+++ b/dom/system/b2g/nsIRadioInterfaceLayer.idl
@@ -111,17 +111,17 @@ interface nsIRILDataCallback : nsISuppor
    *        Array of nsIRILDataCallInfo objects.
    * @param length
    *        Lenght of the aforementioned array.
    */
   void receiveDataCallList([array,size_is(length)] in nsIRILDataCallInfo dataCalls,
                            in unsigned long length);
 };
 
-[scriptable, uuid(9b7e3a01-9c45-4af3-81bb-1bf08a842226)]
+[scriptable, uuid(aeb7ffe7-7d3a-4b7d-9b59-b6d3ae1c72ed)]
 interface nsIRadioInterfaceLayer : nsISupports
 {
   const unsigned short CALL_STATE_UNKNOWN = 0;
   const unsigned short CALL_STATE_DIALING = 1;
   const unsigned short CALL_STATE_RINGING = 2;
   const unsigned short CALL_STATE_BUSY = 3;
   const unsigned short CALL_STATE_CONNECTING = 4;
   const unsigned short CALL_STATE_CONNECTED = 5;
@@ -172,18 +172,21 @@ interface nsIRadioInterfaceLayer : nsISu
                      in DOMString apn,
                      in DOMString user,
                      in DOMString passwd,
                      in long chappap,
                      in DOMString pdptype);
   void deactivateDataCall(in DOMString cid,
                           in DOMString reason);
   void getDataCallList();
-  
+
   void registerDataCallCallback(in nsIRILDataCallback callback);
   void unregisterDataCallCallback(in nsIRILDataCallback callback);
 
   /**
    * SMS-related functionality.
    */
   unsigned short getNumberOfMessagesForText(in DOMString text);
-  void sendSMS(in DOMString number, in DOMString message);
+  void sendSMS(in DOMString number,
+               in DOMString message,
+               in long requestId,
+               in unsigned long long processId);
 };
--- a/dom/system/b2g/ril_worker.js
+++ b/dom/system/b2g/ril_worker.js
@@ -433,22 +433,24 @@ let Buf = {
 
   /**
    * Process one parcel.
    */
   processParcel: function processParcel() {
     let response_type = this.readUint32();
     let length = this.readIncoming - UINT32_SIZE;
 
-    let request_type;
+    let request_type, options;
     if (response_type == RESPONSE_TYPE_SOLICITED) {
       let token = this.readUint32();
       let error = this.readUint32();
       length -= 2 * UINT32_SIZE;
-      request_type = this.tokenRequestMap[token];
+
+      options = this.tokenRequestMap[token];
+      request_type = options.rilRequestType;
       if (error) {
         //TODO
         if (DEBUG) {
           debug("Received error " + error + " for solicited parcel type " +
                 request_type);
         }
         return;
       }
@@ -462,33 +464,41 @@ let Buf = {
       request_type = this.readUint32();
       length -= UINT32_SIZE;
       if (DEBUG) debug("Unsolicited response for request type " + request_type);
     } else {
       if (DEBUG) debug("Unknown response type: " + response_type);
       return;
     }
 
-    RIL.handleParcel(request_type, length);
+    RIL.handleParcel(request_type, length, options);
   },
 
   /**
    * Start a new outgoing parcel.
    *
    * @param type
    *        Integer specifying the request type.
+   * @param options [optional]
+   *        Object containing information about the request, e.g. the
+   *        original main thread message object that led to the RIL request. 
    */
-  newParcel: function newParcel(type) {
+  newParcel: function newParcel(type, options) {
     if (DEBUG) debug("New outgoing parcel of type " + type);
     // We're going to leave room for the parcel size at the beginning.
     this.outgoingIndex = PARCEL_SIZE_SIZE;
     this.writeUint32(type);
     let token = this.token;
     this.writeUint32(token);
-    this.tokenRequestMap[token] = type;
+
+    if (!options) {
+      options = {};
+    }
+    options.rilRequestType = type;
+    this.tokenRequestMap[token] = options;
     this.token++;
     return token;
   },
 
   /**
    * Communicate with the RIL IPC thread.
    */
   sendParcel: function sendParcel() {
@@ -748,37 +758,42 @@ let RIL = {
    */
   rejectCall: function rejectCall() {
     Buf.simpleRequest(REQUEST_UDUB);
   },
 
   /**
    * Send an SMS.
    *
-   * @param smscPDU
+   * The `options` parameter object should contain the following attributes:
+   *
+   * @param SMSC
    *        String containing the SMSC PDU in hex format.
-   * @param address
+   * @param number
    *        String containing the recipients address.
    * @param body
    *        String containing the message body.
    * @param dcs
    *        Data coding scheme. One of the PDU_DCS_MSG_CODING_*BITS_ALPHABET
    *        constants.
    * @param bodyLengthInOctets
    *        Byte length of the message body when encoded with the given DCS.
    */
-  sendSMS: function sendSMS(smscPDU, address, body, dcs, bodyLengthInOctets) {
-    let token = Buf.newParcel(REQUEST_SEND_SMS);
+  sendSMS: function sendSMS(options) {
+    let token = Buf.newParcel(REQUEST_SEND_SMS, options);
     //TODO we want to map token to the input values so that on the
     // response from the RIL device we know which SMS request was successful
     // or not. Maybe we should build that functionality into newParcel() and
     // handle it within tokenRequestMap[].
     Buf.writeUint32(2);
-    Buf.writeString(smscPDU);
-    GsmPDUHelper.writeMessage(address, body, dcs, bodyLengthInOctets);
+    Buf.writeString(options.SMSC);
+    GsmPDUHelper.writeMessage(options.number,
+                              options.body,
+                              options.dcs,
+                              options.bodyLengthInOctets);
     Buf.sendParcel();
   },
 
   /**
    * Acknowledge the receipt and handling of an SMS.
    *
    * @param success
    *        Boolean indicating whether the message was successfuly handled.
@@ -902,21 +917,21 @@ let RIL = {
   },
 
   /**
    * Handle incoming requests from the RIL. We find the method that
    * corresponds to the request type. Incidentally, the request type
    * _is_ the method name, so that's easy.
    */
 
-  handleParcel: function handleParcel(request_type, length) {
+  handleParcel: function handleParcel(request_type, length, options) {
     let method = this[request_type];
     if (typeof method == "function") {
       if (DEBUG) debug("Handling parcel as " + method.name);
-      method.call(this, length);
+      method.call(this, length, options);
     }
   }
 };
 
 RIL[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS() {
   let iccStatus = {
     cardState:                   Buf.readUint32(), // CARD_STATE_*
     universalPINState:           Buf.readUint32(), // PINSTATE_*
@@ -1059,21 +1074,21 @@ RIL[REQUEST_GPRS_REGISTRATION_STATE] = f
 RIL[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length) {
   let operator = Buf.readStringList();
   Phone.onOperator(operator);
 };
 RIL[REQUEST_RADIO_POWER] = null;
 RIL[REQUEST_DTMF] = function REQUEST_DTMF() {
   Phone.onSendTone();
 };
-RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS() {
-  let messageRef = Buf.readUint32();
-  let ackPDU = Buf.readString();
-  let errorCode = Buf.readUint32();
-  Phone.onSendSMS(messageRef, ackPDU, errorCode);
+RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) {
+  options.messageRef = Buf.readUint32();
+  options.ackPDU = Buf.readString();
+  options.errorCode = Buf.readUint32();
+  Phone.onSendSMS(options);
 };
 RIL[REQUEST_SEND_SMS_EXPECT_MORE] = null;
 RIL[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL() {
   let [cid, ifname, ipaddr, dns, gw] = Buf.readStringList();
   Phone.onSetupDataCall(Buf.lastSolicitedToken, cid, ifname, ipaddr, dns, gw);
 };
 RIL[REQUEST_SIM_IO] = null;
 RIL[REQUEST_SEND_USSD] = null;
@@ -1748,18 +1763,19 @@ let Phone = {
 
   onGetSMSCAddress: function onGetSMSCAddress(smsc) {
     this.SMSC = smsc;
   },
 
   onSetSMSCAddress: function onSetSMSCAddress() {
   },
 
-  onSendSMS: function onSendSMS(messageRef, ackPDU, errorCode) {
-    //TODO
+  onSendSMS: function onSendSMS(options) {
+    options.type = "sms-sent";
+    this.sendDOMMessage(options);
   },
 
   onNewSMS: function onNewSMS(payloadLength) {
     if (!payloadLength) {
       if (DEBUG) debug("Received empty SMS!");
       //TODO: should we acknowledge the SMS here? maybe only after multiple
       //failures.
       return;
@@ -2008,34 +2024,43 @@ let Phone = {
 
   /**
    * Send an SMS.
    *
    * @param number
    *        String containing the recipient number.
    * @param body
    *        String containing the message text.
+   * @param requestId
+   *        String identifying the sms request used by the SmsRequestManager.
+   * @param processId
+   *        String containing the processId for the SmsRequestManager.
    */
   sendSMS: function sendSMS(options) {
     // Get the SMS Center address
     if (!this.SMSC) {
       //TODO: we shouldn't get here, but if we do, we might want to hold on
       // to the message and retry once we know the SMSC... or just notify an
       // error to the mainthread and let them deal with retrying?
       if (DEBUG) {
         debug("Cannot send the SMS. Need to get the SMSC address first.");
       }
       return;
     }
+    // We explicitly save this information on the options object so that we
+    // can refer to it later, in particular on the main thread (where this
+    // object may get sent eventually.)
+    options.SMSC = this.SMSC;
+
     //TODO: verify values on 'options'
     //TODO: the data encoding and length in octets should eventually be
     // computed on the mainthread and passed down to us.
-    RIL.sendSMS(this.SMSC, options.number, options.body,
-                PDU_DCS_MSG_CODING_7BITS_ALPHABET, //TODO: hard-coded for now,
-                Math.ceil(options.body.length * 7 / 8)); //TODO: ditto
+    options.dcs = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
+    options.bodyLengthInOctets = Math.ceil(options.body.length * 7 / 8);
+    RIL.sendSMS(options);
   },
 
   /**
    * Setup a data call (PDP).
    */
   setupDataCall: function setupDataCall(options) {
     if (DEBUG) debug("setupDataCall: " + JSON.stringify(options));