Bug 1114935 - Part 7: Add Backward Compatibility for v2.2 binary implementation. r=echen
authorBevis Tseng <btseng@mozilla.com>
Fri, 13 Feb 2015 14:46:49 +0800
changeset 266492 a483c38d6f726be059403e242a8551549902bcf4
parent 266491 d76cc3361383c9217ffb9d7505b114f2ec365828
child 266493 1b274a1579047a13cbca578cd666f7eb5b66f987
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersechen
bugs1114935
milestone39.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 1114935 - Part 7: Add Backward Compatibility for v2.2 binary implementation. r=echen
dom/icc/IccManager.cpp
dom/system/gonk/RILContentHelper.js
dom/system/gonk/RadioInterfaceLayer.js
dom/system/gonk/nsIRadioInterfaceLayer.idl
--- a/dom/icc/IccManager.cpp
+++ b/dom/icc/IccManager.cpp
@@ -8,16 +8,18 @@
 #include "IccListener.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/dom/IccChangeEvent.h"
 #include "mozilla/Preferences.h"
 #include "nsIIccInfo.h"
 // Service instantiation
 #include "ipc/IccIPCService.h"
 #if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
+#include "nsIRadioInterfaceLayer.h"
+#include "nsRadioInterfaceLayer.h"
 #include "nsIGonkIccService.h"
 #endif
 #include "nsXULAppAPI.h" // For XRE_GetProcessType()
 
 using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(IccManager)
 
@@ -140,14 +142,19 @@ already_AddRefed<nsIIccService>
 NS_CreateIccService()
 {
   nsCOMPtr<nsIIccService> service;
 
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     service = new mozilla::dom::icc::IccIPCService();
 #if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
   } else {
-    service = do_GetService(GONK_ICC_SERVICE_CONTRACTID);
+    nsCOMPtr <nsIRadioInterfaceLayer> ril =
+      do_GetService(NS_RADIOINTERFACELAYER_CONTRACTID);
+    nsCOMPtr <nsIRadioInterfaceLayer_new> ril_new(do_QueryInterface(ril));
+
+    service = (ril_new) ? do_GetService(GONK_ICC_SERVICE_CONTRACTID)
+                        : do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
 #endif
   }
 
   return service.forget();
 }
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -93,18 +93,18 @@ IccInfo.prototype = {
 
   // nsIIccInfo
 
   iccType: null,
   iccid: null,
   mcc: null,
   mnc: null,
   spn: null,
-  isDisplayNetworkNameRequired: null,
-  isDisplaySpnRequired: null
+  isDisplayNetworkNameRequired: false,
+  isDisplaySpnRequired: false
 };
 
 function GsmIccInfo() {}
 GsmIccInfo.prototype = {
   __proto__: IccInfo.prototype,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIGsmIccInfo,
                                          Ci.nsIIccInfo]),
 
@@ -126,44 +126,49 @@ CdmaIccInfo.prototype = {
 };
 
 function RILContentHelper() {
   this.updateDebugFlag();
 
   this.numClients = gNumRadioInterfaces;
   if (DEBUG) debug("Number of clients: " + this.numClients);
 
+  this._iccs = [];
   this.rilContexts = [];
   for (let clientId = 0; clientId < this.numClients; clientId++) {
+    this._iccs.push(new Icc(this, clientId));
     this.rilContexts[clientId] = {
       cardState: Ci.nsIIcc.CARD_STATE_UNKNOWN,
       iccInfo: null
     };
   }
 
   this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES);
   this._windowsMap = [];
+  this._requestMap = [];
   this._iccListeners = [];
   this._iccChannelCallback = [];
 
   Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
 
   Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
 }
 
 RILContentHelper.prototype = {
   __proto__: DOMRequestIpcHelper.prototype,
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccProvider,
+                                         Ci.nsIIccService,
                                          Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference]),
   classID:   RILCONTENTHELPER_CID,
   classInfo: XPCOMUtils.generateCI({classID: RILCONTENTHELPER_CID,
                                     classDescription: "RILContentHelper",
-                                    interfaces: [Ci.nsIIccProvider]}),
+                                    interfaces: [Ci.nsIIccProvider,
+                                                 Ci.nsIIccService]}),
 
   updateDebugFlag: function() {
     try {
       DEBUG = RIL.DEBUG_CONTENT_HELPER ||
               Services.prefs.getBoolPref(kPrefRilDebuggingEnabled);
     } catch (e) {}
   },
 
