Bug 806307 - Queue target messages before listener ready and resend after ready. r=vicamo
authorChuck Lee <chulee@mozilla.com>
Mon, 12 Nov 2012 19:19:48 +0800
changeset 113170 424d4452324592f6eb1b39a33cc7aef208a2be68
parent 113169 2351a225d4db7e78c37febd6b5c146dff90681fb
child 113171 f82641cc61eb84937e84957f4e8c48bf68cee70c
push id23859
push useremorley@mozilla.com
push dateWed, 14 Nov 2012 14:36:31 +0000
treeherdermozilla-central@87928cd21b40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvicamo
bugs806307
milestone19.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 806307 - Queue target messages before listener ready and resend after ready. r=vicamo
dom/system/gonk/RadioInterfaceLayer.js
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -276,16 +276,18 @@ function RadioInterfaceLayer() {
   Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
   Services.obs.addObserver(this, kSysMsgListenerReadyObserverTopic, false);
   Services.obs.addObserver(this, kSysClockChangeObserverTopic, false);
 
   this._sentSmsEnvelopes = {};
 
   this.portAddressedSmsApps = {};
   this.portAddressedSmsApps[WAP.WDP_PORT_PUSH] = this.handleSmsWdpPortPush.bind(this);
+
+  this._targetMessageQueue = [];
 }
 RadioInterfaceLayer.prototype = {
 
   classID:   RADIOINTERFACELAYER_CID,
   classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACELAYER_CID,
                                     classDescription: "RadioInterfaceLayer",
                                     interfaces: [Ci.nsIWorkerHolder,
                                                  Ci.nsIRadioInterfaceLayer]}),
@@ -652,16 +654,22 @@ RadioInterfaceLayer.prototype = {
     let index = targets.indexOf(target);
     if (index != -1) {
       targets.splice(index, 1);
       debug("Unregistered " + permission + " target: " + target);
     }
   },
 
   _sendTargetMessage: function _sendTargetMessage(permission, message, options) {
+
+    if (!this._sysMsgListenerReady) {
+      this._enqueueTargetMessage(permission, message, options);
+      return;
+    }
+
     let targets = this._messageManagerByPermission[permission];
     if (!targets) {
       return;
     }
 
     for each (let target in targets) {
       target.sendAsyncMessage(message, options);
     }
@@ -919,16 +927,46 @@ RadioInterfaceLayer.prototype = {
       return;
     }
     this.rilContext.radioState = newState;
     //TODO Should we notify this change as a card state change?
 
     this._ensureRadioState();
   },
 
+  _enqueueTargetMessage: function _enqueueTargetMessage(permission, message, options) {
+    let msg = { permission : permission,
+                message : message,
+                options : options };
+    // Remove previous queued message of same message type, only one message
+    // per message type is allowed in queue.
+    let messageQueue = this._targetMessageQueue;
+    for(let i = 0; i < messageQueue.length; i++) {
+      if (messageQueue[i].message === message) {
+        messageQueue.splice(i, 1);
+        break;
+      }
+    }
+
+    messageQueue.push(msg);
+  },
+
+  _resendQueuedTargetMessage: function _resendQueuedTargetMessage() {
+    // Here uses this._sendTargetMessage() to resend message, which will
+    // enqueue message if listener is not ready.
+    // So only resend after listener is ready, or it will cause infinate loop and
+    // hang the system.
+
+    // Dequeue and resend messages.
+    for each (let msg in this._targetMessageQueue) {
+      this._sendTargetMessage(msg.permission, msg.message, msg.options);
+    }
+    this._targetMessageQueue = null;
+  },
+
   _ensureRadioState: function _ensureRadioState() {
     debug("Reported radio state is " + this.rilContext.radioState +
           ", desired radio enabled state is " + this._radioEnabled);
     if (this._radioEnabled == null) {
       // We haven't read the initial value from the settings DB yet.
       // Wait for that.
       return;
     }
@@ -1485,16 +1523,17 @@ RadioInterfaceLayer.prototype = {
 
   // nsIObserver
 
   observe: function observe(subject, topic, data) {
     switch (topic) {
       case kSysMsgListenerReadyObserverTopic:
         Services.obs.removeObserver(this, kSysMsgListenerReadyObserverTopic);
         this._sysMsgListenerReady = true;
+        this._resendQueuedTargetMessage();
         this._ensureRadioState();
         break;
       case kMozSettingsChangedObserverTopic:
         let setting = JSON.parse(data);
         this.handle(setting.key, setting.value);
         break;
       case "xpcom-shutdown":
         ppmm.removeMessageListener("child-process-shutdown", this);