Bug 742790 - Part 3/5: B2G RIL implementation, r=philikon,marshall_law
authorVicamo Yang <vyang@mozilla.com>
Tue, 30 Oct 2012 18:53:27 +0800
changeset 111890 95642feb675f26b4eac08ae3bb71a82413eafc6a
parent 111889 289f2d39289c776e711d45ec6292a1c412e16237
child 111891 d6d728ec557190cd75ac987de60c75323c1a35fa
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersphilikon, marshall_law
bugs742790
milestone19.0a1
Bug 742790 - Part 3/5: B2G RIL implementation, r=philikon,marshall_law
dom/sms/src/ril/SmsDatabaseService.js
dom/system/gonk/RadioInterfaceLayer.js
dom/system/gonk/ril_consts.js
dom/system/gonk/ril_worker.js
--- a/dom/sms/src/ril/SmsDatabaseService.js
+++ b/dom/sms/src/ril/SmsDatabaseService.js
@@ -15,16 +15,21 @@ const RIL_SMSDATABASESERVICE_CID = Compo
 const DEBUG = false;
 const DB_NAME = "sms";
 const DB_VERSION = 2;
 const STORE_NAME = "sms";
 
 const DELIVERY_SENT = "sent";
 const DELIVERY_RECEIVED = "received";
 
+const DELIVERY_STATUS_NOT_APPLICABLE = "not-applicable";
+const DELIVERY_STATUS_SUCCESS = "success";
+const DELIVERY_STATUS_PENDING = "pending";
+const DELIVERY_STATUS_ERROR = "error";
+
 const FILTER_TIMESTAMP = "timestamp";
 const FILTER_NUMBERS = "numbers";
 const FILTER_DELIVERY = "delivery";
 const FILTER_READ = "read";
 
 // We canĀ“t create an IDBKeyCursor with a boolean, so we need to use numbers
 // instead.
 const FILTER_READ_UNREAD = 0;