@@ -201,16 +206,18 @@ RILContentHelper.prototype = {
       }
     }
 
     this.updateInfo(newInfo, rilContext.iccInfo);
   },
 
   _windowsMap: null,
 
+  _requestMap: null,
+
   rilContexts: null,
 
   getRilContext: function(clientId) {
     // Update ril contexts by sending IPC message to chrome only when the first
     // time we require it. The information will be updated by following info
     // changed messages.
     this.getRilContext = function getRilContext(clientId) {
       return this.rilContexts[clientId];
@@ -229,152 +236,16 @@ RILContentHelper.prototype = {
 
     return this.rilContexts[clientId];
   },
 
   /**
    * nsIIccProvider
    */
 
-  getIccInfo: function(clientId) {
-    let context = this.getRilContext(clientId);
-    return context && context.iccInfo;
-  },
-
-  getCardState: function(clientId) {
-    let context = this.getRilContext(clientId);
-    return context && context.cardState;
-  },
-
-  matchMvno: function(clientId, window, mvnoType, mvnoData) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
-
-    cpmm.sendAsyncMessage("RIL:MatchMvno", {
-      clientId: clientId,
-      data: {
-        requestId: requestId,
-        mvnoType: mvnoType,
-        mvnoData: mvnoData
-      }
-    });
-    return request;
-  },
-
-  getCardLockEnabled: function(clientId, window, lockType) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
-    this._windowsMap[requestId] = window;
-
-    cpmm.sendAsyncMessage("RIL:GetCardLockEnabled", {
-      clientId: clientId,
-      data: {
-        lockType: lockType,
-        requestId: requestId
-      }
-    });
-    return request;
-  },
-
-  unlockCardLock: function(clientId, window, lockType, password, newPin) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
-    this._windowsMap[requestId] = window;
-
-    cpmm.sendAsyncMessage("RIL:UnlockCardLock", {
-      clientId: clientId,
-      data: {
-        lockType: lockType,
-        password: password,
-        newPin: newPin,
-        requestId: requestId
-      }
-    });
-    return request;
-  },
-
-  setCardLockEnabled: function(clientId, window, lockType, password, enabled) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
-    this._windowsMap[requestId] = window;
-
-    cpmm.sendAsyncMessage("RIL:SetCardLockEnabled", {
-      clientId: clientId,
-      data: {
-        lockType: lockType,
-        password: password,
-        enabled: enabled,
-        requestId: requestId
-      }
-    });
-    return request;
-  },
-
-  changeCardLockPassword: function(clientId, window, lockType, password,
-                                   newPassword) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
-    this._windowsMap[requestId] = window;
-
-    cpmm.sendAsyncMessage("RIL:ChangeCardLockPassword", {
-      clientId: clientId,
-      data: {
-        lockType: lockType,
-        password: password,
-        newPassword: newPassword,
-        requestId: requestId
-      }
-    });
-    return request;
-  },
-
-  getCardLockRetryCount: function(clientId, window, lockType) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
-    this._windowsMap[requestId] = window;
-
-    cpmm.sendAsyncMessage("RIL:GetCardLockRetryCount", {
-      clientId: clientId,
-      data: {
-        lockType: lockType,
-        requestId: requestId
-      }
-    });
-    return request;
-  },
-
   sendStkResponse: function(clientId, window, command, response) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     response.command = command;
     cpmm.sendAsyncMessage("RIL:SendStkResponse", {
       clientId: clientId,
@@ -540,37 +411,16 @@ RILContentHelper.prototype = {
         contact: iccContact,
         pin2: pin2
       }
     });
 
     return request;
   },
 