@@ -312,16 +317,17 @@ SmsDatabaseService.prototype = {
           gSmsRequestManager.notifyReadMessageListFailed(
             requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
           return;
         }
         self.lastMessageListId += 1;
         self.messageLists[self.lastMessageListId] = messageList;
         let sms = gSmsService.createSmsMessage(message.id,
                                                message.delivery,
+                                               message.deliveryStatus,
                                                message.sender,
                                                message.receiver,
                                                message.body,
                                                message.timestamp,
                                                message.read);
         gSmsRequestManager.notifyCreateMessageList(requestId,
                                                    self.lastMessageListId,
                                                    sms);
@@ -346,37 +352,87 @@ SmsDatabaseService.prototype = {
 
   /**
    * nsISmsDatabaseService API
    */
 
   saveReceivedMessage: function saveReceivedMessage(sender, body, date) {
     let receiver = this.mRIL.rilContext.icc ? this.mRIL.rilContext.icc.msisdn : null;
 
-    let message = {delivery:  DELIVERY_RECEIVED,
-                   sender:    sender,
-                   receiver:  receiver,
-                   body:      body,
-                   timestamp: date,
-                   read:      FILTER_READ_UNREAD};
+    let message = {delivery:       DELIVERY_RECEIVED,
+                   deliveryStatus: DELIVERY_STATUS_SUCCESS,
+                   sender:         sender,
+                   receiver:       receiver,
+                   body:           body,
+                   timestamp:      date,
+                   read:           FILTER_READ_UNREAD};
     return this.saveMessage(message);
   },
 
   saveSentMessage: function saveSentMessage(receiver, body, date) {
     let sender = this.mRIL.rilContext.icc ? this.mRIL.rilContext.icc.msisdn : null;
 
-    let message = {delivery:  DELIVERY_SENT,
-                   sender:    sender,
-                   receiver:  receiver,
-                   body:      body,
-                   timestamp: date,
-                   read:      FILTER_READ_READ};
+    let message = {delivery:       DELIVERY_SENT,
+                   deliveryStatus: DELIVERY_STATUS_PENDING,
+                   sender:         sender,
+                   receiver:       receiver,
+                   body:           body,
+                   timestamp:      date,
+                   read:           FILTER_READ_READ};
     return this.saveMessage(message);
   },
 
+  setMessageDeliveryStatus: function setMessageDeliveryStatus(messageId, deliveryStatus) {
+    if ((deliveryStatus != DELIVERY_STATUS_SUCCESS)
+        && (deliveryStatus != DELIVERY_STATUS_ERROR)) {
+      if (DEBUG) {
+        debug("Setting message " + messageId + " deliveryStatus to values other"
+              + " than 'success' and 'error'");
+      }
+      return;
+    }
+    if (DEBUG) {
+      debug("Setting message " + messageId + " deliveryStatus to "
+            + deliveryStatus);
+    }
+    this.newTxn(READ_WRITE, function (error, txn, store) {
+      if (error) {
+        if (DEBUG) debug(error);
+        return;
+      }
+
+      let getRequest = store.get(messageId);
+      getRequest.onsuccess = function onsuccess(event) {
+        let message = event.target.result;
+        if (!message) {
+          if (DEBUG) debug("Message ID " + messageId + " not found");
+          return;
+        }
+        if (message.id != messageId) {
+          if (DEBUG) {
+            debug("Retrieve message ID (" + messageId + ") is " +
+                  "different from the one we got");
+          }
+          return;
+        }
+        // Only updates messages that are still waiting for its delivery status.
+        if (message.deliveryStatus != DELIVERY_STATUS_PENDING) {
+          if (DEBUG) {
+            debug("The value of message.deliveryStatus is not 'pending' but "
+                  + message.deliveryStatus);
+          }
+          return;
+        }
+        message.deliveryStatus = deliveryStatus;
+        if (DEBUG) debug("Message.deliveryStatus set to: " + deliveryStatus);
+        store.put(message);
+      };
+    });
+  },
+
   getMessage: function getMessage(messageId, requestId) {
     if (DEBUG) debug("Retrieving message with ID " + messageId);
     this.newTxn(READ_ONLY, function (error, txn, store) {
       if (error) {
         if (DEBUG) debug(error);
         gSmsRequestManager.notifyGetSmsFailed(
           requestId, Ci.nsISmsRequestManager.INTERNAL_ERROR);
         return;
@@ -404,16 +460,17 @@ SmsDatabaseService.prototype = {
                   "different from the one we got");
           }
           gSmsRequestManager.notifyGetSmsFailed(
             requestId, Ci.nsISmsRequestManager.UNKNOWN_ERROR);
           return;
         }
         let message = gSmsService.createSmsMessage(data.id,
                                                    data.delivery,
+                                                   data.deliveryStatus,
                                                    data.sender,
                                                    data.receiver,
                                                    data.body,
                                                    data.timestamp,
                                                    data.read);
         gSmsRequestManager.notifyGotSms(requestId, message);
       };
 
@@ -628,16 +685,17 @@ SmsDatabaseService.prototype = {
         if (DEBUG) debug("Transaction " + txn + " completed.");
         if (!message) {
           if (DEBUG) debug("Could not get message id " + messageId);
           gSmsRequestManager.notifyReadMessageListFailed(
             requestId, Ci.nsISmsRequestManager.NOT_FOUND_ERROR);
         }
         let sms = gSmsService.createSmsMessage(message.id,
                                                message.delivery,
+                                               message.deliveryStatus,
                                                message.sender,
                                                message.receiver,
                                                message.body,
                                                message.timestamp,
                                                message.read);
         gSmsRequestManager.notifyGotNextMessage(requestId, sms);
       };
 
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -32,21 +32,23 @@ const RILNETWORKINTERFACE_CID =
   Components.ID("{3bdd52a9-3965-4130-b569-0ac5afed045e}");
 
 const nsIAudioManager = Ci.nsIAudioManager;
 const nsIRadioInterfaceLayer = Ci.nsIRadioInterfaceLayer;
 
 const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
 const kSmsReceivedObserverTopic          = "sms-received";
 const kSmsSentObserverTopic              = "sms-sent";
-const kSmsDeliveredObserverTopic         = "sms-delivered";
+const kSmsDeliverySuccessObserverTopic   = "sms-delivery-success";
+const kSmsDeliveryErrorObserverTopic     = "sms-delivery-error";
 const kMozSettingsChangedObserverTopic   = "mozsettings-changed";
 const kSysMsgListenerReadyObserverTopic  = "system-message-listener-ready";
 const kSysClockChangeObserverTopic       = "system-clock-change";
 const kTimeNitzAutomaticUpdateEnabled    = "time.nitz.automatic-update.enabled";
+
 const DOM_SMS_DELIVERY_RECEIVED          = "received";
 const DOM_SMS_DELIVERY_SENT              = "sent";
 
 const RIL_IPC_TELEPHONY_MSG_NAMES = [
   "RIL:EnumerateCalls",
   "RIL:GetMicrophoneMuted",
   "RIL:SetMicrophoneMuted",
   "RIL:GetSpeakerEnabled",
@@ -504,18 +506,18 @@ RadioInterfaceLayer.prototype = {
         this.handleCallWaitingStatusChange(message);
         break;
       case "sms-received":
         this.handleSmsReceived(message);
         return;
       case "sms-sent":
         this.handleSmsSent(message);
         return;
-      case "sms-delivered":
-        this.handleSmsDelivered(message);
+      case "sms-delivery":
+        this.handleSmsDelivery(message);
         return;
       case "sms-send-failed":
         this.handleSmsSendFailed(message);
         return;
       case "datacallstatechange":
         this.handleDataCallState(message);
         break;
       case "datacalllist":
@@ -1230,25 +1232,27 @@ RadioInterfaceLayer.prototype = {
     let id = -1;
     if (message.messageClass != RIL.PDU_DCS_MSG_CLASS_0) {
       id = gSmsDatabaseService.saveReceivedMessage(message.sender || null,
                                                    message.fullBody || null,
                                                    message.timestamp);
     }
     let sms = gSmsService.createSmsMessage(id,
                                            DOM_SMS_DELIVERY_RECEIVED,
+                                           RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
                                            message.sender || null,
                                            message.receiver || null,
                                            message.fullBody || null,
                                            message.timestamp,
                                            false);
 
     gSystemMessenger.broadcastMessage("sms-received",
                                       {id: id,
                                        delivery: DOM_SMS_DELIVERY_RECEIVED,
+                                       deliveryStatus: RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS,
                                        sender: message.sender || null,
                                        receiver: message.receiver || null,
                                        body: message.fullBody || null,
                                        timestamp: message.timestamp,
                                        read: false});
     Services.obs.notifyObservers(sms, kSmsReceivedObserverTopic, null);
   },
 
@@ -1276,44 +1280,60 @@ RadioInterfaceLayer.prototype = {
     }
 
     let timestamp = Date.now();
     let id = gSmsDatabaseService.saveSentMessage(options.number,
                                                  options.fullBody,
                                                  timestamp);
     let sms = gSmsService.createSmsMessage(id,
                                            DOM_SMS_DELIVERY_SENT,
+                                           RIL.GECKO_SMS_DELIVERY_STATUS_PENDING,
                                            null,
                                            options.number,
                                            options.fullBody,
                                            timestamp,
                                            true);
 
     if (!options.requestStatusReport) {
       // No more used if STATUS-REPORT not requested.
       delete this._sentSmsEnvelopes[message.envelopeId];
     } else {
-      options.sms = sms;
+      options.id = id;
+      options.timestamp = timestamp;
     }
 
     gSmsRequestManager.notifySmsSent(options.requestId, sms);
 
-    Services.obs.notifyObservers(options.sms, kSmsSentObserverTopic, null);
+    Services.obs.notifyObservers(sms, kSmsSentObserverTopic, null);
   },
 
-  handleSmsDelivered: function handleSmsDelivered(message) {
-    debug("handleSmsDelivered: " + JSON.stringify(message));
+  handleSmsDelivery: function handleSmsDelivery(message) {
+    debug("handleSmsDelivery: " + JSON.stringify(message));
 
     let options = this._sentSmsEnvelopes[message.envelopeId];
     if (!options) {
       return;
     }
     delete this._sentSmsEnvelopes[message.envelopeId];
 
-    Services.obs.notifyObservers(options.sms, kSmsDeliveredObserverTopic, null);
+    gSmsDatabaseService.setMessageDeliveryStatus(options.id,
+                                                 message.deliveryStatus);
+    let sms = gSmsService.createSmsMessage(options.id,
+                                           DOM_SMS_DELIVERY_SENT,
+                                           message.deliveryStatus,
+                                           null,
+                                           options.number,
+                                           options.fullBody,
+                                           options.timestamp,
+                                           true);
+
+    let topic = (message.deliveryStatus == RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS)
+                ? kSmsDeliverySuccessObserverTopic
+                : kSmsDeliveryErrorObserverTopic;
+    Services.obs.notifyObservers(sms, topic, null);
   },
 
   handleSmsSendFailed: function handleSmsSendFailed(message) {
     debug("handleSmsSendFailed: " + JSON.stringify(message));
 
     let options = this._sentSmsEnvelopes[message.envelopeId];
     if (!options) {
       return;
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -925,16 +925,21 @@ const PDU_ST_3_SME_BUSY          = 0x61;
 const PDU_ST_3_SME_NO_RESPONSE   = 0x62;
 const PDU_ST_3_SERVICE_REJECTED  = 0x63;
 const PDU_ST_3_QOS_UNAVAILABLE   = 0x64;
 const PDU_ST_3_SME_ERROR         = 0x65;
 const PDU_ST_3_RESERVED_BEGIN    = 0x66;
 const PDU_ST_3_SC_SPECIFIC_BEGIN = 0x70;
 const PDU_ST_3_SC_SPECIFIC_END   = 0x7F;
 
+const GECKO_SMS_DELIVERY_STATUS_NOT_APPLICABLE = "not-applicable";
+const GECKO_SMS_DELIVERY_STATUS_SUCCESS        = "success";
+const GECKO_SMS_DELIVERY_STATUS_PENDING        = "pending";
+const GECKO_SMS_DELIVERY_STATUS_ERROR          = "error";
+
 // User Data max length in septets
 const PDU_MAX_USER_DATA_7BIT = 160;
 // User Data max length in octets
 const PDU_MAX_USER_DATA_8BIT = 140;
 // User Data max length in chars
 const PDU_MAX_USER_DATA_UCS2 = 70;
 
 // PID - Protocol Indicator
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -3859,31 +3859,30 @@ let RIL = {
     // Pending. Waiting for next status report.
     if ((status >>> 5) == 0x01) {
       if (DEBUG) debug("SMS-STATUS-REPORT: delivery still pending");
       return PDU_FCS_OK;
     }
 
     delete this._pendingSentSmsMap[message.messageRef];
 
-    if ((status >>> 5) != 0x00) {
-      if (DEBUG) debug("SMS-STATUS-REPORT: delivery failed");
-      // It seems unlikely to get a result code for a failure to deliver.
-      // Even if, we don't want to do anything with this.
+    if ((options.segmentMaxSeq > 1)
+        && (options.segmentSeq < options.segmentMaxSeq)) {
+      // Not the last segment.
       return PDU_FCS_OK;
     }
 
-    if ((options.segmentMaxSeq == 1)
-        && (options.segmentSeq == options.segmentMaxSeq)) {
-      // Last segment delivered with success. Report it.
-      this.sendDOMMessage({
-        rilMessageType: "sms-delivered",
-        envelopeId: options.envelopeId,
-      });
-    }
+    let deliveryStatus = ((status >>> 5) == 0x00)
+                       ? GECKO_SMS_DELIVERY_STATUS_SUCCESS
+                       : GECKO_SMS_DELIVERY_STATUS_ERROR;
+    this.sendDOMMessage({
+      rilMessageType: "sms-delivery",
+      envelopeId: options.envelopeId,
+      deliveryStatus: deliveryStatus
+    });
 
     return PDU_FCS_OK;
   },
 
   /**
    * Helper for processing received multipart SMS.
    *
    * @return null for handled segments, and an object containing full message