-  getServiceState: function(clientId, window, service) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    return new window.Promise((resolve, reject) => {
-      let requestId =
-        this.getPromiseResolverId({resolve: resolve, reject: reject});
-      this._windowsMap[requestId] = window;
-
-      cpmm.sendAsyncMessage("RIL:GetServiceState", {
-        clientId: clientId,
-        data: {
-          requestId: requestId,
-          service: service
-        }
-      });
-    });
-  },
-
   _iccListeners: null,
 
   registerListener: function(listenerType, clientId, listener) {
     if (!this[listenerType]) {
       return;
     }
     let listeners = this[listenerType][clientId];
     if (!listeners) {
@@ -716,72 +566,66 @@ RILContentHelper.prototype = {
     }
 
     let data = msg.json.data;
     let clientId = msg.json.clientId;
     switch (msg.name) {
       case "RIL:CardStateChanged":
         if (this.rilContexts[clientId].cardState != data.cardState) {
           this.rilContexts[clientId].cardState = data.cardState;
-          this._deliverEvent(clientId,
-                             "_iccListeners",
-                             "notifyCardStateChanged",
-                             null);
+          this._deliverIccEvent(clientId,
+                                "notifyCardStateChanged",
+                                null);
         }
         break;
       case "RIL:IccInfoChanged":
         this.updateIccInfo(clientId, data);
-        this._deliverEvent(clientId,
-                           "_iccListeners",
-                           "notifyIccInfoChanged",
-                           null);
+        this._deliverIccEvent(clientId,
+                              "notifyIccInfoChanged",
+                              null);
         break;
       case "RIL:GetCardLockResult": {
         let requestId = data.requestId;
-        let requestWindow = this._windowsMap[requestId];
-        delete this._windowsMap[requestId];
+        let callback = this._requestMap[requestId];
+        delete this._requestMap[requestId];
 
         if (data.errorMsg) {
-          this.fireRequestError(requestId, data.errorMsg);
+          callback.notifyError(data.errorMsg);
           break;
         }
 
-        this.fireRequestSuccess(requestId,
-                                Cu.cloneInto({ enabled: data.enabled },
-                                             requestWindow));
+        callback.notifySuccessWithBoolean(data.enabled);
         break;
       }
       case "RIL:SetUnlockCardLockResult": {
         let requestId = data.requestId;
-        let requestWindow = this._windowsMap[requestId];
-        delete this._windowsMap[requestId];
+        let callback = this._requestMap[requestId];
+        delete this._requestMap[requestId];
 
         if (data.errorMsg) {
-          let cardLockError = new requestWindow.IccCardLockError(data.errorMsg,
-                                                                 data.retryCount);
-          this.fireRequestDetailedError(requestId, cardLockError);
+          let retryCount =
+            (data.retryCount !== undefined) ? data.retryCount : -1;
+          callback.notifyCardLockError(data.errorMsg, retryCount);
           break;
         }
 
-        this.fireRequestSuccess(requestId, null);
+        callback.notifySuccess();
         break;
       }
       case "RIL:CardLockRetryCount": {
         let requestId = data.requestId;
-        let requestWindow = this._windowsMap[requestId];
-        delete this._windowsMap[requestId];
+        let callback = this._requestMap[requestId];
+        delete this._requestMap[requestId];
 
         if (data.errorMsg) {
-          this.fireRequestError(data.requestId, data.errorMsg);
+          callback.notifyError(data.errorMsg);
           break;
         }
 
-        this.fireRequestSuccess(data.requestId,
-                                Cu.cloneInto({ retryCount: data.retryCount },
-                                             requestWindow));
+        callback.notifyGetCardLockRetryCount(data.retryCount);
         break;
       }
       case "RIL:StkCommand":
         this._deliverEvent(clientId, "_iccListeners", "notifyStkCommand",
                            [JSON.stringify(data)]);
         break;
       case "RIL:StkSessionEnd":
         this._deliverEvent(clientId, "_iccListeners", "notifyStkSessionEnd", null);
@@ -796,22 +640,40 @@ RILContentHelper.prototype = {
         this.handleIccExchangeAPDU(data);
         break;
       case "RIL:ReadIccContacts":
         this.handleReadIccContacts(data);
         break;
       case "RIL:UpdateIccContact":
         this.handleUpdateIccContact(data);
         break;
-      case "RIL:MatchMvno":
-        this.handleSimpleRequest(data.requestId, data.errorMsg, data.result);
+      case "RIL:MatchMvno": {
+        let requestId = data.requestId;
+        let callback = this._requestMap[requestId];
+        delete this._requestMap[requestId];
+
+        if (data.errorMsg) {
+          callback.notifyError(data.errorMsg);
+          break;
+        }
+        callback.notifySuccessWithBoolean(data.result);
         break;
-      case "RIL:GetServiceState":
-        this.handleGetServiceState(data);
+      }
+      case "RIL:GetServiceState": {
+        let requestId = data.requestId;
+        let callback = this._requestMap[requestId];
+        delete this._requestMap[requestId];
+
+        if (data.errorMsg) {
+          callback.notifyError(data.errorMsg);
+          break;
+        }
+        callback.notifySuccessWithBoolean(data.result);
         break;
+      }
     }
   },
 
   handleSimpleRequest: function(requestId, errorMsg, result) {
     if (errorMsg) {
       this.fireRequestError(requestId, errorMsg);
     } else {
       this.fireRequestSuccess(requestId, result);
@@ -904,30 +766,16 @@ RILContentHelper.prototype = {
     }
 
     let contact = new window.mozContact(prop);
     contact.id = iccContact.contactId;
 
     this.fireRequestSuccess(message.requestId, contact);
   },
 
-  handleGetServiceState: function(message) {
-    let requestId = message.requestId;
-    let requestWindow = this._windowsMap[requestId];
-    delete this._windowsMap[requestId];
-
-    let resolver = this.takePromiseResolver(requestId);
-    if (message.errorMsg) {
-      resolver.reject(new requestWindow.DOMError(message.errorMsg));
-      return;
-    }
-
-    resolver.resolve(message.result);
-  },
-
   _deliverEvent: function(clientId, listenerType, name, args) {
     if (!this[listenerType]) {
       return;
     }
     let thisListeners = this[listenerType][clientId];
     if (!thisListeners) {
       return;
     }
@@ -942,12 +790,241 @@ RILContentHelper.prototype = {
         throw new Error("No handler for " + name);
       }
       try {
         handler.apply(listener, args);
       } catch (e) {
         if (DEBUG) debug("listener for " + name + " threw an exception: " + e);
       }
     }
+  },
+
+  /**
+   * nsIIccService interface.
+   */
+
+  _iccs: null, // An array of Icc instances.
+
+  getIccByServiceId: function(serviceId) {
+    let icc = this._iccs[serviceId];
+    if (!icc) {
+      throw Cr.NS_ERROR_UNEXPECTED;
+    }
+
+    return icc;
+  },
+
+  /**
+   * Bridge APIs from nsIIccService to nsIIccProvider
+   */
+
+  _deliverIccEvent: function(clientId, name, args) {
+    let icc = this._iccs[clientId];
+    if (!icc) {
+      if (DEBUG) debug("_deliverIccEvent: Invalid clientId: " + clientId);
+      return;
+    }
+
+    icc.deliverListenerEvent(name, args);
+  },
+
+  getIccInfo: function(clientId) {
+    let context = this.getRilContext(clientId);
+    return context && context.iccInfo;
+  },
+
+  getCardState: function(clientId) {
+    let context = this.getRilContext(clientId);
+    return context && context.cardState;
+  },
+
+  matchMvno: function(clientId, mvnoType, mvnoData, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:MatchMvno", {
+      clientId: clientId,
+      data: {
+        requestId: requestId,
+        mvnoType: mvnoType,
+        mvnoData: mvnoData
+      }
+    });
+  },
+
+  getCardLockEnabled: function(clientId, lockType, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:GetCardLockEnabled", {
+      clientId: clientId,
+      data: {
+        lockType: lockType,
+        requestId: requestId
+      }
+    });
+  },
+
+  unlockCardLock: function(clientId, lockType, password, newPin, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:UnlockCardLock", {
+      clientId: clientId,
+      data: {
+        lockType: lockType,
+        password: password,
+        newPin: newPin,
+        requestId: requestId
+      }
+    });
+  },
+
+  setCardLockEnabled: function(clientId, lockType, password, enabled, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:SetCardLockEnabled", {
+      clientId: clientId,
+      data: {
+        lockType: lockType,
+        password: password,
+        enabled: enabled,
+        requestId: requestId
+      }
+    });
+  },
+
+  changeCardLockPassword: function(clientId, lockType, password, newPassword,
+                                   callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:ChangeCardLockPassword", {
+      clientId: clientId,
+      data: {
+        lockType: lockType,
+        password: password,
+        newPassword: newPassword,
+        requestId: requestId
+      }
+    });
+  },
+
+  getCardLockRetryCount: function(clientId, lockType, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:GetCardLockRetryCount", {
+      clientId: clientId,
+      data: {
+        lockType: lockType,
+        requestId: requestId
+      }
+    });
+  },
+
+  getServiceStateEnabled: function(clientId, service, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:GetServiceState", {
+      clientId: clientId,
+      data: {
+        requestId: requestId,
+        service: service
+      }
+    });
+  }
+};
+
+function Icc(aIccProvider, aClientId) {
+  this._iccProvider = aIccProvider;
+  this._clientId = aClientId;
+  this._listeners = [];
+}
+Icc.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIIcc]),
+
+  _iccProvider: null,
+  _clientId: -1,
+  _listeners: null,
+
+  deliverListenerEvent: function(aName, aArgs) {
+    let listeners = this._listeners.slice();
+    for (let listener of listeners) {
+      if (this._listeners.indexOf(listener) === -1) {
+        continue;
+      }
+      let handler = listener[aName];
+      if (typeof handler != "function") {
+        throw new Error("No handler for " + aName);
+      }
+      try {
+        handler.apply(listener, aArgs);
+      } catch (e) {
+        if (DEBUG) {
+          debug("listener for " + aName + " threw an exception: " + e);
+        }
+      }
+    }
+  },
+
+  /**
+   * nsIIcc interface.
+   */
+  registerListener: function(aListener) {
+    if (this._listeners.indexOf(aListener) >= 0) {
+      throw Cr.NS_ERROR_UNEXPECTED;
+    }
+
+    this._listeners.push(aListener);
+    cpmm.sendAsyncMessage("RIL:RegisterIccMsg");
+  },
+
+  unregisterListener: function(aListener) {
+    let index = this._listeners.indexOf(aListener);
+    if (index >= 0) {
+      this._listeners.splice(index, 1);
+    }
+  },
+
+  get iccInfo() {
+    return this._iccProvider.getIccInfo(this._clientId);
+  },
+
+  get cardState() {
+    return this._iccProvider.getCardState(this._clientId);
+  },
+
+  getCardLockEnabled: function(aLockType, aCallback) {
+    this._iccProvider.getCardLockEnabled(this._clientId, aLockType, aCallback);
+  },
+
+  unlockCardLock: function(aLockType, aPassword, aNewPin, aCallback) {
+    this._iccProvider.unlockCardLock(this._clientId, aLockType,
+                                     aPassword, aNewPin, aCallback);
+  },
+
+  setCardLockEnabled: function(aLockType, aPassword, aEnabled, aCallback) {
+    this._iccProvider.setCardLockEnabled(this._clientId, aLockType,
+                                         aPassword, aEnabled, aCallback);
+  },
+
+  changeCardLockPassword: function(aLockType, aPassword, aNewPassword, aCallback) {
+    this._iccProvider.changeCardLockPassword(this._clientId, aLockType,
+                                             aPassword, aNewPassword, aCallback);
+  },
+
+  getCardLockRetryCount: function(aLockType, aCallback) {
+    this._iccProvider.getCardLockRetryCount(this._clientId, aLockType, aCallback);
+  },
+
+  matchMvno: function(aMvnoType, aMvnoData, aCallback) {
+    this._iccProvider.matchMvno(this._clientId, aMvnoType, aMvnoData, aCallback);
+  },
+
+  getServiceStateEnabled: function(aService, aCallback) {
+    this._iccProvider.getServiceStateEnabled(this._clientId, aService, aCallback);
   }
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RILContentHelper]);
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -1434,16 +1434,17 @@ function RadioInterfaceLayer() {
 RadioInterfaceLayer.prototype = {
 
   classID:   RADIOINTERFACELAYER_CID,
   classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACELAYER_CID,
                                     classDescription: "RadioInterfaceLayer",
                                     interfaces: [Ci.nsIRadioInterfaceLayer]}),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioInterfaceLayer,
+                                         Ci.nsIRadioInterfaceLayer_new,
                                          Ci.nsIObserver]),
 
   /**
    * nsIObserver interface methods.
    */
 
   observe: function(subject, topic, data) {
     switch (topic) {
--- a/dom/system/gonk/nsIRadioInterfaceLayer.idl
+++ b/dom/system/gonk/nsIRadioInterfaceLayer.idl
@@ -74,8 +74,18 @@ interface nsIRadioInterfaceLayer : nsISu
    * Select a proper client for dialing emergency call.
    *
    * @return clientId or -1 if none of the clients are avaialble.
    */
   unsigned long getClientIdForEmergencyCall();
 
   void setMicrophoneMuted(in boolean muted);
 };
+
+
+/**
+ * Helper Interface to define new APIs of nsIRadioInterfaceLayer during
+ * ril-interfaces frozen phase.
+ */
+[scriptable, uuid(f8ec63da-c22e-11e4-89f3-b767dae42a13)]
+interface nsIRadioInterfaceLayer_new : nsIRadioInterfaceLayer
+{
+};