Merge m-c to f-t
authorPhil Ringnalda <philringnalda@gmail.com>
Mon, 17 Feb 2014 15:27:12 -0800
changeset 169585 22892079a77598076ed1bc0296ecad73f0fa8e39
parent 169584 9765f6d4cad5fc1d532bf737efa3e95f621cc8b5 (current diff)
parent 169556 9ad86e91d6805a2d844d283c3a433c4f146cdd1d (diff)
child 169586 6e3ec93efe1d4154cb3e12d999b4730bac0b93bf
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone30.0a1
Merge m-c to f-t
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bf497b7adfaa4c087d492acf7f143a61b5ec08e9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae90f9b322509ee09fbd3963bd23e142845613ab"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bf497b7adfaa4c087d492acf7f143a61b5ec08e9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="ae90f9b322509ee09fbd3963bd23e142845613ab"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bf497b7adfaa4c087d492acf7f143a61b5ec08e9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae90f9b322509ee09fbd3963bd23e142845613ab"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "0818ccb401e793689adda5b6253e52fdeccba2f9", 
+    "revision": "1adfbae4582a2cebf4b35c822044299aa8dd1026", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bf497b7adfaa4c087d492acf7f143a61b5ec08e9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae90f9b322509ee09fbd3963bd23e142845613ab"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -5,17 +5,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bf497b7adfaa4c087d492acf7f143a61b5ec08e9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae90f9b322509ee09fbd3963bd23e142845613ab"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bf497b7adfaa4c087d492acf7f143a61b5ec08e9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae90f9b322509ee09fbd3963bd23e142845613ab"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bf497b7adfaa4c087d492acf7f143a61b5ec08e9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae90f9b322509ee09fbd3963bd23e142845613ab"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="97a5b461686757dbb8ecab2aac5903e41d2e1afe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="bf497b7adfaa4c087d492acf7f143a61b5ec08e9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="ae90f9b322509ee09fbd3963bd23e142845613ab"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bf497b7adfaa4c087d492acf7f143a61b5ec08e9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="ae90f9b322509ee09fbd3963bd23e142845613ab"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1000,18 +1000,23 @@ var gBrowserInit = {
       //                 [4]: allowThirdPartyFixup (bool)
       else if (window.arguments.length >= 3) {
         loadURI(uriToLoad, window.arguments[2], window.arguments[3] || null,
                 window.arguments[4] || false);
         window.focus();
       }
       // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
       // Such callers expect that window.arguments[0] is handled as a single URI.
-      else
+      else {
+        if (uriToLoad == "about:newtab" &&
+            Services.prefs.getBoolPref("browser.newtabpage.enabled")) {
+          Services.telemetry.getHistogramById("NEWTAB_PAGE_SHOWN").add(true);
+        }
         loadOneOrMoreURIs(uriToLoad);
+      }
     }
 
 #ifdef MOZ_SAFE_BROWSING
     // Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
     setTimeout(function() { SafeBrowsing.init(); }, 2000);
 #endif
 
     Services.obs.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false);
--- a/browser/base/content/newtab/page.js
+++ b/browser/base/content/newtab/page.js
@@ -80,16 +80,18 @@ let gPage = {
   _init: function Page_init() {
     if (this._initialized)
       return;
 
     this._initialized = true;
 
     this._mutationObserver = new MutationObserver(() => {
       if (this.allowBackgroundCaptures) {
+        Services.telemetry.getHistogramById("NEWTAB_PAGE_SHOWN").add(true);
+
         for (let site of gGrid.sites) {
           if (site) {
             site.captureIfMissing();
           }
         }
       }
     });
     this._mutationObserver.observe(document.documentElement, {
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -87,25 +87,19 @@
 @BINPATH@/plugin-hang-ui@BIN_SUFFIX@
 #ifndef MOZ_DEBUG
 #if MOZ_MSVC_REDIST == 1600
 @BINPATH@/msvcp100.dll
 @BINPATH@/msvcr100.dll
 #elif MOZ_MSVC_REDIST == 1700
 @BINPATH@/msvcp110.dll
 @BINPATH@/msvcr110.dll
-#ifdef MOZ_METRO
-@BINPATH@/vccorlib110.dll
-#endif
 #elif MOZ_MSVC_REDIST == 1800
 @BINPATH@/msvcp120.dll
 @BINPATH@/msvcr120.dll
-#ifdef MOZ_METRO
-@BINPATH@/vccorlib120.dll
-#endif
 #endif
 #endif
 #endif
 #ifndef MOZ_NATIVE_ICU
 #ifdef MOZ_SHARED_ICU
 #ifdef XP_WIN
 #ifdef MOZ_DEBUG
 @BINPATH@/icudtd@MOZ_ICU_VERSION@.dll
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -654,20 +654,24 @@ void MediaDecoderStateMachine::SendStrea
   if (mDecoder->IsSameOriginMedia()) {
     SourceMediaStream* mediaStream = stream->mStream;
     StreamTime endPosition = 0;
 
     if (!stream->mStreamInitialized) {
       if (mInfo.HasAudio()) {
         AudioSegment* audio = new AudioSegment();
         mediaStream->AddTrack(TRACK_AUDIO, mInfo.mAudio.mRate, 0, audio);
+        stream->mStream->DispatchWhenNotEnoughBuffered(TRACK_AUDIO,
+            GetStateMachineThread(), GetWakeDecoderRunnable());
       }
       if (mInfo.HasVideo()) {
         VideoSegment* video = new VideoSegment();
         mediaStream->AddTrack(TRACK_VIDEO, RATE_VIDEO, 0, video);
+        stream->mStream->DispatchWhenNotEnoughBuffered(TRACK_VIDEO,
+            GetStateMachineThread(), GetWakeDecoderRunnable());
       }
       stream->mStreamInitialized = true;
     }
 
     if (mInfo.HasAudio()) {
       nsAutoTArray<AudioData*,10> audio;
       // It's OK to hold references to the AudioData because while audio
       // is captured, only the decoder thread pops from the queue (see below).
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -2195,17 +2195,19 @@ SourceMediaStream::DispatchWhenNotEnough
   MutexAutoLock lock(mMutex);
   TrackData* data = FindDataForTrack(aID);
   if (!data) {
     aSignalThread->Dispatch(aSignalRunnable, 0);
     return;
   }
 
   if (data->mHaveEnough) {
-    data->mDispatchWhenNotEnough.AppendElement()->Init(aSignalThread, aSignalRunnable);
+    if (data->mDispatchWhenNotEnough.IsEmpty()) {
+      data->mDispatchWhenNotEnough.AppendElement()->Init(aSignalThread, aSignalRunnable);
+    }
   } else {
     aSignalThread->Dispatch(aSignalRunnable, 0);
   }
 }
 
 void
 SourceMediaStream::EndTrack(TrackID aID)
 {
--- a/content/media/MediaStreamGraph.h
+++ b/content/media/MediaStreamGraph.h
@@ -667,17 +667,17 @@ public:
    * Returns true if the buffer currently has enough data.
    * Returns false if there isn't enough data or if no such track exists.
    */
   bool HaveEnoughBuffered(TrackID aID);
   /**
    * Ensures that aSignalRunnable will be dispatched to aSignalThread
    * when we don't have enough buffered data in the track (which could be
    * immediately). Will dispatch the runnable immediately if the track
-   * does not exist.
+   * does not exist. No op if a runnable is already present for this track.
    */
   void DispatchWhenNotEnoughBuffered(TrackID aID,
       nsIThread* aSignalThread, nsIRunnable* aSignalRunnable);
   /**
    * Indicate that a track has ended. Do not do any more API calls
    * affecting this track.
    * Ignored if the track does not exist.
    */
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2254,21 +2254,21 @@ nsJSContext::EndCycleCollectionCallback(
     if (cs) {
       cs->LogStringMessage(msg.get());
     }
   }
 
   if (sPostGCEventsToObserver) {
     NS_NAMED_MULTILINE_LITERAL_STRING(kJSONFmt,
        MOZ_UTF16("{ \"timestamp\": %llu, ")
-         MOZ_UTF16("\"duration\": %llu, ")
-         MOZ_UTF16("\"max_slice_pause\": %llu, ")
-         MOZ_UTF16("\"total_slice_pause\": %llu, ")
-         MOZ_UTF16("\"max_finish_gc_duration\": %llu, ")
-         MOZ_UTF16("\"max_sync_skippable_duration\": %llu, ")
+         MOZ_UTF16("\"duration\": %lu, ")
+         MOZ_UTF16("\"max_slice_pause\": %lu, ")
+         MOZ_UTF16("\"total_slice_pause\": %lu, ")
+         MOZ_UTF16("\"max_finish_gc_duration\": %lu, ")
+         MOZ_UTF16("\"max_sync_skippable_duration\": %lu, ")
          MOZ_UTF16("\"suspected\": %lu, ")
          MOZ_UTF16("\"visited\": { ")
              MOZ_UTF16("\"RCed\": %lu, ")
              MOZ_UTF16("\"GCed\": %lu }, ")
          MOZ_UTF16("\"collected\": { ")
              MOZ_UTF16("\"RCed\": %lu, ")
              MOZ_UTF16("\"GCed\": %lu }, ")
          MOZ_UTF16("\"waiting_for_gc\": %lu, ")
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -1552,57 +1552,24 @@ DataConnectionHandler.prototype = {
    */
   handleDataCallList: function(message) {
     this._deliverDataCallCallback("receiveDataCallList",
                                   [message.datacalls, message.datacalls.length]);
   },
 };
 
 function RadioInterfaceLayer() {
-  let options = {
-    debug: debugPref,
-    cellBroadcastDisabled: false,
-    clirMode: RIL.CLIR_DEFAULT,
-    quirks: {
-      callstateExtraUint32:
-        libcutils.property_get("ro.moz.ril.callstate_extra_int", "false") === "true",
-      v5Legacy:
-        libcutils.property_get("ro.moz.ril.v5_legacy", "true") === "true",
-      requestUseDialEmergencyCall:
-        libcutils.property_get("ro.moz.ril.dial_emergency_call", "false") === "true",
-      simAppStateExtraFields:
-        libcutils.property_get("ro.moz.ril.simstate_extra_field", "false") === "true",
-      extraUint2ndCall:
-        libcutils.property_get("ro.moz.ril.extra_int_2nd_call", "false") == "true",
-      haveQueryIccLockRetryCount:
-        libcutils.property_get("ro.moz.ril.query_icc_count", "false") == "true",
-      sendStkProfileDownload:
-        libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") == "true",
-      dataRegistrationOnDemand:
-        libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") == "true"
-    },
-    rilEmergencyNumbers: libcutils.property_get("ril.ecclist") ||
-                         libcutils.property_get("ro.ril.ecclist")
-  };
-
-  try {
-    options.cellBroadcastDisabled =
-      Services.prefs.getBoolPref(kPrefCellBroadcastDisabled);
-  } catch(e) {}
-
-  try {
-    options.clirMode = Services.prefs.getIntPref(kPrefClirModePreference);
-  } catch(e) {}
+  let workerMessenger = new WorkerMessenger();
+  workerMessenger.init();
 
   let numIfaces = this.numRadioInterfaces;
   if (DEBUG) debug(numIfaces + " interfaces");
   this.radioInterfaces = [];
   for (let clientId = 0; clientId < numIfaces; clientId++) {
-    options.clientId = clientId;
-    this.radioInterfaces.push(new RadioInterface(options));
+    this.radioInterfaces.push(new RadioInterface(clientId, workerMessenger));
   }
 
   Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
 
   gMessageManager.init(this);
   gRadioEnabledController.init(this);
   gDataConnectionManager.init(this);
 }
@@ -1667,103 +1634,156 @@ XPCOMUtils.defineLazyGetter(RadioInterfa
                             "numRadioInterfaces", function() {
   try {
     return Services.prefs.getIntPref(kPrefRilNumRadioInterfaces);
   } catch(e) {}
 
   return 1;
 });
 
-function WorkerMessenger(radioInterface, options) {
+function WorkerMessenger() {
   // Initial owning attributes.
-  this.radioInterface = radioInterface;
+  this.radioInterfaces = [];
   this.tokenCallbackMap = {};
 
-  // Add a convenient alias to |radioInterface.debug()|.
-  this.debug = radioInterface.debug.bind(radioInterface);
-
-  if (DEBUG) this.debug("Starting RIL Worker[" + options.clientId + "]");
   this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js");
   this.worker.onerror = this.onerror.bind(this);
   this.worker.onmessage = this.onmessage.bind(this);
-
-  this.send("setInitialOptions", options);
-
-  gSystemWorkerManager.registerRilWorker(options.clientId, this.worker);
 }
 WorkerMessenger.prototype = {
-  radioInterface: null,
+  radioInterfaces: null,
   worker: null,
 
   // This gets incremented each time we send out a message.
   token: 1,
 
   // Maps tokens we send out with messages to the message callback.
   tokenCallbackMap: null,
 
+  init: function() {
+    let options = {
+      debug: DEBUG,
+      cellBroadcastDisabled: false,
+      clirMode: RIL.CLIR_DEFAULT,
+      quirks: {
+        callstateExtraUint32:
+          libcutils.property_get("ro.moz.ril.callstate_extra_int", "false") === "true",
+        v5Legacy:
+          libcutils.property_get("ro.moz.ril.v5_legacy", "true") === "true",
+        requestUseDialEmergencyCall:
+          libcutils.property_get("ro.moz.ril.dial_emergency_call", "false") === "true",
+        simAppStateExtraFields:
+          libcutils.property_get("ro.moz.ril.simstate_extra_field", "false") === "true",
+        extraUint2ndCall:
+          libcutils.property_get("ro.moz.ril.extra_int_2nd_call", "false") == "true",
+        haveQueryIccLockRetryCount:
+          libcutils.property_get("ro.moz.ril.query_icc_count", "false") == "true",
+        sendStkProfileDownload:
+          libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") == "true",
+        dataRegistrationOnDemand:
+          libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") == "true"
+      },
+      rilEmergencyNumbers: libcutils.property_get("ril.ecclist") ||
+                           libcutils.property_get("ro.ril.ecclist")
+    };
+
+    try {
+      options.cellBroadcastDisabled =
+        Services.prefs.getBoolPref(kPrefCellBroadcastDisabled);
+    } catch(e) {}
+
+    try {
+      options.clirMode = Services.prefs.getIntPref(kPrefClirModePreference);
+    } catch(e) {}
+
+    this.send(null, "setInitialOptions", options);
+  },
+
+  debug: function(aClientId, aMessage) {
+    // We use the same debug subject with RadioInterface's here.
+    dump("-*- RadioInterface[" + aClientId + "]: " + aMessage + "\n");
+  },
+
   onerror: function(event) {
     if (DEBUG) {
-      this.debug("Got an error: " + event.filename + ":" +
+      this.debug("X", "Got an error: " + event.filename + ":" +
                  event.lineno + ": " + event.message + "\n");
     }
     event.preventDefault();
   },
 
   /**
    * Process the incoming message from the RIL worker.
    */
   onmessage: function(event) {
     let message = event.data;
+    let clientId = message.rilMessageClientId;
+    if (clientId === null) {
+      return;
+    }
+
     if (DEBUG) {
-      this.debug("Received message from worker: " + JSON.stringify(message));
+      this.debug(clientId, "Received message from worker: " + JSON.stringify(message));
     }
 
     let token = message.rilMessageToken;
     if (token == null) {
       // That's an unsolicited message.  Pass to RadioInterface directly.
-      this.radioInterface.handleUnsolicitedWorkerMessage(message);
+      let radioInterface = this.radioInterfaces[clientId];
+      radioInterface.handleUnsolicitedWorkerMessage(message);
       return;
     }
 
     let callback = this.tokenCallbackMap[message.rilMessageToken];
     if (!callback) {
-      if (DEBUG) this.debug("Ignore orphan token: " + message.rilMessageToken);
+      if (DEBUG) this.debug(clientId, "Ignore orphan token: " + message.rilMessageToken);
       return;
     }
 
     let keep = false;
     try {
       keep = callback(message);
     } catch(e) {
-      if (DEBUG) this.debug("callback throws an exception: " + e);
+      if (DEBUG) this.debug(clientId, "callback throws an exception: " + e);
     }
 
     if (!keep) {
       delete this.tokenCallbackMap[message.rilMessageToken];
     }
   },
 
+  registerClient: function(aClientId, aRadioInterface) {
+    if (DEBUG) this.debug(aClientId, "Starting RIL Worker");
+
+    // Keep a reference so that we can dispatch unsolicited messages to it.
+    this.radioInterfaces[aClientId] = aRadioInterface;
+
+    this.send(null, "registerClient", { clientId: aClientId });
+    gSystemWorkerManager.registerRilWorker(aClientId, this.worker);
+  },
+
   /**
    * Send arbitrary message to worker.
    *
    * @param rilMessageType
    *        A text message type.
    * @param message [optional]
    *        An optional message object to send.
    * @param callback [optional]
    *        An optional callback function which is called when worker replies
    *        with an message containing a "rilMessageToken" attribute of the
    *        same value we passed.  This callback function accepts only one
    *        parameter -- the reply from worker.  It also returns a boolean
    *        value true to keep current token-callback mapping and wait for
    *        another worker reply, or false to remove the mapping.
    */
-  send: function(rilMessageType, message, callback) {
+  send: function(clientId, rilMessageType, message, callback) {
     message = message || {};
 
+    message.rilMessageClientId = clientId;
     message.rilMessageToken = this.token;
     this.token++;
 
     if (callback) {
       // Only create the map if callback is provided.  For sending a request
       // and intentionally leaving the callback undefined, that reply will
       // be dropped in |this.onmessage| because of that orphan token.
       //
@@ -1784,31 +1804,36 @@ WorkerMessenger.prototype = {
    *        A message object from ppmm.
    * @param rilMessageType
    *        A text string for worker message type.
    * @param ipcType [optinal]
    *        A text string for ipc message type. "msg.name" if omitted.
    *
    * @TODO: Bug 815526 - deprecate RILContentHelper.
    */
-  sendWithIPCMessage: function(msg, rilMessageType, ipcType) {
-    this.send(rilMessageType, msg.json.data, (function(reply) {
+  sendWithIPCMessage: function(clientId, msg, rilMessageType, ipcType) {
+    this.send(clientId, rilMessageType, msg.json.data, (function(reply) {
       ipcType = ipcType || msg.name;
       msg.target.sendAsyncMessage(ipcType, {
-        clientId: this.radioInterface.clientId,
+        clientId: clientId,
         data: reply
       });
       return false;
     }).bind(this));
   }
 };
 
-function RadioInterface(options) {
-  this.clientId = options.clientId;
-  this.workerMessenger = new WorkerMessenger(this, options);
+function RadioInterface(aClientId, aWorkerMessenger) {
+  this.clientId = aClientId;
+  this.workerMessenger = {
+    send: aWorkerMessenger.send.bind(aWorkerMessenger, aClientId),
+    sendWithIPCMessage:
+      aWorkerMessenger.sendWithIPCMessage.bind(aWorkerMessenger, aClientId),
+  };
+  aWorkerMessenger.registerClient(aClientId, this);
 
   this.supportedNetworkTypes = this.getSupportedNetworkTypes();
 
   this.rilContext = {
     radioState:     RIL.GECKO_RADIOSTATE_UNAVAILABLE,
     detailedRadioState: null,
     cardState:      RIL.GECKO_CARDSTATE_UNKNOWN,
     networkSelectionMode: RIL.GECKO_NETWORK_SELECTION_UNKNOWN,
@@ -1891,17 +1916,17 @@ RadioInterface.prototype = {
   classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACE_CID,
                                     classDescription: "RadioInterface",
                                     interfaces: [Ci.nsIRadioInterface]}),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioInterface,
                                          Ci.nsIObserver,
                                          Ci.nsISettingsServiceCallback]),
 
-  // A private WorkerMessenger instance.
+  // A private wrapped WorkerMessenger instance.
   workerMessenger: null,
 
   debug: function(s) {
     dump("-*- RadioInterface[" + this.clientId + "]: " + s + "\n");
   },
 
   shutdown: function() {
     // Release the CPU wake lock for handling the received SMS.
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -38,26 +38,27 @@
 
 "use strict";
 
 importScripts("ril_consts.js");
 importScripts("resource://gre/modules/workers/require.js");
 
 // set to true in ril_consts.js to see debug messages
 let DEBUG = DEBUG_WORKER;
-let CLIENT_ID = -1;
 let GLOBAL = this;
 
 if (!this.debug) {
   // Debugging stub that goes nowhere.
   this.debug = function debug(message) {
-    dump("RIL Worker[" + CLIENT_ID + "]: " + message + "\n");
+    dump("RIL Worker: " + message + "\n");
   };
 }
 
+let RIL_CELLBROADCAST_DISABLED;
+let RIL_CLIR_MODE;
 let RIL_EMERGENCY_NUMBERS;
 const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"];
 
 // Timeout value for emergency callback mode.
 const EMERGENCY_CB_MODE_TIMEOUT_MS = 300000;  // 5 mins = 300000 ms.
 
 const ICC_MAX_LINEAR_FIXED_RECORDS = 0xfe;
 
@@ -87,23 +88,21 @@ let RILQUIRKS_EXTRA_UINT32_2ND_CALL;
 let RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT;
 
 // Ril quirk to Send STK Profile Download
 let RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD;
 
 // Ril quirk to attach data registration on demand.
 let RILQUIRKS_DATA_REGISTRATION_ON_DEMAND;
 
-// Marker object.
-let PENDING_NETWORK_TYPE = {};
-
-let Buf = {
-  __proto__: (function(){
-    return require("resource://gre/modules/workers/worker_buf.js").Buf;
-  })(),
+function BufObject(aContext) {
+  this.context = aContext;
+}
+BufObject.prototype = {
+  context: null,
 
   mToken: 0,
   mTokenRequestMap: null,
 
   init: function() {
     this._init();
 
     // This gets incremented each time we send out a parcel.
@@ -123,51 +122,56 @@ let Buf = {
     let request_type, options;
     if (response_type == RESPONSE_TYPE_SOLICITED) {
       let token = this.readInt32();
       let error = this.readInt32();
 
       options = this.mTokenRequestMap.get(token);
       if (!options) {
         if (DEBUG) {
-          debug("Suspicious uninvited request found: " + token + ". Ignored!");
+          this.context.debug("Suspicious uninvited request found: " +
+                             token + ". Ignored!");
         }
         return;
       }
 
       this.mTokenRequestMap.delete(token);
       request_type = options.rilRequestType;
 
       options.rilRequestError = error;
       if (DEBUG) {
-        debug("Solicited response for request type " + request_type +
-              ", token " + token + ", error " + error);
+        this.context.debug("Solicited response for request type " + request_type +
+                           ", token " + token + ", error " + error);
       }
     } else if (response_type == RESPONSE_TYPE_UNSOLICITED) {
       request_type = this.readInt32();
-      if (DEBUG) debug("Unsolicited response for request type " + request_type);
+      if (DEBUG) {
+        this.context.debug("Unsolicited response for request type " + request_type);
+      }
     } else {
-      if (DEBUG) debug("Unknown response type: " + response_type);
+      if (DEBUG) {
+        this.context.debug("Unknown response type: " + response_type);
+      }
       return;
     }
 
-    RIL.handleParcel(request_type, this.readAvailable, options);
+    this.context.RIL.handleParcel(request_type, this.readAvailable, 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(type, options) {
-    if (DEBUG) debug("New outgoing parcel of type " + type);
+    if (DEBUG) this.context.debug("New outgoing parcel of type " + type);
 
     // We're going to leave room for the parcel size at the beginning.
     this.outgoingIndex = this.PARCEL_SIZE_SIZE;
     this.writeInt32(type);
     this.writeInt32(this.mToken);
 
     if (!options) {
       options = {};
@@ -180,79 +184,111 @@ let Buf = {
   },
 
   simpleRequest: function(type, options) {
     this.newParcel(type, options);
     this.sendParcel();
   },
 
   onSendParcel: function(parcel) {
-    postRILMessage(CLIENT_ID, parcel);
-  }
-};
+    postRILMessage(this.context.clientId, parcel);
+  }
+};
+
+(function() {
+  let base = require("resource://gre/modules/workers/worker_buf.js").Buf;
+  for (let p in base) {
+    BufObject.prototype[p] = base[p];
+  }
+})();
 
 /**
  * The RIL state machine.
  *
  * This object communicates with rild via parcels and with the main thread
  * via post messages. It maintains state about the radio, ICC, calls, etc.
  * and acts upon state changes accordingly.
  */
-let RIL = {
+function RilObject(aContext) {
+  this.context = aContext;
+
+  this.currentCalls = {};
+  this.currentConference = {state: null, participants: {}};
+  this.currentDataCalls = {};
+  this._receivedSmsSegmentsMap = {};
+  this._pendingSentSmsMap = {};
+  this.pendingNetworkType = {};
+  this._receivedSmsCbPagesMap = {};
+
+  // Init properties that are only initialized once.
+  this.v5Legacy = RILQUIRKS_V5_LEGACY;
+  this.cellBroadcastDisabled = RIL_CELLBROADCAST_DISABLED;
+  this.clirMode = RIL_CLIR_MODE;
+}
+RilObject.prototype = {
+  context: null,
+
+  v5Legacy: null,
+
   /**
    * Valid calls.
    */
-  currentCalls: {},
+  currentCalls: null,
 
   /**
    * Existing conference call and its participants.
    */
-  currentConference: {state: null, participants: {}},
+  currentConference: null,
 
   /**
    * Existing data calls.
    */
-  currentDataCalls: {},
+  currentDataCalls: null,
 
   /**
    * Hash map for received multipart sms fragments. Messages are hashed with
    * its sender address and concatenation reference number. Three additional
    * attributes `segmentMaxSeq`, `receivedSegments`, `segments` are inserted.
    */
-  _receivedSmsSegmentsMap: {},
+  _receivedSmsSegmentsMap: null,
 
   /**
    * Outgoing messages waiting for SMS-STATUS-REPORT.
    */
-  _pendingSentSmsMap: {},
+  _pendingSentSmsMap: null,
 
   /**
    * Index of the RIL_PREFERRED_NETWORK_TYPE_TO_GECKO. Its value should be
    * preserved over rild reset.
    */
   preferredNetworkType: null,
 
   /**
+   * Marker object.
+   */
+  pendingNetworkType: null,
+
+  /**
    * Global Cell Broadcast switch.
    */
   cellBroadcastDisabled: false,
 
   /**
    * Global CLIR mode settings.
    */
   clirMode: CLIR_DEFAULT,
 
   /**
    * Parsed Cell Broadcast search lists.
    * cellBroadcastConfigs.MMI should be preserved over rild reset.
    */
   cellBroadcastConfigs: null,
   mergedCellBroadcastConfig: null,
 
-  _receivedSmsCbPagesMap: {},
+  _receivedSmsCbPagesMap: null,
 
   initRILState: function() {
     /**
      * One of the RADIO_STATE_* constants.
      */
     this.radioState = GECKO_RADIOSTATE_UNAVAILABLE;
 
     /**
@@ -425,17 +461,17 @@ let RIL = {
    * an object, which then contains all of the parameters as attributes.
    * The "@param" documentation is to be interpreted accordingly.
    */
 
   /**
    * Retrieve the ICC's status.
    */
   getICCStatus: function() {
-    Buf.simpleRequest(REQUEST_GET_SIM_STATUS);
+    this.context.Buf.simpleRequest(REQUEST_GET_SIM_STATUS);
   },
 
   /**
    * Helper function for unlocking ICC locks.
    */
   iccUnlockCardLock: function(options) {
     switch (options.lockType) {
       case GECKO_CARDLOCK_PIN:
@@ -475,52 +511,55 @@ let RIL = {
    * Enter a PIN to unlock the ICC.
    *
    * @param pin
    *        String containing the PIN.
    * @param [optional] aid
    *        AID value.
    */
   enterICCPIN: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_ENTER_SIM_PIN, options);
-    Buf.writeInt32(RILQUIRKS_V5_LEGACY ? 1 : 2);
+    Buf.writeInt32(this.v5Legacy ? 1 : 2);
     Buf.writeString(options.pin);
-    if (!RILQUIRKS_V5_LEGACY) {
+    if (!this.v5Legacy) {
       Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
 
   /**
    * Enter a PIN2 to unlock the ICC.
    *
    * @param pin
    *        String containing the PIN2.
    * @param [optional] aid
    *        AID value.
    */
   enterICCPIN2: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_ENTER_SIM_PIN2, options);
-    Buf.writeInt32(RILQUIRKS_V5_LEGACY ? 1 : 2);
+    Buf.writeInt32(this.v5Legacy ? 1 : 2);
     Buf.writeString(options.pin);
-    if (!RILQUIRKS_V5_LEGACY) {
+    if (!this.v5Legacy) {
       Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
 
   /**
    * Requests a network personalization be deactivated.
    *
    * @param type
    *        Integer indicating the network personalization be deactivated.
    * @param password
    *        String containing the password.
    */
   enterDepersonalization: function(type, password, options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE, options);
     Buf.writeInt32(type);
     Buf.writeString(password);
     Buf.sendParcel();
   },
 
   /**
    * Helper function for changing ICC locks.
@@ -569,83 +608,87 @@ let RIL = {
    * @param pin
    *        String containing the old PIN value
    * @param newPin
    *        String containing the new PIN value
    * @param [optional] aid
    *        AID value.
    */
   changeICCPIN: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_CHANGE_SIM_PIN, options);
-    Buf.writeInt32(RILQUIRKS_V5_LEGACY ? 2 : 3);
+    Buf.writeInt32(this.v5Legacy ? 2 : 3);
     Buf.writeString(options.pin);
     Buf.writeString(options.newPin);
-    if (!RILQUIRKS_V5_LEGACY) {
+    if (!this.v5Legacy) {
       Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
 
   /**
    * Change the current ICC PIN2 number.
    *
    * @param pin
    *        String containing the old PIN2 value
    * @param newPin
    *        String containing the new PIN2 value
    * @param [optional] aid
    *        AID value.
    */
   changeICCPIN2: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_CHANGE_SIM_PIN2, options);
-    Buf.writeInt32(RILQUIRKS_V5_LEGACY ? 2 : 3);
+    Buf.writeInt32(this.v5Legacy ? 2 : 3);
     Buf.writeString(options.pin);
     Buf.writeString(options.newPin);
-    if (!RILQUIRKS_V5_LEGACY) {
+    if (!this.v5Legacy) {
       Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
   /**
    * Supplies ICC PUK and a new PIN to unlock the ICC.
    *
    * @param puk
    *        String containing the PUK value.
    * @param newPin
    *        String containing the new PIN value.
    * @param [optional] aid
    *        AID value.
    */
    enterICCPUK: function(options) {
+     let Buf = this.context.Buf;
      Buf.newParcel(REQUEST_ENTER_SIM_PUK, options);
-     Buf.writeInt32(RILQUIRKS_V5_LEGACY ? 2 : 3);
+     Buf.writeInt32(this.v5Legacy ? 2 : 3);
      Buf.writeString(options.puk);
      Buf.writeString(options.newPin);
-     if (!RILQUIRKS_V5_LEGACY) {
+     if (!this.v5Legacy) {
        Buf.writeString(options.aid || this.aid);
      }
      Buf.sendParcel();
    },
 
   /**
    * Supplies ICC PUK2 and a new PIN2 to unlock the ICC.
    *
    * @param puk
    *        String containing the PUK2 value.
    * @param newPin
    *        String containing the new PIN2 value.
    * @param [optional] aid
    *        AID value.
    */
    enterICCPUK2: function(options) {
+     let Buf = this.context.Buf;
      Buf.newParcel(REQUEST_ENTER_SIM_PUK2, options);
-     Buf.writeInt32(RILQUIRKS_V5_LEGACY ? 2 : 3);
+     Buf.writeInt32(this.v5Legacy ? 2 : 3);
      Buf.writeString(options.puk);
      Buf.writeString(options.newPin);
-     if (!RILQUIRKS_V5_LEGACY) {
+     if (!this.v5Legacy) {
        Buf.writeString(options.aid || this.aid);
      }
      Buf.sendParcel();
    },
 
   /**
    * Helper function for fetching the state of ICC locks.
    */
@@ -712,16 +755,17 @@ let RIL = {
    * Query ICC lock retry count.
    *
    * @param selCode
    *        One of ICC_SEL_CODE_*.
    * @param serviceClass
    *        One of ICC_SERVICE_CLASS_*.
    */
   queryICCLockRetryCount: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_GET_UNLOCK_RETRY_COUNT, options);
     Buf.writeInt32(1);
     Buf.writeString(options.selCode);
     Buf.sendParcel();
   },
 
   /**
    * Query ICC facility lock.
@@ -731,22 +775,23 @@ let RIL = {
    * @param password
    *        Password for the facility, or "" if not required.
    * @param serviceClass
    *        One of ICC_SERVICE_CLASS_*.
    * @param [optional] aid
    *        AID value.
    */
   queryICCFacilityLock: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_QUERY_FACILITY_LOCK, options);
-    Buf.writeInt32(RILQUIRKS_V5_LEGACY ? 3 : 4);
+    Buf.writeInt32(this.v5Legacy ? 3 : 4);
     Buf.writeString(options.facility);
     Buf.writeString(options.password);
     Buf.writeString(options.serviceClass.toString());
-    if (!RILQUIRKS_V5_LEGACY) {
+    if (!this.v5Legacy) {
       Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
 
   /**
    * Set ICC facility lock.
    *
@@ -757,23 +802,24 @@ let RIL = {
    * @param password
    *        Password for the facility, or "" if not required.
    * @param serviceClass
    *        One of ICC_SERVICE_CLASS_*.
    * @param [optional] aid
    *        AID value.
    */
   setICCFacilityLock: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SET_FACILITY_LOCK, options);
-    Buf.writeInt32(RILQUIRKS_V5_LEGACY ? 4 : 5);
+    Buf.writeInt32(this.v5Legacy ? 4 : 5);
     Buf.writeString(options.facility);
     Buf.writeString(options.enabled ? "1" : "0");
     Buf.writeString(options.password);
     Buf.writeString(options.serviceClass.toString());
-    if (!RILQUIRKS_V5_LEGACY) {
+    if (!this.v5Legacy) {
       Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
 
   /**
    *  Request an ICC I/O operation.
    *
@@ -792,16 +838,17 @@ let RIL = {
    *  @param [optional] dataWriter
    *         The function for writing string parameter for the ICC_COMMAND_UPDATE_RECORD.
    *  @param [optional] pin2
    *         String containing the PIN2.
    *  @param [optional] aid
    *         AID value.
    */
   iccIO: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SIM_IO, options);
     Buf.writeInt32(options.command);
     Buf.writeInt32(options.fileId);
     Buf.writeString(options.pathId);
     Buf.writeInt32(options.p1);
     Buf.writeInt32(options.p2);
     Buf.writeInt32(options.p3);
 
@@ -816,30 +863,31 @@ let RIL = {
     // Write pin2.
     if (options.command == ICC_COMMAND_UPDATE_RECORD &&
         options.pin2) {
       Buf.writeString(options.pin2);
     } else {
       Buf.writeString(null);
     }
 
-    if (!RILQUIRKS_V5_LEGACY) {
+    if (!this.v5Legacy) {
       Buf.writeString(options.aid || this.aid);
     }
     Buf.sendParcel();
   },
 
   /**
    * Get IMSI.
    *
    * @param [optional] aid
    *        AID value.
    */
   getIMSI: function(aid) {
-    if (RILQUIRKS_V5_LEGACY) {
+    let Buf = this.context.Buf;
+    if (this.v5Legacy) {
       Buf.simpleRequest(REQUEST_GET_IMSI);
       return;
     }
     Buf.newParcel(REQUEST_GET_IMSI);
     Buf.writeInt32(1);
     Buf.writeString(aid || this.aid);
     Buf.sendParcel();
   },
@@ -854,33 +902,33 @@ let RIL = {
    */
   readICCContacts: function(options) {
     if (!this.appType) {
       options.errorMsg = CONTACT_ERR_REQUEST_NOT_SUPPORTED;
       this.sendChromeMessage(options);
       return;
     }
 
-    ICCContactHelper.readICCContacts(
+    this.context.ICCContactHelper.readICCContacts(
       this.appType,
       options.contactType,
       function onsuccess(contacts) {
         for (let i = 0; i < contacts.length; i++) {
           let contact = contacts[i];
           let pbrIndex = contact.pbrIndex || 0;
           let recordIndex = pbrIndex * ICC_MAX_LINEAR_FIXED_RECORDS + contact.recordId;
           contact.contactId = this.iccInfo.iccid + recordIndex;
         }
         // Reuse 'options' to get 'requestId' and 'contactType'.
         options.contacts = contacts;
-        RIL.sendChromeMessage(options);
+        this.sendChromeMessage(options);
       }.bind(this),
       function onerror(errorMsg) {
         options.errorMsg = errorMsg;
-        RIL.sendChromeMessage(options);
+        this.sendChromeMessage(options);
       }.bind(this));
   },
 
   /**
    * Update UICC Phonebook.
    *
    * @param contactType   "adn" or "fdn".
    * @param contact       The contact will be updated.
@@ -888,44 +936,45 @@ let RIL = {
    * @param requestId     Request id from RadioInterfaceLayer.
    */
   updateICCContact: function(options) {
     let onsuccess = function onsuccess() {
       let recordIndex =
         contact.pbrIndex * ICC_MAX_LINEAR_FIXED_RECORDS + contact.recordId;
       contact.contactId = this.iccInfo.iccid + recordIndex;
       // Reuse 'options' to get 'requestId' and 'contactType'.
-      RIL.sendChromeMessage(options);
+      this.sendChromeMessage(options);
     }.bind(this);
 
     let onerror = function onerror(errorMsg) {
       options.errorMsg = errorMsg;
-      RIL.sendChromeMessage(options);
+      this.sendChromeMessage(options);
     }.bind(this);
 
     if (!this.appType || !options.contact) {
       onerror(CONTACT_ERR_REQUEST_NOT_SUPPORTED );
       return;
     }
 
     let contact = options.contact;
-    let iccid = RIL.iccInfo.iccid;
+    let iccid = this.iccInfo.iccid;
     let isValidRecordId = false;
     if (typeof contact.contactId === "string" &&
         contact.contactId.startsWith(iccid)) {
       let recordIndex = contact.contactId.substring(iccid.length);
       contact.pbrIndex = Math.floor(recordIndex / ICC_MAX_LINEAR_FIXED_RECORDS);
       contact.recordId = recordIndex % ICC_MAX_LINEAR_FIXED_RECORDS;
       isValidRecordId = contact.recordId > 0 && contact.recordId < 0xff;
     }
 
     if (DEBUG) {
-      debug("Update ICC Contact " + JSON.stringify(contact));
-    }
-
+      this.context.debug("Update ICC Contact " + JSON.stringify(contact));
+    }
+
+    let ICCContactHelper = this.context.ICCContactHelper;
     // If contact has 'recordId' property, updates corresponding record.
     // If not, inserts the contact into a free record.
     if (isValidRecordId) {
       ICCContactHelper.updateICCContact(
         this.appType, options.contactType, contact, options.pin2, onsuccess, onerror);
     } else {
       ICCContactHelper.addICCContact(
         this.appType, options.contactType, contact, options.pin2, onsuccess, onerror);
@@ -934,26 +983,29 @@ let RIL = {
 
   /**
    * Request the phone's radio to be enabled or disabled.
    *
    * @param enabled
    *        Boolean indicating the desired state.
    */
   setRadioEnabled: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_RADIO_POWER, options);
     Buf.writeInt32(1);
     Buf.writeInt32(options.enabled ? 1 : 0);
     Buf.sendParcel();
   },
 
   /**
    * Query call waiting status via MMI.
    */
   _handleQueryMMICallWaiting: function(options) {
+    let Buf = this.context.Buf;
+
     function callback(options) {
       options.length = Buf.readInt32();
       options.enabled = (Buf.readInt32() === 1);
       let services = Buf.readInt32();
       if (options.enabled) {
         options.statusMessage = MMI_SM_KS_SERVICE_ENABLED_FOR;
         let serviceClass = [];
         for (let serviceClassMask = 1;
@@ -997,102 +1049,106 @@ let RIL = {
     this.setCallWaiting(options);
   },
 
   /**
    * Query call waiting status.
    *
    */
   queryCallWaiting: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_QUERY_CALL_WAITING, options);
     Buf.writeInt32(1);
     // As per 3GPP TS 24.083, section 1.6 UE doesn't need to send service
     // class parameter in call waiting interrogation  to network
     Buf.writeInt32(ICC_SERVICE_CLASS_NONE);
     Buf.sendParcel();
   },
 
   /**
    * Set call waiting status.
    *
    * @param on
    *        Boolean indicating the desired waiting status.
    */
   setCallWaiting: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SET_CALL_WAITING, options);
     Buf.writeInt32(2);
     Buf.writeInt32(options.enabled ? 1 : 0);
     Buf.writeInt32(options.serviceClass !== undefined ?
                     options.serviceClass : ICC_SERVICE_CLASS_VOICE);
     Buf.sendParcel();
   },
 
   /**
    * Queries current CLIP status.
    *
    * (MMI request for code "*#30#")
    *
    */
   queryCLIP: function(options) {
-    Buf.simpleRequest(REQUEST_QUERY_CLIP, options);
+    this.context.Buf.simpleRequest(REQUEST_QUERY_CLIP, options);
   },
 
   /**
    * Queries current CLIR status.
    *
    */
   getCLIR: function(options) {
-    Buf.simpleRequest(REQUEST_GET_CLIR, options);
+    this.context.Buf.simpleRequest(REQUEST_GET_CLIR, options);
   },
 
   /**
    * Enables or disables the presentation of the calling line identity (CLI) to
    * the called party when originating a call.
    *
    * @param options.clirMode
    *        Is one of the CLIR_* constants in
    *        nsIDOMMozMobileConnection interface.
    */
   setCLIR: function(options) {
     if (options) {
       this.clirMode = options.clirMode;
     }
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SET_CLIR, options);
     Buf.writeInt32(1);
     Buf.writeInt32(this.clirMode);
     Buf.sendParcel();
   },
 
   /**
    * Set screen state.
    *
    * @param on
    *        Boolean indicating whether the screen should be on or off.
    */
   setScreenState: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SCREEN_STATE);
     Buf.writeInt32(1);
     Buf.writeInt32(options.on ? 1 : 0);
     Buf.sendParcel();
   },
 
   getVoiceRegistrationState: function() {
-    Buf.simpleRequest(REQUEST_VOICE_REGISTRATION_STATE);
+    this.context.Buf.simpleRequest(REQUEST_VOICE_REGISTRATION_STATE);
   },
 
   getVoiceRadioTechnology: function() {
-    Buf.simpleRequest(REQUEST_VOICE_RADIO_TECH);
+    this.context.Buf.simpleRequest(REQUEST_VOICE_RADIO_TECH);
   },
 
   getDataRegistrationState: function() {
-    Buf.simpleRequest(REQUEST_DATA_REGISTRATION_STATE);
+    this.context.Buf.simpleRequest(REQUEST_DATA_REGISTRATION_STATE);
   },
 
   getOperator: function() {
-    Buf.simpleRequest(REQUEST_OPERATOR);
+    this.context.Buf.simpleRequest(REQUEST_OPERATOR);
   },
 
   /**
    * Set the preferred network type.
    *
    * @param options An object contains a valid index of
    *                RIL_PREFERRED_NETWORK_TYPE_TO_GECKO as its `networkType`
    *                attribute, or undefined to set current preferred network
@@ -1101,146 +1157,155 @@ let RIL = {
   setPreferredNetworkType: function(options) {
     if (options) {
       this.preferredNetworkType = options.networkType;
     }
     if (this.preferredNetworkType == null) {
       return;
     }
 
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SET_PREFERRED_NETWORK_TYPE, options);
     Buf.writeInt32(1);
     Buf.writeInt32(this.preferredNetworkType);
     Buf.sendParcel();
   },
 
   /**
    * Get the preferred network type.
    */
   getPreferredNetworkType: function(options) {
-    Buf.simpleRequest(REQUEST_GET_PREFERRED_NETWORK_TYPE, options);
+    this.context.Buf.simpleRequest(REQUEST_GET_PREFERRED_NETWORK_TYPE, options);
   },
 
   /**
    * Request various states about the network.
    */
   requestNetworkInfo: function() {
     if (this._processingNetworkInfo) {
-      if (DEBUG) debug("Network info requested, but we're already requesting network info.");
+      if (DEBUG) {
+        this.context.debug("Network info requested, but we're already " +
+                           "requesting network info.");
+      }
       this._needRepollNetworkInfo = true;
       return;
     }
 
-    if (DEBUG) debug("Requesting network info");
+    if (DEBUG) this.context.debug("Requesting network info");
 
     this._processingNetworkInfo = true;
     this.getVoiceRegistrationState();
     this.getDataRegistrationState(); //TODO only GSM
     this.getOperator();
     this.getNetworkSelectionMode();
     this.getSignalStrength();
   },
 
   /**
    * Get the available networks
    */
   getAvailableNetworks: function(options) {
-    if (DEBUG) debug("Getting available networks");
+    if (DEBUG) this.context.debug("Getting available networks");
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_QUERY_AVAILABLE_NETWORKS, options);
     Buf.sendParcel();
   },
 
   /**
    * Request the radio's network selection mode
    */
   getNetworkSelectionMode: function() {
-    if (DEBUG) debug("Getting network selection mode");
-    Buf.simpleRequest(REQUEST_QUERY_NETWORK_SELECTION_MODE);
+    if (DEBUG) this.context.debug("Getting network selection mode");
+    this.context.Buf.simpleRequest(REQUEST_QUERY_NETWORK_SELECTION_MODE);
   },
 
   /**
    * Tell the radio to automatically choose a voice/data network
    */
   selectNetworkAuto: function(options) {
-    if (DEBUG) debug("Setting automatic network selection");
-    Buf.simpleRequest(REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, options);
+    if (DEBUG) this.context.debug("Setting automatic network selection");
+    this.context.Buf.simpleRequest(REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, options);
   },
 
   /**
    * Set the roaming preference mode
    */
   setRoamingPreference: function(options) {
     let roamingMode = CDMA_ROAMING_PREFERENCE_TO_GECKO.indexOf(options.mode);
 
     if (roamingMode === -1) {
       options.errorMsg = GECKO_ERROR_INVALID_PARAMETER;
       this.sendChromeMessage(options);
       return;
     }
 
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_CDMA_SET_ROAMING_PREFERENCE, options);
     Buf.writeInt32(1);
     Buf.writeInt32(roamingMode);
     Buf.sendParcel();
   },
 
   /**
    * Get the roaming preference mode
    */
   queryRoamingPreference: function(options) {
-    Buf.simpleRequest(REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, options);
+    this.context.Buf.simpleRequest(REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, options);
   },
 
   /**
    * Set the voice privacy mode
    */
   setVoicePrivacyMode: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE, options);
     Buf.writeInt32(1);
     Buf.writeInt32(options.enabled ? 1 : 0);
     Buf.sendParcel();
   },
 
   /**
    * Get the voice privacy mode
    */
   queryVoicePrivacyMode: function(options) {
-    Buf.simpleRequest(REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE, options);
+    this.context.Buf.simpleRequest(REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE, options);
   },
 
   /**
    * Open Logical UICC channel (aid) for Secure Element access
    */
   iccOpenChannel: function(options) {
     if (DEBUG) {
-      debug("iccOpenChannel: " + JSON.stringify(options));
-    }
-
+      this.context.debug("iccOpenChannel: " + JSON.stringify(options));
+    }
+
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SIM_OPEN_CHANNEL, options);
     Buf.writeString(options.aid);
     Buf.sendParcel();
   },
 
 /**
    * Exchange APDU data on an open Logical UICC channel
    */
   iccExchangeAPDU: function(options) {
-    if (DEBUG) debug("iccExchangeAPDU: " + JSON.stringify(options));
+    if (DEBUG) this.context.debug("iccExchangeAPDU: " + JSON.stringify(options));
 
     let cla = options.apdu.cla;
     let command = options.apdu.command;
     let channel = options.channel;
     let path = options.apdu.path || "";
     let data = options.apdu.data || "";
     let data2 = options.apdu.data2 || "";
 
     let p1 = options.apdu.p1;
     let p2 = options.apdu.p2;
     let p3 = options.apdu.p3; // Extra
 
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SIM_ACCESS_CHANNEL, options);
     Buf.writeInt32(cla);
     Buf.writeInt32(command);
     Buf.writeInt32(channel);
     Buf.writeString(path); // path
     Buf.writeInt32(p1);
     Buf.writeInt32(p2);
     Buf.writeInt32(p3);
@@ -1249,74 +1314,77 @@ let RIL = {
 
     Buf.sendParcel();
   },
 
   /**
    * Close Logical UICC channel
    */
   iccCloseChannel: function(options) {
-    if (DEBUG) debug("iccCloseChannel: " + JSON.stringify(options));
-
+    if (DEBUG) this.context.debug("iccCloseChannel: " + JSON.stringify(options));
+
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SIM_CLOSE_CHANNEL, options);
     Buf.writeInt32(1);
     Buf.writeInt32(options.channel);
     Buf.sendParcel();
   },
 
   /**
    * Tell the radio to choose a specific voice/data network
    */
   selectNetwork: function(options) {
     if (DEBUG) {
-      debug("Setting manual network selection: " + options.mcc + ", " + options.mnc);
+      this.context.debug("Setting manual network selection: " +
+                         options.mcc + ", " + options.mnc);
     }
 
     let numeric = (options.mcc && options.mnc) ? options.mcc + options.mnc : null;
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SET_NETWORK_SELECTION_MANUAL, options);
     Buf.writeString(numeric);
     Buf.sendParcel();
   },
 
   /**
    * Get current calls.
    */
   getCurrentCalls: function() {
-    Buf.simpleRequest(REQUEST_GET_CURRENT_CALLS);
+    this.context.Buf.simpleRequest(REQUEST_GET_CURRENT_CALLS);
   },
 
   /**
    * Get the signal strength.
    */
   getSignalStrength: function() {
-    Buf.simpleRequest(REQUEST_SIGNAL_STRENGTH);
+    this.context.Buf.simpleRequest(REQUEST_SIGNAL_STRENGTH);
   },
 
   getIMEI: function(options) {
-    Buf.simpleRequest(REQUEST_GET_IMEI, options);
+    this.context.Buf.simpleRequest(REQUEST_GET_IMEI, options);
   },
 
   getIMEISV: function() {
-    Buf.simpleRequest(REQUEST_GET_IMEISV);
+    this.context.Buf.simpleRequest(REQUEST_GET_IMEISV);
   },
 
   getDeviceIdentity: function() {
-    Buf.simpleRequest(REQUEST_DEVICE_IDENTITY);
+    this.context.Buf.simpleRequest(REQUEST_DEVICE_IDENTITY);
   },
 
   getBasebandVersion: function() {
-    Buf.simpleRequest(REQUEST_BASEBAND_VERSION);
+    this.context.Buf.simpleRequest(REQUEST_BASEBAND_VERSION);
   },
 
   sendExitEmergencyCbModeRequest: function(options) {
-    Buf.simpleRequest(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, options);
+    this.context.Buf.simpleRequest(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, options);
   },
 
   getCdmaSubscription: function() {
-    Buf.simpleRequest(REQUEST_CDMA_SUBSCRIPTION);
+    this.context.Buf.simpleRequest(REQUEST_CDMA_SUBSCRIPTION);
   },
 
   exitEmergencyCbMode: function(options) {
     // The function could be called by an API from RadioInterfaceLayer or by
     // ril_worker itself. From ril_worker, we won't pass the parameter
     // 'options'. In this case, it is marked as internal.
     if (!options) {
       options = {internal: true};
@@ -1392,31 +1460,34 @@ let RIL = {
     this.sendDialRequest(options);
   },
 
   dialEmergencyNumber: function(options, onerror) {
     options.request = RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL ?
                       REQUEST_DIAL_EMERGENCY_CALL : REQUEST_DIAL;
 
     if (this.radioState == GECKO_RADIOSTATE_OFF) {
-      if (DEBUG) debug("Automatically enable radio for an emergency call.");
+      if (DEBUG) {
+        this.context.debug("Automatically enable radio for an emergency call.");
+      }
 
       if (!this.cachedDialRequest) {
         this.cachedDialRequest = {};
       }
       this.cachedDialRequest.onerror = onerror;
       this.cachedDialRequest.callback = this.sendDialRequest.bind(this, options);
       this.setRadioEnabled({enabled: true});
       return;
     }
 
     this.sendDialRequest(options);
   },
 
   sendDialRequest: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(options.request, options);
     Buf.writeString(options.number);
     Buf.writeInt32(options.clirMode || 0);
     Buf.writeInt32(options.uusInfo || 0);
     // TODO Why do we need this extra 0? It was put it in to make this
     // match the format of the binary message.
     Buf.writeInt32(0);
     Buf.sendParcel();
@@ -1438,16 +1509,17 @@ let RIL = {
    *        Call index (1-based) as reported by REQUEST_GET_CURRENT_CALLS.
    */
   hangUp: function(options) {
     let call = this.currentCalls[options.callIndex];
     if (!call) {
       return;
     }
 
+    let Buf = this.context.Buf;
     switch (call.state) {
       case CALL_STATE_ACTIVE:
       case CALL_STATE_DIALING:
       case CALL_STATE_ALERTING:
         Buf.newParcel(REQUEST_HANGUP);
         Buf.writeInt32(1);
         Buf.writeInt32(options.callIndex);
         Buf.sendParcel();
@@ -1460,16 +1532,17 @@ let RIL = {
 
   /**
    * Mute or unmute the radio.
    *
    * @param mute
    *        Boolean to indicate whether to mute or unmute the radio.
    */
   setMute: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SET_MUTE);
     Buf.writeInt32(1);
     Buf.writeInt32(options.muted ? 1 : 0);
     Buf.sendParcel();
   },
 
   /**
    * Answer an incoming/waiting call.
@@ -1482,16 +1555,17 @@ let RIL = {
     // notification the incoming/waiting call may have changed. The main
     // thread thinks that it is answering the call with the given index,
     // so only answer if that is still incoming/waiting.
     let call = this.currentCalls[options.callIndex];
     if (!call) {
       return;
     }
 
+    let Buf = this.context.Buf;
     switch (call.state) {
       case CALL_STATE_INCOMING:
         Buf.simpleRequest(REQUEST_ANSWER);
         break;
       case CALL_STATE_WAITING:
         // Answer the waiting (second) call, and hold the first call.
         Buf.simpleRequest(REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE);
         break;
@@ -1509,16 +1583,17 @@ let RIL = {
     // notification the incoming/waiting call may have changed. The main
     // thread thinks that it is rejecting the call with the given index,
     // so only reject if that is still incoming/waiting.
     let call = this.currentCalls[options.callIndex];
     if (!call) {
       return;
     }
 
+    let Buf = this.context.Buf;
     if (this._isCdma) {
       // AT+CHLD=0 means "release held or UDUB."
       Buf.simpleRequest(REQUEST_HANGUP_WAITING_OR_BACKGROUND);
       return;
     }
 
     switch (call.state) {
       case CALL_STATE_INCOMING:
@@ -1529,54 +1604,56 @@ let RIL = {
         Buf.simpleRequest(REQUEST_HANGUP_WAITING_OR_BACKGROUND);
         break;
     }
   },
 
   holdCall: function(options) {
     let call = this.currentCalls[options.callIndex];
     if (call && call.state == CALL_STATE_ACTIVE) {
+      let Buf = this.context.Buf;
       if (this._isCdma) {
         Buf.newParcel(REQUEST_CDMA_FLASH);
         Buf.writeString("");
         Buf.sendParcel();
       } else {
         Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE);
       }
     }
   },
 
   resumeCall: function(options) {
     let call = this.currentCalls[options.callIndex];
     if (call && call.state == CALL_STATE_HOLDING) {
-      Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE);
+      this.context.Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE);
     }
   },
 
   // Flag indicating whether user has requested making a conference call.
   _hasConferenceRequest: false,
 
   conferenceCall: function(options) {
     this._hasConferenceRequest = true;
-    Buf.simpleRequest(REQUEST_CONFERENCE, options);
+    this.context.Buf.simpleRequest(REQUEST_CONFERENCE, options);
   },
 
   separateCall: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SEPARATE_CONNECTION, options);
     Buf.writeInt32(1);
     Buf.writeInt32(options.callIndex);
     Buf.sendParcel();
   },
 
   holdConference: function() {
-    Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE);
+    this.context.Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE);
   },
 
   resumeConference: function() {
-    Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE);
+    this.context.Buf.simpleRequest(REQUEST_SWITCH_HOLDING_AND_ACTIVE);
   },
 
   /**
    * Send an SMS.
    *
    * The `options` parameter object should contain the following attributes:
    *
    * @param number
@@ -1596,37 +1673,39 @@ let RIL = {
 
     if (!options.segmentSeq) {
       // Fist segment to send
       options.segmentSeq = 1;
       options.body = options.segments[0].body;
       options.encodedBodyLength = options.segments[0].encodedBodyLength;
     }
 
+    let Buf = this.context.Buf;
     if (this._isCdma) {
       Buf.newParcel(REQUEST_CDMA_SEND_SMS, options);
-      CdmaPDUHelper.writeMessage(options);
+      this.context.CdmaPDUHelper.writeMessage(options);
     } else {
       Buf.newParcel(REQUEST_SEND_SMS, options);
       Buf.writeInt32(2);
       Buf.writeString(options.SMSC);
-      GsmPDUHelper.writeMessage(options);
+      this.context.GsmPDUHelper.writeMessage(options);
     }
     Buf.sendParcel();
   },
 
   /**
    * Acknowledge the receipt and handling of an SMS.
    *
    * @param success
    *        Boolean indicating whether the message was successfuly handled.
    * @param cause
    *        SMS_* constant indicating the reason for unsuccessful handling.
    */
   acknowledgeGsmSms: function(success, cause) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SMS_ACKNOWLEDGE);
     Buf.writeInt32(2);
     Buf.writeInt32(success ? 1 : 0);
     Buf.writeInt32(cause);
     Buf.sendParcel();
   },
 
   /**
@@ -1650,16 +1729,17 @@ let RIL = {
    * Acknowledge the receipt and handling of a CDMA SMS.
    *
    * @param success
    *        Boolean indicating whether the message was successfuly handled.
    * @param cause
    *        SMS_* constant indicating the reason for unsuccessful handling.
    */
   acknowledgeCdmaSms: function(success, cause) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_CDMA_SMS_ACKNOWLEDGE);
     Buf.writeInt32(success ? 0 : 1);
     Buf.writeInt32(cause);
     Buf.sendParcel();
   },
 
   setCellBroadcastDisabled: function(options) {
     this.cellBroadcastDisabled = options.disabled;
@@ -1676,17 +1756,17 @@ let RIL = {
 
   setCellBroadcastSearchList: function(options) {
     try {
       let str = options.searchListStr;
       this.cellBroadcastConfigs.MMI = this._convertCellBroadcastSearchList(str);
       options.success = true;
     } catch (e) {
       if (DEBUG) {
-        debug("Invalid Cell Broadcast search list: " + e);
+        this.context.debug("Invalid Cell Broadcast search list: " + e);
       }
       options.success = false;
     }
 
     this.sendChromeMessage(options);
     if (!options.success) {
       return;
     }
@@ -1702,16 +1782,17 @@ let RIL = {
       this.setSmsBroadcastConfig(this.mergedCellBroadcastConfig);
     } else {
       // It's unnecessary to set config first if we're deactivating.
       this.setSmsBroadcastActivation(false);
     }
   },
 
   setGsmSmsBroadcastConfig: function(config) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_GSM_SET_BROADCAST_SMS_CONFIG);
 
     let numConfigs = config ? config.length / 2 : 0;
     Buf.writeInt32(numConfigs);
     for (let i = 0; i < config.length;) {
       Buf.writeInt32(config[i++]);
       Buf.writeInt32(config[i++]);
       Buf.writeInt32(0x00);
@@ -1723,16 +1804,17 @@ let RIL = {
   },
 
   /**
    * Send CDMA SMS broadcast config.
    *
    * @see 3GPP2 C.R1001 Sec. 9.2 and 9.3
    */
   setCdmaSmsBroadcastConfig: function(config) {
+    let Buf = this.context.Buf;
     // |config| is an array of half-closed range: [[from, to), [from, to), ...].
     // It will be further decomposed, ex: [1, 4) => 1, 2, 3.
     Buf.newParcel(REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG);
 
     let numConfigs = 0;
     for (let i = 0; i < config.length; i += 2) {
       numConfigs += (config[i+1] - config[i]);
     }
@@ -1758,57 +1840,60 @@ let RIL = {
     } else {
       this.setGsmSmsBroadcastConfig(config);
     }
   },
 
   setSmsBroadcastActivation: function(activate) {
     let parcelType = this._isCdma ? REQUEST_CDMA_SMS_BROADCAST_ACTIVATION :
                                     REQUEST_GSM_SMS_BROADCAST_ACTIVATION;
+    let Buf = this.context.Buf;
     Buf.newParcel(parcelType);
     Buf.writeInt32(1);
     // See hardware/ril/include/telephony/ril.h, 0 - Activate, 1 - Turn off.
     Buf.writeInt32(activate ? 0 : 1);
     Buf.sendParcel();
   },
 
   /**
    * Start a DTMF Tone.
    *
    * @param dtmfChar
    *        DTMF signal to send, 0-9, *, +
    */
   startTone: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_DTMF_START);
     Buf.writeString(options.dtmfChar);
     Buf.sendParcel();
   },
 
   stopTone: function() {
-    Buf.simpleRequest(REQUEST_DTMF_STOP);
+    this.context.Buf.simpleRequest(REQUEST_DTMF_STOP);
   },
 
   /**
    * Send a DTMF tone.
    *
    * @param dtmfChar
    *        DTMF signal to send, 0-9, *, +
    */
   sendTone: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_DTMF);
     Buf.writeString(options.dtmfChar);
     Buf.sendParcel();
   },
 
   /**
    * Get the Short Message Service Center address.
    */
   getSmscAddress: function(options) {
     if (!this.SMSC) {
-      Buf.simpleRequest(REQUEST_GET_SMSC_ADDRESS, options);
+      this.context.Buf.simpleRequest(REQUEST_GET_SMSC_ADDRESS, options);
       return;
     }
 
     if (!options || options.rilMessageType !== "getSmscAddress") {
       return;
     }
 
     options.smscAddress = this.SMSC;
@@ -1818,16 +1903,17 @@ let RIL = {
 
   /**
    * Set the Short Message Service Center address.
    *
    * @param smscAddress
    *        Short Message Service Center address in PDU format.
    */
   setSmscAddress: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SET_SMSC_ADDRESS, options);
     Buf.writeString(options.smscAddress);
     Buf.sendParcel();
   },
 
   /**
    * Setup a data call.
    *
@@ -1856,22 +1942,23 @@ let RIL = {
     // for values above 2 this is RIL_RadioTechnology + 2.
     //
     // From frameworks/base/telephony/java/com/android/internal/telephony/DataConnection.java:
     // if the mRilVersion < 6, radio technology must be GSM/UMTS or CDMA.
     // Otherwise, it must be + 2
     //
     // See also bug 901232 and 867873
     let radioTech;
-    if (RILQUIRKS_V5_LEGACY) {
+    if (this.v5Legacy) {
       radioTech = this._isCdma ? DATACALL_RADIOTECHNOLOGY_CDMA
                                : DATACALL_RADIOTECHNOLOGY_GSM;
     } else {
       radioTech = options.radioTech + 2;
     }
+    let Buf = this.context.Buf;
     let token = Buf.newParcel(REQUEST_SETUP_DATA_CALL, options);
     Buf.writeInt32(7);
     Buf.writeString(radioTech.toString());
     Buf.writeString(DATACALL_PROFILE_DEFAULT.toString());
     Buf.writeString(options.apn);
     Buf.writeString(options.user);
     Buf.writeString(options.passwd);
     Buf.writeString(options.chappap.toString());
@@ -1889,52 +1976,54 @@ let RIL = {
    *        One of DATACALL_DEACTIVATE_* constants.
    */
   deactivateDataCall: function(options) {
     let datacall = this.currentDataCalls[options.cid];
     if (!datacall) {
       return;
     }
 
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_DEACTIVATE_DATA_CALL, options);
     Buf.writeInt32(2);
     Buf.writeString(options.cid);
     Buf.writeString(options.reason || DATACALL_DEACTIVATE_NO_REASON);
     Buf.sendParcel();
 
     datacall.state = GECKO_NETWORK_STATE_DISCONNECTING;
     this.sendChromeMessage(datacall);
   },
 
   /**
    * Get a list of data calls.
    */
   getDataCallList: function() {
-    Buf.simpleRequest(REQUEST_DATA_CALL_LIST);
+    this.context.Buf.simpleRequest(REQUEST_DATA_CALL_LIST);
   },
 
   _attachDataRegistration: false,
   /**
    * Manually attach/detach data registration.
    *
    * @param attach
    *        Boolean value indicating attach or detach.
    */
   setDataRegistration: function(options) {
     let request = options.attach ? RIL_REQUEST_GPRS_ATTACH :
                                    RIL_REQUEST_GPRS_DETACH;
     this._attachDataRegistration = options.attach;
-    Buf.simpleRequest(request);
+    this.context.Buf.simpleRequest(request);
   },
 
   /**
    * Get failure casue code for the most recently failed PDP context.
    */
   getFailCauseCode: function(callback) {
-    Buf.simpleRequest(REQUEST_LAST_CALL_FAIL_CAUSE, {callback: callback});
+    this.context.Buf.simpleRequest(REQUEST_LAST_CALL_FAIL_CAUSE,
+                                   {callback: callback});
   },
 
   /**
    * Helper to parse MMI/USSD string. TS.22.030 Figure 3.5.3.2.
    */
   _parseMMI: function(mmiString) {
     if (!mmiString || !mmiString.length) {
       return null;
@@ -2055,22 +2144,22 @@ let RIL = {
       return true;
     }
 
     return false;
   },
 
   sendMMI: function(options) {
     if (DEBUG) {
-      debug("SendMMI " + JSON.stringify(options));
+      this.context.debug("SendMMI " + JSON.stringify(options));
     }
     let mmiString = options.mmi;
     let mmi = this._parseMMI(mmiString);
 
-    let _sendMMIError = (function _sendMMIError(errorMsg, mmiServiceCode) {
+    let _sendMMIError = (function(errorMsg, mmiServiceCode) {
       options.success = false;
       options.errorMsg = errorMsg;
       if (mmiServiceCode) {
         options.mmiServiceCode = mmiServiceCode;
       }
       this.sendChromeMessage(options);
     }).bind(this);
 
@@ -2098,23 +2187,23 @@ let RIL = {
           mmi.sic.length < 4 || mmi.sic.length > 8) {
         _sendMMIError(MMI_ERROR_KS_INVALID_PIN, mmiServiceCode);
         return false;
       }
 
       return true;
     }
 
-    function _isRadioAvailable(mmiServiceCode) {
-      if (RIL.radioState !== GECKO_RADIOSTATE_READY) {
+    let _isRadioAvailable = (function(mmiServiceCode) {
+      if (this.radioState !== GECKO_RADIOSTATE_READY) {
         _sendMMIError(GECKO_ERROR_RADIO_NOT_AVAILABLE, mmiServiceCode);
         return false;
       }
       return true;
-    }
+    }).bind(this);
 
     // If we couldn't parse the MMI code, we'll send it as an USSD request.
     if (mmi === null) {
       if (this._ussdSession) {
         if (!_isRadioAvailable(MMI_KS_SC_USSD)) {
           return;
         }
         options.ussd = mmiString;
@@ -2122,17 +2211,17 @@ let RIL = {
         return;
       }
 
       _sendMMIError(MMI_ERROR_KS_ERROR);
       return;
     }
 
     if (DEBUG) {
-      debug("MMI " + JSON.stringify(mmi));
+      this.context.debug("MMI " + JSON.stringify(mmi));
     }
 
     // We check if the MMI service code is supported and in that case we
     // trigger the appropriate RIL request if possible.
     let sc = mmi.serviceCode;
     switch (sc) {
       // Call forwarding
       case MMI_SC_CFU:
@@ -2358,40 +2447,42 @@ let RIL = {
   /**
    * Send USSD.
    *
    * @param ussd
    *        String containing the USSD code.
    *
    */
    sendUSSD: function(options) {
+     let Buf = this.context.Buf;
      Buf.newParcel(REQUEST_SEND_USSD, options);
      Buf.writeString(options.ussd);
      Buf.sendParcel();
    },
 
   /**
    * Cancel pending USSD.
    */
    cancelUSSD: function(options) {
      options.mmiServiceCode = MMI_KS_SC_USSD;
-     Buf.simpleRequest(REQUEST_CANCEL_USSD, options);
+     this.context.Buf.simpleRequest(REQUEST_CANCEL_USSD, options);
    },
 
   /**
    * Queries current call forward rules.
    *
    * @param reason
    *        One of nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_* constants.
    * @param serviceClass
    *        One of ICC_SERVICE_CLASS_* constants.
    * @param number
    *        Phone number of forwarding address.
    */
   queryCallForwardStatus: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_QUERY_CALL_FORWARD_STATUS, options);
     Buf.writeInt32(CALL_FORWARD_ACTION_QUERY_STATUS);
     Buf.writeInt32(options.reason);
     Buf.writeInt32(options.serviceClass || ICC_SERVICE_CLASS_NONE);
     Buf.writeInt32(this._toaFromString(options.number));
     Buf.writeString(options.number);
     Buf.writeInt32(0);
     Buf.sendParcel();
@@ -2407,16 +2498,17 @@ let RIL = {
    * @param serviceClass
    *        One of ICC_SERVICE_CLASS_* constants.
    * @param number
    *        Phone number of forwarding address.
    * @param timeSeconds
    *        Time in seconds to wait beforec all is forwarded.
    */
   setCallForward: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_SET_CALL_FORWARD, options);
     Buf.writeInt32(options.action);
     Buf.writeInt32(options.reason);
     Buf.writeInt32(options.serviceClass);
     Buf.writeInt32(this._toaFromString(options.number));
     Buf.writeString(options.number);
     Buf.writeInt32(options.timeSeconds);
     Buf.sendParcel();
@@ -2457,16 +2549,17 @@ let RIL = {
    * Change call barring facility password.
    *
    * @param pin
    *        Old password.
    * @param newPin
    *        New password.
    */
   changeCallBarringPassword: function(options) {
+    let Buf = this.context.Buf;
     Buf.newParcel(REQUEST_CHANGE_BARRING_PASSWORD, options);
     Buf.writeInt32(3);
     // Set facility to ICC_CB_FACILITY_BA_ALL by following TS.22.030 clause
     // 6.5.4 and Table B.1.
     Buf.writeString(ICC_CB_FACILITY_BA_ALL);
     Buf.writeString(options.pin);
     Buf.writeString(options.newPin);
     Buf.sendParcel();
@@ -2474,28 +2567,32 @@ let RIL = {
 
   /**
    * Handle STK CALL_SET_UP request.
    *
    * @param hasConfirmed
    *        Does use have confirmed the call requested from ICC?
    */
   stkHandleCallSetup: function(options) {
+     let Buf = this.context.Buf;
      Buf.newParcel(REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM);
      Buf.writeInt32(1);
      Buf.writeInt32(options.hasConfirmed ? 1 : 0);
      Buf.sendParcel();
   },
 
   /**
    * Send STK Profile Download.
    *
    * @param profile Profile supported by ME.
    */
   sendStkTerminalProfile: function(profile) {
+    let Buf = this.context.Buf;
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     Buf.newParcel(REQUEST_STK_SET_PROFILE);
     Buf.writeInt32(profile.length * 2);
     for (let i = 0; i < profile.length; i++) {
       GsmPDUHelper.writeHexOctet(profile[i]);
     }
     Buf.writeInt32(0);
     Buf.sendParcel();
   },
@@ -2514,16 +2611,20 @@ let RIL = {
    * @param [optional] timer
    */
   sendStkTerminalResponse: function(response) {
     if (response.hasConfirmed !== undefined) {
       this.stkHandleCallSetup(response);
       return;
     }
 
+    let Buf = this.context.Buf;
+    let ComprehensionTlvHelper = this.context.ComprehensionTlvHelper;
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     let command = response.command;
     Buf.newParcel(REQUEST_STK_SEND_TERMINAL_RESPONSE);
 
     // 1st mark for Parcel size
     Buf.startCalOutgoingSize(function(size) {
       // Parcel size is in string length, which costs 2 uint8 per char.
       Buf.writeInt32(size / 2);
     });
@@ -2626,17 +2727,17 @@ let RIL = {
       // Location Infomation
       if (localInfo.locationInfo) {
         ComprehensionTlvHelper.writeLocationInfoTlv(localInfo.locationInfo);
       }
 
       // IMEI
       if (localInfo.imei != null) {
         let imei = localInfo.imei;
-        if(imei.length == 15) {
+        if (imei.length == 15) {
           imei = imei + "0";
         }
 
         GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_IMEI);
         GsmPDUHelper.writeHexOctet(8);
         for (let i = 0; i < imei.length / 2; i++) {
           GsmPDUHelper.writeHexOctet(parseInt(imei.substr(i * 2, 2), 16));
         }
@@ -2788,18 +2889,23 @@ let RIL = {
    * @param [optional] transactionId
    * @param [optional] cause
    * @param [optional] timerId
    * @param [optional] timerValue
    * @param [optional] terminationCause
    */
   sendICCEnvelopeCommand: function(options) {
     if (DEBUG) {
-      debug("Stk Envelope " + JSON.stringify(options));
-    }
+      this.context.debug("Stk Envelope " + JSON.stringify(options));
+    }
+
+    let Buf = this.context.Buf;
+    let ComprehensionTlvHelper = this.context.ComprehensionTlvHelper;
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     Buf.newParcel(REQUEST_STK_SEND_ENVELOPE_COMMAND);
 
     // 1st mark for Parcel size
     Buf.startCalOutgoingSize(function(size) {
       // Parcel size is in string length, which costs 2 uint8 per char.
       Buf.writeInt32(size / 2);
     });
 
@@ -2866,17 +2972,17 @@ let RIL = {
 
     // Address
     if (options.address) {
       GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_ADDRESS |
                                  COMPREHENSIONTLV_FLAG_CR);
       ComprehensionTlvHelper.writeLength(
         Math.ceil(options.address.length/2) + 1 // address BCD + TON
       );
-      ICCPDUHelper.writeDiallingNumber(options.address);
+      this.context.ICCPDUHelper.writeDiallingNumber(options.address);
     }
 
     // Cause of disconnection.
     if (options.cause != null) {
       ComprehensionTlvHelper.writeCauseTlv(options.cause);
     }
 
     // Timer Identifier
@@ -2948,17 +3054,17 @@ let RIL = {
              (mmi.procedure == MMI_PROCEDURE_ACTIVATION ||
               mmi.procedure == MMI_PROCEDURE_DEACTIVATION));
    },
 
   /**
    * Report STK Service is running.
    */
   reportStkServiceIsRunning: function() {
-    Buf.simpleRequest(REQUEST_REPORT_STK_SERVICE_IS_RUNNING);
+    this.context.Buf.simpleRequest(REQUEST_REPORT_STK_SERVICE_IS_RUNNING);
   },
 
   /**
    * Process ICC status.
    */
   _processICCStatus: function(iccStatus) {
     this.iccStatus = iccStatus;
     let newCardState;
@@ -2973,21 +3079,22 @@ let RIL = {
         this.operator = null;
         // We should send |cardstatechange| before |iccinfochange|, otherwise we
         // may lost cardstatechange event when icc card becomes undetected.
         this.cardState = GECKO_CARDSTATE_UNDETECTED;
         this.sendChromeMessage({rilMessageType: "cardstatechange",
                                 cardState: this.cardState});
 
         this.iccInfo = {iccType: null};
-        ICCUtilsHelper.handleICCInfoChange();
+        this.context.ICCUtilsHelper.handleICCInfoChange();
       }
       return;
     }
 
+    let ICCRecordHelper = this.context.ICCRecordHelper;
     // fetchICCRecords will need to read aid, so read aid here.
     this.aid = app.aid;
     this.appType = app.app_type;
     this.iccInfo.iccType = GECKO_CARD_TYPE[this.appType];
     // Try to get iccId only when cardState left GECKO_CARDSTATE_UNDETECTED.
     if (iccStatus.cardState === CARD_STATE_PRESENT &&
         (this.cardState === GECKO_CARDSTATE_UNINITIALIZED ||
          this.cardState === GECKO_CARDSTATE_UNDETECTED)) {
@@ -3028,17 +3135,17 @@ let RIL = {
     }
 
     // This was moved down from CARD_APPSTATE_READY
     this.requestNetworkInfo();
     if (newCardState == GECKO_CARDSTATE_READY) {
       // For type SIM, we need to check EF_phase first.
       // Other types of ICC we can send Terminal_Profile immediately.
       if (this.appType == CARD_APPTYPE_SIM) {
-        SimRecordHelper.readSimPhase();
+        this.context.SimRecordHelper.readSimPhase();
       } else if (RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD) {
         this.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
       }
 
       ICCRecordHelper.fetchICCRecords();
     }
 
     this.cardState = newCardState;
@@ -3049,17 +3156,17 @@ let RIL = {
    /**
    * Helper for processing responses of functions such as enterICC* and changeICC*.
    */
   _processEnterAndChangeICCResponses: function(length, options) {
     options.success = (options.rilRequestError === 0);
     if (!options.success) {
       options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     }
-    options.retryCount = length ? Buf.readInt32List()[0] : -1;
+    options.retryCount = length ? this.context.Buf.readInt32List()[0] : -1;
     if (options.rilMessageType != "sendMMI") {
       this.sendChromeMessage(options);
       return;
     }
 
     let mmiServiceCode = options.mmiServiceCode;
 
     if (options.success) {
@@ -3123,70 +3230,79 @@ let RIL = {
   _sendNetworkInfoMessage: function(type, message) {
     if (!this._processingNetworkInfo) {
       // We only combine these messages in the case of the combined request
       // in requestNetworkInfo()
       this.sendChromeMessage(message);
       return;
     }
 
-    if (DEBUG) debug("Queuing " + type + " network info message: " + JSON.stringify(message));
+    if (DEBUG) {
+      this.context.debug("Queuing " + type + " network info message: " +
+                         JSON.stringify(message));
+    }
     this._pendingNetworkInfo[type] = message;
   },
 
   _receivedNetworkInfo: function(type) {
-    if (DEBUG) debug("Received " + type + " network info.");
+    if (DEBUG) this.context.debug("Received " + type + " network info.");
     if (!this._processingNetworkInfo) {
       return;
     }
 
     let pending = this._pendingNetworkInfo;
 
     // We still need to track states for events that aren't fired.
     if (!(type in pending)) {
-      pending[type] = PENDING_NETWORK_TYPE;
+      pending[type] = this.pendingNetworkType;
     }
 
     // Pending network info is ready to be sent when no more messages
     // are waiting for responses, but the combined payload hasn't been sent.
     for (let i = 0; i < NETWORK_INFO_MESSAGE_TYPES.length; i++) {
       let msgType = NETWORK_INFO_MESSAGE_TYPES[i];
       if (!(msgType in pending)) {
-        if (DEBUG) debug("Still missing some more network info, not notifying main thread.");
+        if (DEBUG) {
+          this.context.debug("Still missing some more network info, not " +
+                             "notifying main thread.");
+        }
         return;
       }
     }
 
     // Do a pass to clean up the processed messages that didn't create
     // a response message, so we don't have unused keys in the outbound
     // networkinfochanged message.
     for (let key in pending) {
-      if (pending[key] == PENDING_NETWORK_TYPE) {
+      if (pending[key] == this.pendingNetworkType) {
         delete pending[key];
       }
     }
 
-    if (DEBUG) debug("All pending network info has been received: " + JSON.stringify(pending));
+    if (DEBUG) {
+      this.context.debug("All pending network info has been received: " +
+                         JSON.stringify(pending));
+    }
 
     // Send the message on the next tick of the worker's loop, so we give the
     // last message a chance to call _sendNetworkInfoMessage first.
-    setTimeout(this._sendPendingNetworkInfo, 0);
+    setTimeout(this._sendPendingNetworkInfo.bind(this), 0);
   },
 
   _sendPendingNetworkInfo: function() {
-    RIL.sendChromeMessage(RIL._pendingNetworkInfo);
-
-    RIL._processingNetworkInfo = false;
+    this.sendChromeMessage(this._pendingNetworkInfo);
+
+    this._processingNetworkInfo = false;
     for (let i = 0; i < NETWORK_INFO_MESSAGE_TYPES.length; i++) {
-      delete RIL._pendingNetworkInfo[NETWORK_INFO_MESSAGE_TYPES[i]];
-    }
-
-    if (RIL._needRepollNetworkInfo) {
-      RIL._needRepollNetworkInfo = false;
-      RIL.requestNetworkInfo();
+      delete this._pendingNetworkInfo[NETWORK_INFO_MESSAGE_TYPES[i]];
+    }
+
+    if (this._needRepollNetworkInfo) {
+      this._needRepollNetworkInfo = false;
+      this.requestNetworkInfo();
     }
   },
 
   /**
    * Normalize the signal strength in dBm to the signal level from 0 to 100.
    *
    * @param signal
    *        The signal strength in dBm to normalize.
@@ -3283,17 +3399,17 @@ let RIL = {
   /**
    * Process the network registration flags.
    *
    * @return true if the state changed, false otherwise.
    */
   _processCREG: function(curState, newState) {
     let changed = false;
 
-    let regState = RIL.parseInt(newState[0], NETWORK_CREG_STATE_UNKNOWN);
+    let regState = this.parseInt(newState[0], NETWORK_CREG_STATE_UNKNOWN);
     if (curState.regState === undefined || curState.regState !== regState) {
       changed = true;
       curState.regState = regState;
 
       curState.state = NETWORK_CREG_TO_GECKO_MOBILE_CONNECTION_STATE[regState];
       curState.connected = regState == NETWORK_CREG_STATE_REGISTERED_HOME ||
                            regState == NETWORK_CREG_STATE_REGISTERED_ROAMING;
       curState.roaming = regState == NETWORK_CREG_STATE_REGISTERED_ROAMING;
@@ -3301,62 +3417,62 @@ let RIL = {
     }
 
     if (!curState.cell) {
       curState.cell = {};
     }
 
     // From TS 23.003, 0000 and 0xfffe are indicated that no valid LAI exists
     // in MS. So we still need to report the '0000' as well.
-    let lac = RIL.parseInt(newState[1], -1, 16);
+    let lac = this.parseInt(newState[1], -1, 16);
     if (curState.cell.gsmLocationAreaCode === undefined ||
         curState.cell.gsmLocationAreaCode !== lac) {
       curState.cell.gsmLocationAreaCode = lac;
       changed = true;
     }
 
-    let cid = RIL.parseInt(newState[2], -1, 16);
+    let cid = this.parseInt(newState[2], -1, 16);
     if (curState.cell.gsmCellId === undefined ||
         curState.cell.gsmCellId !== cid) {
       curState.cell.gsmCellId = cid;
       changed = true;
     }
 
     let radioTech = (newState[3] === undefined ?
                      NETWORK_CREG_TECH_UNKNOWN :
-                     RIL.parseInt(newState[3], NETWORK_CREG_TECH_UNKNOWN));
+                     this.parseInt(newState[3], NETWORK_CREG_TECH_UNKNOWN));
     if (curState.radioTech === undefined || curState.radioTech !== radioTech) {
       changed = true;
       curState.radioTech = radioTech;
       curState.type = GECKO_RADIO_TECH[radioTech] || null;
     }
     return changed;
   },
 
   _processVoiceRegistrationState: function(state) {
     let rs = this.voiceRegistrationState;
     let stateChanged = this._processCREG(rs, state);
     if (stateChanged && rs.connected) {
-      RIL.getSmscAddress();
+      this.getSmscAddress();
     }
 
     let cell = rs.cell;
     if (this._isCdma) {
       // Some variables below are not used. Comment them instead of removing to
       // keep the information about state[x].
-      let cdmaBaseStationId = RIL.parseInt(state[4], -1);
-      let cdmaBaseStationLatitude = RIL.parseInt(state[5], -2147483648);
-      let cdmaBaseStationLongitude = RIL.parseInt(state[6], -2147483648);
-      // let cssIndicator = RIL.parseInt(state[7]);
-      let cdmaSystemId = RIL.parseInt(state[8], -1);
-      let cdmaNetworkId = RIL.parseInt(state[9], -1);
-      // let roamingIndicator = RIL.parseInt(state[10]);
-      // let systemIsInPRL = RIL.parseInt(state[11]);
-      // let defaultRoamingIndicator = RIL.parseInt(state[12]);
-      // let reasonForDenial = RIL.parseInt(state[13]);
+      let cdmaBaseStationId = this.parseInt(state[4], -1);
+      let cdmaBaseStationLatitude = this.parseInt(state[5], -2147483648);
+      let cdmaBaseStationLongitude = this.parseInt(state[6], -2147483648);
+      // let cssIndicator = this.parseInt(state[7]);
+      let cdmaSystemId = this.parseInt(state[8], -1);
+      let cdmaNetworkId = this.parseInt(state[9], -1);
+      // let roamingIndicator = this.parseInt(state[10]);
+      // let systemIsInPRL = this.parseInt(state[11]);
+      // let defaultRoamingIndicator = this.parseInt(state[12]);
+      // let reasonForDenial = this.parseInt(state[13]);
 
       if (cell.cdmaBaseStationId !== cdmaBaseStationId ||
           cell.cdmaBaseStationLatitude !== cdmaBaseStationLatitude ||
           cell.cdmaBaseStationLongitude !== cdmaBaseStationLongitude ||
           cell.cdmaSystemId !== cdmaSystemId ||
           cell.cdmaNetworkId !== cdmaNetworkId) {
         stateChanged = true;
         cell.cdmaBaseStationId = cdmaBaseStationId;
@@ -3380,17 +3496,17 @@ let RIL = {
       rs.rilMessageType = "dataregistrationstatechange";
       this._sendNetworkInfoMessage(NETWORK_INFO_DATA_REGISTRATION_STATE, rs);
     }
   },
 
   _processOperator: function(operatorData) {
     if (operatorData.length < 3) {
       if (DEBUG) {
-        debug("Expected at least 3 strings for operator.");
+        this.context.debug("Expected at least 3 strings for operator.");
       }
     }
 
     if (!this.operator) {
       this.operator = {
         rilMessageType: "operatorchange",
         longName: null,
         shortName: null
@@ -3406,42 +3522,43 @@ let RIL = {
 
       this.operator.mcc = null;
       this.operator.mnc = null;
 
       if (networkTuple) {
         try {
           this._processNetworkTuple(networkTuple, this.operator);
         } catch (e) {
-          if (DEBUG) debug("Error processing operator tuple: " + e);
+          if (DEBUG) this.context.debug("Error processing operator tuple: " + e);
         }
       } else {
         // According to ril.h, the operator fields will be NULL when the operator
         // is not currently registered. We can avoid trying to parse the numeric
         // tuple in that case.
         if (DEBUG) {
-          debug("Operator is currently unregistered");
-        }
-      }
-
+          this.context.debug("Operator is currently unregistered");
+        }
+      }
+
+      let ICCUtilsHelper = this.context.ICCUtilsHelper;
       let networkName;
       // We won't get network name using PNN and OPL if voice registration isn't ready
       if (this.voiceRegistrationState.cell &&
           this.voiceRegistrationState.cell.gsmLocationAreaCode != -1) {
         networkName = ICCUtilsHelper.getNetworkNameFromICC(
           this.operator.mcc,
           this.operator.mnc,
           this.voiceRegistrationState.cell.gsmLocationAreaCode);
       }
 
       if (networkName) {
         if (DEBUG) {
-          debug("Operator names will be overriden: " +
-                "longName = " + networkName.fullName + ", " +
-                "shortName = " + networkName.shortName);
+          this.context.debug("Operator names will be overriden: " +
+                             "longName = " + networkName.fullName + ", " +
+                             "shortName = " + networkName.shortName);
         }
 
         this.operator.longName = networkName.fullName;
         this.operator.shortName = networkName.shortName;
       } else {
         this.operator.longName = longName;
         this.operator.shortName = shortName;
       }
@@ -3752,43 +3869,48 @@ let RIL = {
         currentDataCall.state = updatedDataCall.state;
         currentDataCall.rilMessageType = "datacallstatechange";
         this.sendChromeMessage(currentDataCall);
         continue;
       }
 
       // State not changed, now check links.
       if (this._compareDataCallLink(updatedDataCall, currentDataCall)) {
-        if(DEBUG) debug("No changes in data call.");
+        if (DEBUG) this.context.debug("No changes in data call.");
         continue;
       }
       if ((updatedDataCall.ifname != currentDataCall.ifname) ||
           (updatedDataCall.ipaddr != currentDataCall.ipaddr)) {
-        if(DEBUG) debug("Data link changed, cleanup.");
+        if (DEBUG) this.context.debug("Data link changed, cleanup.");
         this.deactivateDataCall(currentDataCall);
         continue;
       }
       // Minor change, just update and notify.
-      if(DEBUG) debug("Data link minor change, just update and notify.");
+      if (DEBUG) {
+        this.context.debug("Data link minor change, just update and notify.");
+      }
       currentDataCall.gw = updatedDataCall.gw;
       if (updatedDataCall.dns) {
         currentDataCall.dns[0] = updatedDataCall.dns[0];
         currentDataCall.dns[1] = updatedDataCall.dns[1];
       }
       currentDataCall.rilMessageType = "datacallstatechange";
       this.sendChromeMessage(currentDataCall);
     }
 
     for each (let newDataCall in datacalls) {
       if (!newDataCall.ifname) {
         continue;
       }
 
       if (!newDataCallOptions) {
-        if (DEBUG) debug("Unexpected new data call: " + JSON.stringify(newDataCall));
+        if (DEBUG) {
+          this.context.debug("Unexpected new data call: " +
+                             JSON.stringify(newDataCall));
+        }
         continue;
       }
 
       this.currentDataCalls[newDataCall.cid] = newDataCall;
       this._setDataCallGeckoState(newDataCall);
 
       newDataCall.radioTech = newDataCallOptions.radioTech;
       newDataCall.apn = newDataCallOptions.apn;
@@ -3812,17 +3934,17 @@ let RIL = {
       case DATACALL_ACTIVE_UP:
         datacall.state = GECKO_NETWORK_STATE_CONNECTED;
         break;
     }
   },
 
   _processSuppSvcNotification: function(info) {
     if (DEBUG) {
-      debug("handle supp svc notification: " + JSON.stringify(info));
+      this.context.debug("handle supp svc notification: " + JSON.stringify(info));
     }
 
     if (info.notificationType !== 1) {
       // We haven't supported MO intermediate result code, i.e.
       // info.notificationType === 0, which refers to code1 defined in 3GPP
       // 27.007 7.17. We only support partial MT unsolicited result code,
       // referring to code2, for now.
       return;
@@ -3885,33 +4007,33 @@ let RIL = {
 
     let message = {rilMessageType: "emergencyCbModeChange",
                    active: active,
                    timeoutMs: EMERGENCY_CB_MODE_TIMEOUT_MS};
     this.sendChromeMessage(message);
   },
 
   _processNetworks: function() {
-    let strings = Buf.readStringList();
+    let strings = this.context.Buf.readStringList();
     let networks = [];
 
     for (let i = 0; i < strings.length; i += 4) {
       let network = {
         longName: strings[i],
         shortName: strings[i + 1],
         mcc: null,
         mnc: null,
         state: null
       };
 
       let networkTuple = strings[i + 2];
       try {
         this._processNetworkTuple(networkTuple, network);
       } catch (e) {
-        if (DEBUG) debug("Error processing operator tuple: " + e);
+        if (DEBUG) this.context.debug("Error processing operator tuple: " + e);
       }
 
       let state = strings[i + 3];
       if (state === NETWORK_STATE_UNKNOWN) {
         // TODO: looks like this might conflict in style with
         // GECKO_NETWORK_STYLE_UNKNOWN / nsINetworkManager
         state = GECKO_QAN_STATE_UNKNOWN;
       }
@@ -3958,18 +4080,18 @@ let RIL = {
       case NETWORK_CREG_TECH_HSPA:
       case NETWORK_CREG_TECH_LTE:
       case NETWORK_CREG_TECH_HSPAP:
       case NETWORK_CREG_TECH_GSM:
         isCdma = false;
     }
 
     if (DEBUG) {
-      debug("Radio tech is set to: " + GECKO_RADIO_TECH[radioTech] +
-            ", it is a " + (isCdma?"cdma":"gsm") + " technology");
+      this.context.debug("Radio tech is set to: " + GECKO_RADIO_TECH[radioTech] +
+                         ", it is a " + (isCdma?"cdma":"gsm") + " technology");
     }
 
     // We should request SIM information when
     //  1. Radio state has been changed, so we are waiting for radioTech or
     //  2. isCdma is different from this._isCdma.
     if (this._waitingRadioTech || isCdma != this._isCdma) {
       this._isCdma = isCdma;
       this._waitingRadioTech = false;
@@ -4033,16 +4155,19 @@ let RIL = {
   },
 
   /**
    * @param message A decoded SMS-DELIVER message.
    *
    * @see 3GPP TS 31.111 section 7.1.1
    */
   dataDownloadViaSMSPP: function(message) {
+    let Buf = this.context.Buf;
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     let options = {
       pid: message.pid,
       dcs: message.dcs,
       encoding: message.encoding,
     };
     Buf.newParcel(REQUEST_STK_SEND_ENVELOPE_WITH_STATUS, options);
 
     Buf.seekIncoming(-1 * (Buf.getCurrentParcelSize() - Buf.getReadAvailable()
@@ -4102,16 +4227,19 @@ let RIL = {
    *                SMS-DELIVER message handling.
    * @param responsePduLen ICC IO response PDU length in octets.
    * @param options An object that contains four attributes: `pid`, `dcs`,
    *                `encoding` and `responsePduLen`.
    *
    * @see 3GPP TS 23.040 section 9.2.2.1a
    */
   acknowledgeIncomingGsmSmsWithPDU: function(success, responsePduLen, options) {
+    let Buf = this.context.Buf;
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     Buf.newParcel(REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU);
 
     // Two strings.
     Buf.writeInt32(2);
 
     // String 1: Success
     Buf.writeString(success ? "1" : "0");
 
@@ -4144,16 +4272,19 @@ let RIL = {
 
     Buf.sendParcel();
   },
 
   /**
    * @param message A decoded SMS-DELIVER message.
    */
   writeSmsToSIM: function(message) {
+    let Buf = this.context.Buf;
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     Buf.newParcel(REQUEST_WRITE_SMS_TO_SIM);
 
     // Write EFsms Status
     Buf.writeInt32(EFSMS_STATUS_FREE);
 
     Buf.seekIncoming(-1 * (Buf.getCurrentParcelSize() - Buf.getReadAvailable()
                            - 2 * Buf.UINT32_SIZE)); // Skip response_type & request_type.
     let messageStringLength = Buf.readInt32(); // In semi-octets
@@ -4224,18 +4355,19 @@ let RIL = {
         message.rilMessageType = "broadcastsms-received";
       } else {
         message.rilMessageType = "sms-received";
       }
 
       this.sendChromeMessage(message);
 
       // Update MWI Status into ICC if present.
-      if (message.mwi && ICCUtilsHelper.isICCServiceAvailable("MWIS")) {
-        SimRecordHelper.updateMWIS(message.mwi);
+      if (message.mwi &&
+          this.context.ICCUtilsHelper.isICCServiceAvailable("MWIS")) {
+        this.context.SimRecordHelper.updateMWIS(message.mwi);
       }
 
       // We will acknowledge receipt of the SMS after we try to store it
       // in the database.
       return MOZ_FCS_WAIT_FOR_EXPLICIT_ACK;
     }
 
     return PDU_FCS_OK;
@@ -4245,25 +4377,25 @@ let RIL = {
    * Helper for processing SMS-STATUS-REPORT PDUs.
    *
    * @param length
    *        Length of SMS string in the incoming parcel.
    *
    * @return A failure cause defined in 3GPP 23.040 clause 9.2.3.22.
    */
   _processSmsStatusReport: function(length) {
-    let [message, result] = GsmPDUHelper.processReceivedSms(length);
+    let [message, result] = this.context.GsmPDUHelper.processReceivedSms(length);
     if (!message) {
-      if (DEBUG) debug("invalid SMS-STATUS-REPORT");
+      if (DEBUG) this.context.debug("invalid SMS-STATUS-REPORT");
       return PDU_FCS_UNSPECIFIED;
     }
 
     let options = this._pendingSentSmsMap[message.messageRef];
     if (!options) {
-      if (DEBUG) debug("no pending SMS-SUBMIT message");
+      if (DEBUG) this.context.debug("no pending SMS-SUBMIT message");
       return PDU_FCS_OK;
     }
 
     let status = message.status;
 
     // 3GPP TS 23.040 9.2.3.15 `The MS shall interpret any reserved values as
     // "Service Rejected"(01100011) but shall store them exactly as received.`
     if ((status >= 0x80)
@@ -4276,17 +4408,17 @@ let RIL = {
         || ((status >= PDU_ST_3_RESERVED_BEGIN)
             && (status < PDU_ST_3_SC_SPECIFIC_BEGIN))
         ) {
       status = PDU_ST_3_SERVICE_REJECTED;
     }
 
     // Pending. Waiting for next status report.
     if ((status >>> 5) == 0x01) {
-      if (DEBUG) debug("SMS-STATUS-REPORT: delivery still pending");
+      if (DEBUG) this.context.debug("SMS-STATUS-REPORT: delivery still pending");
       return PDU_FCS_OK;
     }
 
     delete this._pendingSentSmsMap[message.messageRef];
 
     let deliveryStatus = ((status >>> 5) === 0x00)
                        ? GECKO_SMS_DELIVERY_STATUS_SUCCESS
                        : GECKO_SMS_DELIVERY_STATUS_ERROR;
@@ -4305,22 +4437,25 @@ let RIL = {
    * @param message
    *        decoded SMS Delivery ACK message from CdmaPDUHelper.
    *
    * @return A failure cause defined in 3GPP 23.040 clause 9.2.3.22.
    */
   _processCdmaSmsStatusReport: function(message) {
     let options = this._pendingSentSmsMap[message.msgId];
     if (!options) {
-      if (DEBUG) debug("no pending SMS-SUBMIT message");
+      if (DEBUG) this.context.debug("no pending SMS-SUBMIT message");
       return PDU_FCS_OK;
     }
 
     if (message.errorClass === 2) {
-      if (DEBUG) debug("SMS-STATUS-REPORT: delivery still pending, msgStatus: " + message.msgStatus);
+      if (DEBUG) {
+        this.context.debug("SMS-STATUS-REPORT: delivery still pending, " +
+                           "msgStatus: " + message.msgStatus);
+      }
       return PDU_FCS_OK;
     }
 
     delete this._pendingSentSmsMap[message.msgId];
 
     if (message.errorClass === -1 && message.body) {
       // Process as normal incoming SMS, if errorClass is invalid
       // but message body is available.
@@ -4344,45 +4479,45 @@ let RIL = {
    *
    * @param message
    *        decoded WAP message from CdmaPDUHelper.
    *
    * @return A failure cause defined in 3GPP 23.040 clause 9.2.3.22.
    */
   _processCdmaSmsWapPush: function(message) {
     if (!message.data) {
-      if (DEBUG) debug("no data inside WAP Push message.");
+      if (DEBUG) this.context.debug("no data inside WAP Push message.");
       return PDU_FCS_OK;
     }
 
     // See 6.5. MAPPING OF WDP TO CDMA SMS in WAP-295-WDP.
     //
     // Field             | Length (bits)
     // -----------------------------------------
     // MSG_TYPE          | 8
     // TOTAL_SEGMENTS    | 8
     // SEGMENT_NUMBER    | 8
     // DATAGRAM          | (NUM_FIELDS – 3) * 8
     let index = 0;
     if (message.data[index++] !== 0) {
-     if (DEBUG) debug("Ignore a WAP Message which is not WDP.");
+      if (DEBUG) this.context.debug("Ignore a WAP Message which is not WDP.");
       return PDU_FCS_OK;
     }
 
     // 1. Originator Address in SMS-TL + Message_Id in SMS-TS are used to identify a unique WDP datagram.
     // 2. TOTAL_SEGMENTS, SEGMENT_NUMBER are used to verify that a complete
     //    datagram has been received and is ready to be passed to a higher layer.
     message.header = {
       segmentRef:     message.msgId,
       segmentMaxSeq:  message.data[index++],
       segmentSeq:     message.data[index++] + 1 // It's zero-based in CDMA WAP Push.
     };
 
     if (message.header.segmentSeq > message.header.segmentMaxSeq) {
-     if (DEBUG) debug("Wrong WDP segment info.");
+      if (DEBUG) this.context.debug("Wrong WDP segment info.");
       return PDU_FCS_OK;
     }
 
     // Ports are only specified in 1st segment.
     if (message.header.segmentSeq == 1) {
       message.header.originatorPort = message.data[index++] << 8;
       message.header.originatorPort |= message.data[index++];
       message.header.destinationPort = message.data[index++] << 8;
@@ -4410,18 +4545,18 @@ let RIL = {
       this._receivedSmsSegmentsMap[hash] = options;
 
       options.segmentMaxSeq = original.header.segmentMaxSeq;
       options.receivedSegments = 0;
       options.segments = [];
     } else if (options.segments[seq]) {
       // Duplicated segment?
       if (DEBUG) {
-        debug("Got duplicated segment no." + seq + " of a multipart SMS: "
-              + JSON.stringify(original));
+        this.context.debug("Got duplicated segment no." + seq +
+                           " of a multipart SMS: " + JSON.stringify(original));
       }
       return null;
     }
 
     if (options.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
       options.segments[seq] = original.data;
       delete original.data;
     } else {
@@ -4442,18 +4577,18 @@ let RIL = {
 
       if (!options.header.destinationPort && original.header.destinationPort) {
         options.header.destinationPort = original.header.destinationPort;
       }
     }
 
     if (options.receivedSegments < options.segmentMaxSeq) {
       if (DEBUG) {
-        debug("Got segment no." + seq + " of a multipart SMS: "
-              + JSON.stringify(options));
+        this.context.debug("Got segment no." + seq + " of a multipart SMS: " +
+                           JSON.stringify(options));
       }
       return null;
     }
 
     // Remove from map
     delete this._receivedSmsSegmentsMap[hash];
 
     // Rebuild full body
@@ -4472,17 +4607,17 @@ let RIL = {
           options.fullData[d++] = data[j];
         }
       }
     } else {
       options.fullBody = options.segments.join("");
     }
 
     if (DEBUG) {
-      debug("Got full multipart SMS: " + JSON.stringify(options));
+      this.context.debug("Got full multipart SMS: " + JSON.stringify(options));
     }
 
     return options;
   },
 
   /**
    * Helper for processing sent multipart SMS.
    */
@@ -4501,17 +4636,20 @@ let RIL = {
    *
    * @param length
    *        Length of SMS string in the incoming parcel.
    * @param options
    *        Sms information.
    */
   _processSmsSendResult: function(length, options) {
     if (options.rilRequestError) {
-      if (DEBUG) debug("_processSmsSendResult: rilRequestError = " + options.rilRequestError);
+      if (DEBUG) {
+        this.context.debug("_processSmsSendResult: rilRequestError = " +
+                           options.rilRequestError);
+      }
       switch (options.rilRequestError) {
         case ERROR_SMS_SEND_FAIL_RETRY:
           if (options.retryCount < SMS_RETRY_MAX) {
             options.retryCount++;
             // TODO: bug 736702 TP-MR, retry interval, retry timeout
             this.sendSMS(options);
             break;
           }
@@ -4523,28 +4661,32 @@ let RIL = {
             rilMessageToken: options.rilMessageToken,
             errorMsg: options.rilRequestError,
           });
           break;
       }
       return;
     }
 
+    let Buf = this.context.Buf;
     options.messageRef = Buf.readInt32();
     options.ackPDU = Buf.readString();
     options.errorCode = Buf.readInt32();
 
     if ((options.segmentMaxSeq > 1)
         && (options.segmentSeq < options.segmentMaxSeq)) {
       // Not last segment
       this._processSentSmsSegment(options);
     } else {
       // Last segment sent with success.
       if (options.requestStatusReport) {
-        if (DEBUG) debug("waiting SMS-STATUS-REPORT for messageRef " + options.messageRef);
+        if (DEBUG) {
+          this.context.debug("waiting SMS-STATUS-REPORT for messageRef " +
+                             options.messageRef);
+        }
         this._pendingSentSmsMap[options.messageRef] = options;
       }
 
       this.sendChromeMessage({
         rilMessageType: options.rilMessageType,
         rilMessageToken: options.rilMessageToken,
       });
     }
@@ -4586,34 +4728,34 @@ let RIL = {
       options = original;
       this._receivedSmsCbPagesMap[hash] = options;
 
       options.receivedPages = 0;
       options.pages = [];
     } else if (options.pages[index]) {
       // Duplicated page?
       if (DEBUG) {
-        debug("Got duplicated page no." + index + " of a multipage SMSCB: "
-              + JSON.stringify(original));
+        this.context.debug("Got duplicated page no." + index +
+                           " of a multipage SMSCB: " + JSON.stringify(original));
       }
       return null;
     }
 
     if (options.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
       options.pages[index] = original.data;
       delete original.data;
     } else {
       options.pages[index] = original.body;
       delete original.body;
     }
     options.receivedPages++;
     if (options.receivedPages < options.numPages) {
       if (DEBUG) {
-        debug("Got page no." + index + " of a multipage SMSCB: "
-              + JSON.stringify(options));
+        this.context.debug("Got page no." + index + " of a multipage SMSCB: " +
+                           JSON.stringify(options));
       }
       return null;
     }
 
     // Remove from map
     delete this._receivedSmsCbPagesMap[hash];
 
     // Rebuild full body
@@ -4631,17 +4773,17 @@ let RIL = {
           options.fullData[d++] = data[j];
         }
       }
     } else {
       options.fullBody = options.pages.join("");
     }
 
     if (DEBUG) {
-      debug("Got full multipage SMSCB: " + JSON.stringify(options));
+      this.context.debug("Got full multipage SMSCB: " + JSON.stringify(options));
     }
 
     return options;
   },
 
   _mergeCellBroadcastConfigs: function(list, from, to) {
     if (!list) {
       return [from, to];
@@ -4753,46 +4895,48 @@ let RIL = {
   },
 
   /**
    * Merge all members of cellBroadcastConfigs into mergedCellBroadcastConfig.
    */
   _mergeAllCellBroadcastConfigs: function() {
     if (!this._isCellBroadcastConfigReady()) {
       if (DEBUG) {
-        debug("cell broadcast configs not ready, waiting ...");
+        this.context.debug("cell broadcast configs not ready, waiting ...");
       }
       return;
     }
 
     // Prepare cell broadcast config. CBMI* are only used in GSM.
     let usedCellBroadcastConfigs = {MMI: this.cellBroadcastConfigs.MMI};
     if (!this._isCdma) {
       usedCellBroadcastConfigs.CBMI = this.cellBroadcastConfigs.CBMI;
       usedCellBroadcastConfigs.CBMID = this.cellBroadcastConfigs.CBMID;
       usedCellBroadcastConfigs.CBMIR = this.cellBroadcastConfigs.CBMIR;
     }
 
     if (DEBUG) {
-      debug("Cell Broadcast search lists: " + JSON.stringify(usedCellBroadcastConfigs));
+      this.context.debug("Cell Broadcast search lists: " +
+                         JSON.stringify(usedCellBroadcastConfigs));
     }
 
     let list = null;
     for each (let ll in usedCellBroadcastConfigs) {
       if (ll == null) {
         continue;
       }
 
       for (let i = 0; i < ll.length; i += 2) {
         list = this._mergeCellBroadcastConfigs(list, ll[i], ll[i + 1]);
       }
     }
 
     if (DEBUG) {
-      debug("Cell Broadcast search lists(merged): " + JSON.stringify(list));
+      this.context.debug("Cell Broadcast search lists(merged): " +
+                         JSON.stringify(list));
     }
     this.mergedCellBroadcastConfig = list;
     this.updateCellBroadcastConfig();
   },
 
   /**
    * Check whether search list from settings is settable by MMI, that is,
    * whether the range is bounded in any entries of CB_NON_MMI_SETTABLE_RANGES.
@@ -4854,32 +4998,35 @@ let RIL = {
 
   /**
    * Handle incoming messages from the main UI thread.
    *
    * @param message
    *        Object containing the message. Messages are supposed
    */
   handleChromeMessage: function(message) {
-    if (DEBUG) debug("Received chrome message " + JSON.stringify(message));
+    if (DEBUG) {
+      this.context.debug("Received chrome message " + JSON.stringify(message));
+    }
     let method = this[message.rilMessageType];
     if (typeof method != "function") {
       if (DEBUG) {
-        debug("Don't know what to do with message " + JSON.stringify(message));
+        this.context.debug("Don't know what to do with message " +
+                           JSON.stringify(message));
       }
       return;
     }
     method.call(this, message);
   },
 
   /**
    * Get a list of current voice calls.
    */
   enumerateCalls: function(options) {
-    if (DEBUG) debug("Sending all current calls");
+    if (DEBUG) this.context.debug("Sending all current calls");
     let calls = [];
     for each (let call in this.currentCalls) {
       calls.push(call);
     }
     options.calls = calls;
     this.sendChromeMessage(options);
   },
 
@@ -4894,110 +5041,95 @@ let RIL = {
     this.sendChromeMessage({rilMessageType: "datacalllist",
                             datacalls: datacall_list});
   },
 
   /**
    * Process STK Proactive Command.
    */
   processStkProactiveCommand: function() {
+    let Buf = this.context.Buf;
     let length = Buf.readInt32();
     let berTlv;
     try {
-      berTlv = BerTlvHelper.decode(length / 2);
+      berTlv = this.context.BerTlvHelper.decode(length / 2);
     } catch (e) {
-      if (DEBUG) debug("processStkProactiveCommand : " + e);
-      RIL.sendStkTerminalResponse({
+      if (DEBUG) this.context.debug("processStkProactiveCommand : " + e);
+      this.sendStkTerminalResponse({
         resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
       return;
     }
 
     Buf.readStringDelimiter(length);
 
     let ctlvs = berTlv.value;
-    let ctlv = StkProactiveCmdHelper.searchForTag(
+    let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
         COMPREHENSIONTLV_TAG_COMMAND_DETAILS, ctlvs);
     if (!ctlv) {
-      RIL.sendStkTerminalResponse({
+      this.sendStkTerminalResponse({
         resultCode: STK_RESULT_CMD_DATA_NOT_UNDERSTOOD});
       throw new Error("Can't find COMMAND_DETAILS ComprehensionTlv");
     }
 
     let cmdDetails = ctlv.value;
     if (DEBUG) {
-      debug("commandNumber = " + cmdDetails.commandNumber +
-           " typeOfCommand = " + cmdDetails.typeOfCommand.toString(16) +
-           " commandQualifier = " + cmdDetails.commandQualifier);
+      this.context.debug("commandNumber = " + cmdDetails.commandNumber +
+                         " typeOfCommand = " + cmdDetails.typeOfCommand.toString(16) +
+                         " commandQualifier = " + cmdDetails.commandQualifier);
     }
 
     // STK_CMD_MORE_TIME need not to propagate event to chrome.
     if (cmdDetails.typeOfCommand == STK_CMD_MORE_TIME) {
-      RIL.sendStkTerminalResponse({
+      this.sendStkTerminalResponse({
         command: cmdDetails,
         resultCode: STK_RESULT_OK});
       return;
     }
 
     cmdDetails.rilMessageType = "stkcommand";
-    cmdDetails.options = StkCommandParamsFactory.createParam(cmdDetails, ctlvs);
-    RIL.sendChromeMessage(cmdDetails);
+    cmdDetails.options =
+      this.context.StkCommandParamsFactory.createParam(cmdDetails, ctlvs);
+    this.sendChromeMessage(cmdDetails);
   },
 
   /**
    * Send messages to the main thread.
    */
   sendChromeMessage: function(message) {
+    message.rilMessageClientId = this.context.clientId;
     postMessage(message);
   },
 
   /**
    * 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(request_type, length, options) {
     let method = this[request_type];
     if (typeof method == "function") {
-      if (DEBUG) debug("Handling parcel as " + method.name);
+      if (DEBUG) this.context.debug("Handling parcel as " + method.name);
       method.call(this, length, options);
     }
-  },
-
-  setInitialOptions: function(options) {
-    DEBUG = DEBUG_WORKER || options.debug;
-    CLIENT_ID = options.clientId;
-    this.cellBroadcastDisabled = options.cellBroadcastDisabled;
-    this.clirMode = options.clirMode;
-    RIL_EMERGENCY_NUMBERS = options.rilEmergencyNumbers;
-    let quirks = options.quirks;
-    RILQUIRKS_CALLSTATE_EXTRA_UINT32 = quirks.callstateExtraUint32;
-    RILQUIRKS_V5_LEGACY = quirks.v5Legacy;
-    RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = quirks.requestUseDialEmergencyCall;
-    RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = quirks.simAppStateExtraFields;
-    RILQUIRKS_EXTRA_UINT32_2ND_CALL = quirks.extraUint2ndCall;
-    RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT = quirks.haveQueryIccLockRetryCount;
-    RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD = quirks.sendStkProfileDownload;
-    RILQUIRKS_DATA_REGISTRATION_ON_DEMAND = quirks.dataRegistrationOnDemand;
-  }
-};
-
-RIL.initRILState();
-
-RIL[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS(length, options) {
+  }
+};
+
+RilObject.prototype[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   let iccStatus = {};
+  let Buf = this.context.Buf;
   iccStatus.cardState = Buf.readInt32(); // CARD_STATE_*
   iccStatus.universalPINState = Buf.readInt32(); // CARD_PINSTATE_*
   iccStatus.gsmUmtsSubscriptionAppIndex = Buf.readInt32();
   iccStatus.cdmaSubscriptionAppIndex = Buf.readInt32();
-  if (!RILQUIRKS_V5_LEGACY) {
+  if (!this.v5Legacy) {
     iccStatus.imsSubscriptionAppIndex = Buf.readInt32();
   }
 
   let apps_length = Buf.readInt32();
   if (apps_length > CARD_MAX_APPS) {
     apps_length = CARD_MAX_APPS;
   }
 
@@ -5016,46 +5148,47 @@ RIL[REQUEST_GET_SIM_STATUS] = function R
     if (RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS) {
       Buf.readInt32();
       Buf.readInt32();
       Buf.readInt32();
       Buf.readInt32();
     }
   }
 
-  if (DEBUG) debug("iccStatus: " + JSON.stringify(iccStatus));
+  if (DEBUG) this.context.debug("iccStatus: " + JSON.stringify(iccStatus));
   this._processICCStatus(iccStatus);
 };
-RIL[REQUEST_ENTER_SIM_PIN] = function REQUEST_ENTER_SIM_PIN(length, options) {
+RilObject.prototype[REQUEST_ENTER_SIM_PIN] = function REQUEST_ENTER_SIM_PIN(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_ENTER_SIM_PUK] = function REQUEST_ENTER_SIM_PUK(length, options) {
+RilObject.prototype[REQUEST_ENTER_SIM_PUK] = function REQUEST_ENTER_SIM_PUK(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_ENTER_SIM_PIN2] = function REQUEST_ENTER_SIM_PIN2(length, options) {
+RilObject.prototype[REQUEST_ENTER_SIM_PIN2] = function REQUEST_ENTER_SIM_PIN2(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_ENTER_SIM_PUK2] = function REQUEST_ENTER_SIM_PUK(length, options) {
+RilObject.prototype[REQUEST_ENTER_SIM_PUK2] = function REQUEST_ENTER_SIM_PUK(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_CHANGE_SIM_PIN] = function REQUEST_CHANGE_SIM_PIN(length, options) {
+RilObject.prototype[REQUEST_CHANGE_SIM_PIN] = function REQUEST_CHANGE_SIM_PIN(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_CHANGE_SIM_PIN2] = function REQUEST_CHANGE_SIM_PIN2(length, options) {
+RilObject.prototype[REQUEST_CHANGE_SIM_PIN2] = function REQUEST_CHANGE_SIM_PIN2(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE] =
+RilObject.prototype[REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE] =
   function REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length, options) {
+RilObject.prototype[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
+  let Buf = this.context.Buf;
   let calls_length = 0;
   // The RIL won't even send us the length integer if there are no active calls.
   // So only read this integer if the parcel actually has it.
   if (length) {
     calls_length = Buf.readInt32();
   }
   if (!calls_length) {
     this._processCalls(null);
@@ -5097,269 +5230,274 @@ RIL[REQUEST_GET_CURRENT_CALLS] = functio
         userData: null //XXX TODO byte array?!?
       };
     }
 
     calls[call.callIndex] = call;
   }
   this._processCalls(calls);
 };
-RIL[REQUEST_DIAL] = function REQUEST_DIAL(length, options) {
+RilObject.prototype[REQUEST_DIAL] = function REQUEST_DIAL(length, options) {
   options.success = (options.rilRequestError === 0);
   if (options.success) {
     this.sendChromeMessage(options);
   } else {
     this.getFailCauseCode((function(options, failCause) {
       options.errorMsg = failCause;
       this.sendChromeMessage(options);
     }).bind(this, options));
   }
 };
-RIL[REQUEST_GET_IMSI] = function REQUEST_GET_IMSI(length, options) {
+RilObject.prototype[REQUEST_GET_IMSI] = function REQUEST_GET_IMSI(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
-  this.iccInfoPrivate.imsi = Buf.readString();
+  this.iccInfoPrivate.imsi = this.context.Buf.readString();
   if (DEBUG) {
-    debug("IMSI: " + this.iccInfoPrivate.imsi);
+    this.context.debug("IMSI: " + this.iccInfoPrivate.imsi);
   }
 
   options.rilMessageType = "iccimsi";
   options.imsi = this.iccInfoPrivate.imsi;
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_HANGUP] = function REQUEST_HANGUP(length, options) {
+RilObject.prototype[REQUEST_HANGUP] = function REQUEST_HANGUP(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.getCurrentCalls();
 };
-RIL[REQUEST_HANGUP_WAITING_OR_BACKGROUND] = function REQUEST_HANGUP_WAITING_OR_BACKGROUND(length, options) {
+RilObject.prototype[REQUEST_HANGUP_WAITING_OR_BACKGROUND] = function REQUEST_HANGUP_WAITING_OR_BACKGROUND(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.getCurrentCalls();
 };
-RIL[REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] = function REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND(length, options) {
+RilObject.prototype[REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] = function REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.getCurrentCalls();
 };
-RIL[REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE(length, options) {
+RilObject.prototype[REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.getCurrentCalls();
 };
-RIL[REQUEST_SWITCH_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_HOLDING_AND_ACTIVE(length, options) {
+RilObject.prototype[REQUEST_SWITCH_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_HOLDING_AND_ACTIVE(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   // XXX Normally we should get a UNSOLICITED_RESPONSE_CALL_STATE_CHANGED parcel
   // notifying us of call state changes, but sometimes we don't (have no idea why).
   // this.getCurrentCalls() helps update the call state actively.
   this.getCurrentCalls();
 };
-RIL[REQUEST_CONFERENCE] = function REQUEST_CONFERENCE(length, options) {
+RilObject.prototype[REQUEST_CONFERENCE] = function REQUEST_CONFERENCE(length, options) {
   if (options.rilRequestError) {
     this._hasConferenceRequest = false;
     options = {rilMessageType: "conferenceError",
                errorName: "addError",
                errorMsg: RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]};
     this.sendChromeMessage(options);
     return;
   }
 };
-RIL[REQUEST_UDUB] = null;
-RIL[REQUEST_LAST_CALL_FAIL_CAUSE] = function REQUEST_LAST_CALL_FAIL_CAUSE(length, options) {
+RilObject.prototype[REQUEST_UDUB] = null;
+RilObject.prototype[REQUEST_LAST_CALL_FAIL_CAUSE] = function REQUEST_LAST_CALL_FAIL_CAUSE(length, options) {
+  let Buf = this.context.Buf;
   let num = length ? Buf.readInt32() : 0;
   let failCause = num ? RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[Buf.readInt32()] : null;
   if (options.callback) {
     options.callback(failCause);
   }
 };
-RIL[REQUEST_SIGNAL_STRENGTH] = function REQUEST_SIGNAL_STRENGTH(length, options) {
+RilObject.prototype[REQUEST_SIGNAL_STRENGTH] = function REQUEST_SIGNAL_STRENGTH(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_SIGNAL);
 
   if (options.rilRequestError) {
     return;
   }
 
+  let Buf = this.context.Buf;
   let signal = {
     gsmSignalStrength: Buf.readInt32(),
     gsmBitErrorRate:   Buf.readInt32(),
     cdmaDBM:           Buf.readInt32(),
     cdmaECIO:          Buf.readInt32(),
     evdoDBM:           Buf.readInt32(),
     evdoECIO:          Buf.readInt32(),
     evdoSNR:           Buf.readInt32()
   };
 
-  if (!RILQUIRKS_V5_LEGACY) {
+  if (!this.v5Legacy) {
     signal.lteSignalStrength = Buf.readInt32();
     signal.lteRSRP =           Buf.readInt32();
     signal.lteRSRQ =           Buf.readInt32();
     signal.lteRSSNR =          Buf.readInt32();
     signal.lteCQI =            Buf.readInt32();
   }
 
-  if (DEBUG) debug("signal strength: " + JSON.stringify(signal));
+  if (DEBUG) this.context.debug("signal strength: " + JSON.stringify(signal));
 
   this._processSignalStrength(signal);
 };
-RIL[REQUEST_VOICE_REGISTRATION_STATE] = function REQUEST_VOICE_REGISTRATION_STATE(length, options) {
+RilObject.prototype[REQUEST_VOICE_REGISTRATION_STATE] = function REQUEST_VOICE_REGISTRATION_STATE(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_VOICE_REGISTRATION_STATE);
 
   if (options.rilRequestError) {
     return;
   }
 
-  let state = Buf.readStringList();
-  if (DEBUG) debug("voice registration state: " + state);
+  let state = this.context.Buf.readStringList();
+  if (DEBUG) this.context.debug("voice registration state: " + state);
 
   this._processVoiceRegistrationState(state);
 
   if (this.cachedDialRequest &&
        (this.voiceRegistrationState.emergencyCallsOnly ||
         this.voiceRegistrationState.connected) &&
       this.voiceRegistrationState.radioTech != NETWORK_CREG_TECH_UNKNOWN) {
     // Radio is ready for making the cached emergency call.
     this.cachedDialRequest.callback();
     this.cachedDialRequest = null;
   }
 };
-RIL[REQUEST_DATA_REGISTRATION_STATE] = function REQUEST_DATA_REGISTRATION_STATE(length, options) {
+RilObject.prototype[REQUEST_DATA_REGISTRATION_STATE] = function REQUEST_DATA_REGISTRATION_STATE(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_DATA_REGISTRATION_STATE);
 
   if (options.rilRequestError) {
     return;
   }
 
-  let state = Buf.readStringList();
+  let state = this.context.Buf.readStringList();
   this._processDataRegistrationState(state);
 };
-RIL[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length, options) {
+RilObject.prototype[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_OPERATOR);
 
   if (options.rilRequestError) {
     return;
   }
 
-  let operatorData = Buf.readStringList();
-  if (DEBUG) debug("Operator: " + operatorData);
+  let operatorData = this.context.Buf.readStringList();
+  if (DEBUG) this.context.debug("Operator: " + operatorData);
   this._processOperator(operatorData);
 };
-RIL[REQUEST_RADIO_POWER] = function REQUEST_RADIO_POWER(length, options) {
+RilObject.prototype[REQUEST_RADIO_POWER] = function REQUEST_RADIO_POWER(length, options) {
   if (options.rilMessageType == null) {
     // The request was made by ril_worker itself.
     if (options.rilRequestError) {
       if (this.cachedDialRequest && options.enabled) {
         // Turning on radio fails. Notify the error of making an emergency call.
         this.cachedDialRequest.onerror(GECKO_ERROR_RADIO_NOT_AVAILABLE);
         this.cachedDialRequest = null;
       }
     }
     return;
   }
 
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_DTMF] = null;
-RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) {
+RilObject.prototype[REQUEST_DTMF] = null;
+RilObject.prototype[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) {
   this._processSmsSendResult(length, options);
 };
-RIL[REQUEST_SEND_SMS_EXPECT_MORE] = null;
-
-RIL.readSetupDataCall_v5 = function readSetupDataCall_v5(options) {
+RilObject.prototype[REQUEST_SEND_SMS_EXPECT_MORE] = null;
+
+RilObject.prototype.readSetupDataCall_v5 = function readSetupDataCall_v5(options) {
   if (!options) {
     options = {};
   }
-  let [cid, ifname, ipaddr, dns, gw] = Buf.readStringList();
+  let [cid, ifname, ipaddr, dns, gw] = this.context.Buf.readStringList();
   options.cid = cid;
   options.ifname = ifname;
   options.ipaddr = ipaddr;
   options.dns = dns;
   options.gw = gw;
   options.active = DATACALL_ACTIVE_UNKNOWN;
   options.state = GECKO_NETWORK_STATE_CONNECTING;
   return options;
 };
 
-RIL[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL(length, options) {
+RilObject.prototype[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL(length, options) {
   if (options.rilRequestError) {
     // On Data Call generic errors, we shall notify caller
     this._sendDataCallError(options, options.rilRequestError);
     return;
   }
 
-  if (RILQUIRKS_V5_LEGACY) {
+  if (this.v5Legacy) {
     // Populate the `options` object with the data call information. That way
     // we retain the APN and other info about how the data call was set up.
     this.readSetupDataCall_v5(options);
     this.currentDataCalls[options.cid] = options;
     options.rilMessageType = "datacallstatechange";
     this.sendChromeMessage(options);
     // Let's get the list of data calls to ensure we know whether it's active
     // or not.
     this.getDataCallList();
     return;
   }
   // Pass `options` along. That way we retain the APN and other info about
   // how the data call was set up.
   this[REQUEST_DATA_CALL_LIST](length, options);
 };
-RIL[REQUEST_SIM_IO] = function REQUEST_SIM_IO(length, options) {
+RilObject.prototype[REQUEST_SIM_IO] = function REQUEST_SIM_IO(length, options) {
+  let ICCIOHelper = this.context.ICCIOHelper;
   if (!length) {
     ICCIOHelper.processICCIOError(options);
     return;
   }
 
   // Don't need to read rilRequestError since we can know error status from
   // sw1 and sw2.
+  let Buf = this.context.Buf;
   options.sw1 = Buf.readInt32();
   options.sw2 = Buf.readInt32();
   if (options.sw1 != ICC_STATUS_NORMAL_ENDING) {
     ICCIOHelper.processICCIOError(options);
     return;
   }
   ICCIOHelper.processICCIO(options);
 };
-RIL[REQUEST_SEND_USSD] = function REQUEST_SEND_USSD(length, options) {
+RilObject.prototype[REQUEST_SEND_USSD] = function REQUEST_SEND_USSD(length, options) {
   if (DEBUG) {
-    debug("REQUEST_SEND_USSD " + JSON.stringify(options));
+    this.context.debug("REQUEST_SEND_USSD " + JSON.stringify(options));
   }
   options.success = (this._ussdSession = options.rilRequestError === 0);
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_CANCEL_USSD] = function REQUEST_CANCEL_USSD(length, options) {
+RilObject.prototype[REQUEST_CANCEL_USSD] = function REQUEST_CANCEL_USSD(length, options) {
   if (DEBUG) {
-    debug("REQUEST_CANCEL_USSD" + JSON.stringify(options));
+    this.context.debug("REQUEST_CANCEL_USSD" + JSON.stringify(options));
   }
   options.success = (options.rilRequestError === 0);
   this._ussdSession = !options.success;
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_GET_CLIR] = function REQUEST_GET_CLIR(length, options) {
+RilObject.prototype[REQUEST_GET_CLIR] = function REQUEST_GET_CLIR(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
+  let Buf = this.context.Buf;
   let bufLength = Buf.readInt32();
   if (!bufLength || bufLength < 2) {
     options.success = false;
     options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
     this.sendChromeMessage(options);
     return;
   }
 
@@ -5426,17 +5564,17 @@ RIL[REQUEST_GET_CLIR] = function REQUEST
         options.success = false;
         options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
         break;
     }
   }
 
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SET_CLIR] = function REQUEST_SET_CLIR(length, options) {
+RilObject.prototype[REQUEST_SET_CLIR] = function REQUEST_SET_CLIR(length, options) {
   if (options.rilMessageType == null) {
     // The request was made by ril_worker itself automatically. Don't report.
     return;
   }
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   } else if (options.rilMessageType === "sendMMI") {
@@ -5447,25 +5585,26 @@ RIL[REQUEST_SET_CLIR] = function REQUEST
       case MMI_PROCEDURE_DEACTIVATION:
         options.statusMessage = MMI_SM_KS_SERVICE_DISABLED;
         break;
     }
   }
   this.sendChromeMessage(options);
 };
 
-RIL[REQUEST_QUERY_CALL_FORWARD_STATUS] =
+RilObject.prototype[REQUEST_QUERY_CALL_FORWARD_STATUS] =
   function REQUEST_QUERY_CALL_FORWARD_STATUS(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
+  let Buf = this.context.Buf;
   let rulesLength = 0;
   if (length) {
     rulesLength = Buf.readInt32();
   }
   if (!rulesLength) {
     options.success = false;
     options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
     this.sendChromeMessage(options);
@@ -5487,17 +5626,17 @@ RIL[REQUEST_QUERY_CALL_FORWARD_STATUS] =
     options.statusMessage = MMI_SM_KS_SERVICE_INTERROGATED;
     // MMI query call forwarding options request returns a set of rules that
     // will be exposed in the form of an array of nsIDOMMozMobileCFInfo
     // instances.
     options.additionalInformation = rules;
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SET_CALL_FORWARD] =
+RilObject.prototype[REQUEST_SET_CALL_FORWARD] =
   function REQUEST_SET_CALL_FORWARD(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   } else if (options.rilMessageType === "sendMMI") {
     switch (options.action) {
       case CALL_FORWARD_ACTION_ENABLE:
         options.statusMessage = MMI_SM_KS_SERVICE_ENABLED;
@@ -5510,97 +5649,98 @@ RIL[REQUEST_SET_CALL_FORWARD] =
         break;
       case CALL_FORWARD_ACTION_ERASURE:
         options.statusMessage = MMI_SM_KS_SERVICE_ERASED;
         break;
     }
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_QUERY_CALL_WAITING] =
+RilObject.prototype[REQUEST_QUERY_CALL_WAITING] =
   function REQUEST_QUERY_CALL_WAITING(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   if (options.callback) {
     options.callback.call(this, options);
     return;
   }
 
+  let Buf = this.context.Buf;
   options.length = Buf.readInt32();
   options.enabled = ((Buf.readInt32() == 1) &&
                      ((Buf.readInt32() & ICC_SERVICE_CLASS_VOICE) == 0x01));
   this.sendChromeMessage(options);
 };
 
-RIL[REQUEST_SET_CALL_WAITING] = function REQUEST_SET_CALL_WAITING(length, options) {
+RilObject.prototype[REQUEST_SET_CALL_WAITING] = function REQUEST_SET_CALL_WAITING(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   if (options.callback) {
     options.callback.call(this, options);
     return;
   }
 
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SMS_ACKNOWLEDGE] = null;
-RIL[REQUEST_GET_IMEI] = function REQUEST_GET_IMEI(length, options) {
-  this.IMEI = Buf.readString();
+RilObject.prototype[REQUEST_SMS_ACKNOWLEDGE] = null;
+RilObject.prototype[REQUEST_GET_IMEI] = function REQUEST_GET_IMEI(length, options) {
+  this.IMEI = this.context.Buf.readString();
   let rilMessageType = options.rilMessageType;
   // So far we only send the IMEI back to chrome if it was requested via MMI.
   if (rilMessageType !== "sendMMI") {
     return;
   }
 
   options.success = (options.rilRequestError === 0);
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   if ((!options.success || this.IMEI == null) && !options.errorMsg) {
     options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
   }
   options.statusMessage = this.IMEI;
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_GET_IMEISV] = function REQUEST_GET_IMEISV(length, options) {
+RilObject.prototype[REQUEST_GET_IMEISV] = function REQUEST_GET_IMEISV(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
-  this.IMEISV = Buf.readString();
-};
-RIL[REQUEST_ANSWER] = null;
-RIL[REQUEST_DEACTIVATE_DATA_CALL] = function REQUEST_DEACTIVATE_DATA_CALL(length, options) {
+  this.IMEISV = this.context.Buf.readString();
+};
+RilObject.prototype[REQUEST_ANSWER] = null;
+RilObject.prototype[REQUEST_DEACTIVATE_DATA_CALL] = function REQUEST_DEACTIVATE_DATA_CALL(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   let datacall = this.currentDataCalls[options.cid];
   delete this.currentDataCalls[options.cid];
   datacall.state = GECKO_NETWORK_STATE_UNKNOWN;
   datacall.rilMessageType = "datacallstatechange";
   this.sendChromeMessage(datacall);
 };
-RIL[REQUEST_QUERY_FACILITY_LOCK] = function REQUEST_QUERY_FACILITY_LOCK(length, options) {
+RilObject.prototype[REQUEST_QUERY_FACILITY_LOCK] = function REQUEST_QUERY_FACILITY_LOCK(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
 
   let services;
   if (length) {
     // Buf.readInt32List()[0] for Call Barring is a bit vector of services.
-    services = Buf.readInt32List()[0];
+    services = this.context.Buf.readInt32List()[0];
   } else {
     options.success = false;
     options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
     this.sendChromeMessage(options);
     return;
   }
 
   options.enabled = services === 0 ? false : true;
@@ -5619,87 +5759,92 @@ RIL[REQUEST_QUERY_FACILITY_LOCK] = funct
         }
       }
 
       options.additionalInformation = serviceClass;
     }
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SET_FACILITY_LOCK] = function REQUEST_SET_FACILITY_LOCK(length, options) {
+RilObject.prototype[REQUEST_SET_FACILITY_LOCK] = function REQUEST_SET_FACILITY_LOCK(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
 
-  options.retryCount = length ? Buf.readInt32List()[0] : -1;
+  options.retryCount = length ? this.context.Buf.readInt32List()[0] : -1;
 
   if (options.success && (options.rilMessageType === "sendMMI")) {
     switch (options.procedure) {
       case MMI_PROCEDURE_ACTIVATION:
         options.statusMessage = MMI_SM_KS_SERVICE_ENABLED;
         break;
       case MMI_PROCEDURE_DEACTIVATION:
         options.statusMessage = MMI_SM_KS_SERVICE_DISABLED;
         break;
     }
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_CHANGE_BARRING_PASSWORD] =
+RilObject.prototype[REQUEST_CHANGE_BARRING_PASSWORD] =
   function REQUEST_CHANGE_BARRING_PASSWORD(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SIM_OPEN_CHANNEL] = function REQUEST_SIM_OPEN_CHANNEL(length, options) {
+RilObject.prototype[REQUEST_SIM_OPEN_CHANNEL] = function REQUEST_SIM_OPEN_CHANNEL(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
-  options.channel = Buf.readInt32();
-  if (DEBUG) debug("Setting channel number in options: " + options.channel);
+  options.channel = this.context.Buf.readInt32();
+  if (DEBUG) {
+    this.context.debug("Setting channel number in options: " + options.channel);
+  }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SIM_CLOSE_CHANNEL] = function REQUEST_SIM_CLOSE_CHANNEL(length, options) {
+RilObject.prototype[REQUEST_SIM_CLOSE_CHANNEL] = function REQUEST_SIM_CLOSE_CHANNEL(length, options) {
   if (options.rilRequestError) {
     options.error = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   // No return value
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SIM_ACCESS_CHANNEL] = function REQUEST_SIM_ACCESS_CHANNEL(length, options) {
+RilObject.prototype[REQUEST_SIM_ACCESS_CHANNEL] = function REQUEST_SIM_ACCESS_CHANNEL(length, options) {
   if (options.rilRequestError) {
     options.error = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
   }
 
+  let Buf = this.context.Buf;
   options.sw1 = Buf.readInt32();
   options.sw2 = Buf.readInt32();
   options.simResponse = Buf.readString();
   if (DEBUG) {
-    debug("Setting return values for RIL[REQUEST_SIM_ACCESS_CHANNEL]: ["
-          + options.sw1 + "," + options.sw2 + ", " + options.simResponse + "]");
+    this.context.debug("Setting return values for RIL[REQUEST_SIM_ACCESS_CHANNEL]: [" +
+                       options.sw1 + "," +
+                       options.sw2 + ", " +
+                       options.simResponse + "]");
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_QUERY_NETWORK_SELECTION_MODE] = function REQUEST_QUERY_NETWORK_SELECTION_MODE(length, options) {
+RilObject.prototype[REQUEST_QUERY_NETWORK_SELECTION_MODE] = function REQUEST_QUERY_NETWORK_SELECTION_MODE(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_NETWORK_SELECTION_MODE);
 
   if (options.rilRequestError) {
     return;
   }
 
-  let mode = Buf.readInt32List();
+  let mode = this.context.Buf.readInt32List();
   let selectionMode;
 
   switch (mode[0]) {
     case NETWORK_SELECTION_MODE_AUTOMATIC:
       selectionMode = GECKO_NETWORK_SELECTION_AUTOMATIC;
       break;
     case NETWORK_SELECTION_MODE_MANUAL:
       selectionMode = GECKO_NETWORK_SELECTION_MANUAL;
@@ -5710,67 +5855,68 @@ RIL[REQUEST_QUERY_NETWORK_SELECTION_MODE
   }
 
   if (this.networkSelectionMode != selectionMode) {
     this.networkSelectionMode = options.mode = selectionMode;
     options.rilMessageType = "networkselectionmodechange";
     this._sendNetworkInfoMessage(NETWORK_INFO_NETWORK_SELECTION_MODE, options);
   }
 };
-RIL[REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = function REQUEST_SET_NETWORK_SELECTION_AUTOMATIC(length, options) {
+RilObject.prototype[REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = function REQUEST_SET_NETWORK_SELECTION_AUTOMATIC(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
 
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SET_NETWORK_SELECTION_MANUAL] = function REQUEST_SET_NETWORK_SELECTION_MANUAL(length, options) {
+RilObject.prototype[REQUEST_SET_NETWORK_SELECTION_MANUAL] = function REQUEST_SET_NETWORK_SELECTION_MANUAL(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
 
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_QUERY_AVAILABLE_NETWORKS] = function REQUEST_QUERY_AVAILABLE_NETWORKS(length, options) {
+RilObject.prototype[REQUEST_QUERY_AVAILABLE_NETWORKS] = function REQUEST_QUERY_AVAILABLE_NETWORKS(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   } else {
     options.networks = this._processNetworks();
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_DTMF_START] = null;
-RIL[REQUEST_DTMF_STOP] = null;
-RIL[REQUEST_BASEBAND_VERSION] = function REQUEST_BASEBAND_VERSION(length, options) {
+RilObject.prototype[REQUEST_DTMF_START] = null;
+RilObject.prototype[REQUEST_DTMF_STOP] = null;
+RilObject.prototype[REQUEST_BASEBAND_VERSION] = function REQUEST_BASEBAND_VERSION(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
-  this.basebandVersion = Buf.readString();
-  if (DEBUG) debug("Baseband version: " + this.basebandVersion);
-};
-RIL[REQUEST_SEPARATE_CONNECTION] = function REQUEST_SEPARATE_CONNECTION(length, options) {
+  this.basebandVersion = this.context.Buf.readString();
+  if (DEBUG) this.context.debug("Baseband version: " + this.basebandVersion);
+};
+RilObject.prototype[REQUEST_SEPARATE_CONNECTION] = function REQUEST_SEPARATE_CONNECTION(length, options) {
   if (options.rilRequestError) {
     options = {rilMessageType: "conferenceError",
                errorName: "removeError",
                errorMsg: RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]};
     this.sendChromeMessage(options);
     return;
   }
 };
-RIL[REQUEST_SET_MUTE] = null;
-RIL[REQUEST_GET_MUTE] = null;
-RIL[REQUEST_QUERY_CLIP] = function REQUEST_QUERY_CLIP(length, options) {
+RilObject.prototype[REQUEST_SET_MUTE] = null;
+RilObject.prototype[REQUEST_GET_MUTE] = null;
+RilObject.prototype[REQUEST_QUERY_CLIP] = function REQUEST_QUERY_CLIP(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
+  let Buf = this.context.Buf;
   let bufLength = Buf.readInt32();
   if (!bufLength) {
     options.success = false;
     options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
     this.sendChromeMessage(options);
     return;
   }
 
@@ -5791,34 +5937,36 @@ RIL[REQUEST_QUERY_CLIP] = function REQUE
       default:
         options.success = false;
         options.errorMsg = MMI_ERROR_KS_ERROR;
         break;
     }
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_LAST_DATA_CALL_FAIL_CAUSE] = null;
-
-RIL.readDataCall_v5 = function(options) {
+RilObject.prototype[REQUEST_LAST_DATA_CALL_FAIL_CAUSE] = null;
+
+RilObject.prototype.readDataCall_v5 = function(options) {
   if (!options) {
     options = {};
   }
+  let Buf = this.context.Buf;
   options.cid = Buf.readInt32().toString();
   options.active = Buf.readInt32(); // DATACALL_ACTIVE_*
   options.type = Buf.readString();
   options.apn = Buf.readString();
   options.address = Buf.readString();
   return options;
 };
 
-RIL.readDataCall_v6 = function(options) {
+RilObject.prototype.readDataCall_v6 = function(options) {
   if (!options) {
     options = {};
   }
+  let Buf = this.context.Buf;
   options.status = Buf.readInt32();  // DATACALL_FAIL_*
   options.suggestedRetryTime = Buf.readInt32();
   options.cid = Buf.readInt32().toString();
   options.active = Buf.readInt32();  // DATACALL_ACTIVE_*
   options.type = Buf.readString();
   options.ifname = Buf.readString();
   options.ipaddr = Buf.readString();
   options.dns = Buf.readString();
@@ -5831,28 +5979,29 @@ RIL.readDataCall_v6 = function(options) 
     options.ipaddr = options.ipaddr.split(" ")[0];
   }
   if (options.gw) {
     options.gw = options.gw.split(" ")[0];
   }
   return options;
 };
 
-RIL[REQUEST_DATA_CALL_LIST] = function REQUEST_DATA_CALL_LIST(length, options) {
+RilObject.prototype[REQUEST_DATA_CALL_LIST] = function REQUEST_DATA_CALL_LIST(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   if (!length) {
     this._processDataCallList(null);
     return;
   }
 
+  let Buf = this.context.Buf;
   let version = 0;
-  if (!RILQUIRKS_V5_LEGACY) {
+  if (!this.v5Legacy) {
     version = Buf.readInt32();
   }
   let num = Buf.readInt32();
   let datacalls = {};
   for (let i = 0; i < num; i++) {
     let datacall;
     if (version < 6) {
       datacall = this.readDataCall_v5();
@@ -5863,192 +6012,194 @@ RIL[REQUEST_DATA_CALL_LIST] = function R
   }
 
   let newDataCallOptions = null;
   if (options.rilRequestType == REQUEST_SETUP_DATA_CALL) {
     newDataCallOptions = options;
   }
   this._processDataCallList(datacalls, newDataCallOptions);
 };
-RIL[REQUEST_RESET_RADIO] = null;
-RIL[REQUEST_OEM_HOOK_RAW] = null;
-RIL[REQUEST_OEM_HOOK_STRINGS] = null;
-RIL[REQUEST_SCREEN_STATE] = null;
-RIL[REQUEST_SET_SUPP_SVC_NOTIFICATION] = null;
-RIL[REQUEST_WRITE_SMS_TO_SIM] = function REQUEST_WRITE_SMS_TO_SIM(length, options) {
+RilObject.prototype[REQUEST_RESET_RADIO] = null;
+RilObject.prototype[REQUEST_OEM_HOOK_RAW] = null;
+RilObject.prototype[REQUEST_OEM_HOOK_STRINGS] = null;
+RilObject.prototype[REQUEST_SCREEN_STATE] = null;
+RilObject.prototype[REQUEST_SET_SUPP_SVC_NOTIFICATION] = null;
+RilObject.prototype[REQUEST_WRITE_SMS_TO_SIM] = function REQUEST_WRITE_SMS_TO_SIM(length, options) {
   if (options.rilRequestError) {
     // `The MS shall return a "protocol error, unspecified" error message if
     // the short message cannot be stored in the (U)SIM, and there is other
     // message storage available at the MS` ~ 3GPP TS 23.038 section 4. Here
     // we assume we always have indexed db as another storage.
     this.acknowledgeGsmSms(false, PDU_FCS_PROTOCOL_ERROR);
   } else {
     this.acknowledgeGsmSms(true, PDU_FCS_OK);
   }
 };
-RIL[REQUEST_DELETE_SMS_ON_SIM] = null;
-RIL[REQUEST_SET_BAND_MODE] = null;
-RIL[REQUEST_QUERY_AVAILABLE_BAND_MODE] = null;
-RIL[REQUEST_STK_GET_PROFILE] = null;
-RIL[REQUEST_STK_SET_PROFILE] = null;
-RIL[REQUEST_STK_SEND_ENVELOPE_COMMAND] = null;
-RIL[REQUEST_STK_SEND_TERMINAL_RESPONSE] = null;
-RIL[REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM] = null;
-RIL[REQUEST_EXPLICIT_CALL_TRANSFER] = null;
-RIL[REQUEST_SET_PREFERRED_NETWORK_TYPE] = function REQUEST_SET_PREFERRED_NETWORK_TYPE(length, options) {
+RilObject.prototype[REQUEST_DELETE_SMS_ON_SIM] = null;
+RilObject.prototype[REQUEST_SET_BAND_MODE] = null;
+RilObject.prototype[REQUEST_QUERY_AVAILABLE_BAND_MODE] = null;
+RilObject.prototype[REQUEST_STK_GET_PROFILE] = null;
+RilObject.prototype[REQUEST_STK_SET_PROFILE] = null;
+RilObject.prototype[REQUEST_STK_SEND_ENVELOPE_COMMAND] = null;
+RilObject.prototype[REQUEST_STK_SEND_TERMINAL_RESPONSE] = null;
+RilObject.prototype[REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM] = null;
+RilObject.prototype[REQUEST_EXPLICIT_CALL_TRANSFER] = null;
+RilObject.prototype[REQUEST_SET_PREFERRED_NETWORK_TYPE] = function REQUEST_SET_PREFERRED_NETWORK_TYPE(length, options) {
   if (options.networkType == null) {
     // The request was made by ril_worker itself automatically. Don't report.
     return;
   }
 
   if (options.rilRequestError) {
     options.success = false;
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   } else {
     options.success = true;
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_GET_PREFERRED_NETWORK_TYPE] = function REQUEST_GET_PREFERRED_NETWORK_TYPE(length, options) {
+RilObject.prototype[REQUEST_GET_PREFERRED_NETWORK_TYPE] = function REQUEST_GET_PREFERRED_NETWORK_TYPE(length, options) {
   if (options.rilRequestError) {
     options.success = false;
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
+  let Buf = this.context.Buf;
   let networkType = RIL_PREFERRED_NETWORK_TYPE_TO_GECKO.indexOf(GECKO_PREFERRED_NETWORK_TYPE_DEFAULT);
   let responseLen = Buf.readInt32(); // Number of INT32 responsed.
   if (responseLen) {
     this.preferredNetworkType = networkType = Buf.readInt32();
   }
   options.networkType = networkType;
   options.success = true;
 
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_GET_NEIGHBORING_CELL_IDS] = null;
-RIL[REQUEST_SET_LOCATION_UPDATES] = null;
-RIL[REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE] = null;
-RIL[REQUEST_CDMA_SET_ROAMING_PREFERENCE] = function REQUEST_CDMA_SET_ROAMING_PREFERENCE(length, options) {
+RilObject.prototype[REQUEST_GET_NEIGHBORING_CELL_IDS] = null;
+RilObject.prototype[REQUEST_SET_LOCATION_UPDATES] = null;
+RilObject.prototype[REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE] = null;
+RilObject.prototype[REQUEST_CDMA_SET_ROAMING_PREFERENCE] = function REQUEST_CDMA_SET_ROAMING_PREFERENCE(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_CDMA_QUERY_ROAMING_PREFERENCE] = function REQUEST_CDMA_QUERY_ROAMING_PREFERENCE(length, options) {
+RilObject.prototype[REQUEST_CDMA_QUERY_ROAMING_PREFERENCE] = function REQUEST_CDMA_QUERY_ROAMING_PREFERENCE(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   } else {
-    let mode = Buf.readInt32List();
+    let mode = this.context.Buf.readInt32List();
     options.mode = CDMA_ROAMING_PREFERENCE_TO_GECKO[mode[0]];
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SET_TTY_MODE] = null;
-RIL[REQUEST_QUERY_TTY_MODE] = null;
-RIL[REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE] = function REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE(length, options) {
+RilObject.prototype[REQUEST_SET_TTY_MODE] = null;
+RilObject.prototype[REQUEST_QUERY_TTY_MODE] = null;
+RilObject.prototype[REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE] = function REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE] = function REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE(length, options) {
+RilObject.prototype[REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE] = function REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
-  let enabled = Buf.readInt32List();
+  let enabled = this.context.Buf.readInt32List();
   options.enabled = enabled[0] ? true : false;
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_CDMA_FLASH] = null;
-RIL[REQUEST_CDMA_BURST_DTMF] = null;
-RIL[REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY] = null;
-RIL[REQUEST_CDMA_SEND_SMS] = function REQUEST_CDMA_SEND_SMS(length, options) {
+RilObject.prototype[REQUEST_CDMA_FLASH] = null;
+RilObject.prototype[REQUEST_CDMA_BURST_DTMF] = null;
+RilObject.prototype[REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY] = null;
+RilObject.prototype[REQUEST_CDMA_SEND_SMS] = function REQUEST_CDMA_SEND_SMS(length, options) {
   this._processSmsSendResult(length, options);
 };
-RIL[REQUEST_CDMA_SMS_ACKNOWLEDGE] = null;
-RIL[REQUEST_GSM_GET_BROADCAST_SMS_CONFIG] = null;
-RIL[REQUEST_GSM_SET_BROADCAST_SMS_CONFIG] = function REQUEST_GSM_SET_BROADCAST_SMS_CONFIG(length, options) {
+RilObject.prototype[REQUEST_CDMA_SMS_ACKNOWLEDGE] = null;
+RilObject.prototype[REQUEST_GSM_GET_BROADCAST_SMS_CONFIG] = null;
+RilObject.prototype[REQUEST_GSM_SET_BROADCAST_SMS_CONFIG] = function REQUEST_GSM_SET_BROADCAST_SMS_CONFIG(length, options) {
   if (options.rilRequestError == ERROR_SUCCESS) {
     this.setSmsBroadcastActivation(true);
   }
 };
-RIL[REQUEST_GSM_SMS_BROADCAST_ACTIVATION] = null;
-RIL[REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG] = null;
-RIL[REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG] = null;
-RIL[REQUEST_CDMA_SMS_BROADCAST_ACTIVATION] = null;
-RIL[REQUEST_CDMA_SUBSCRIPTION] = function REQUEST_CDMA_SUBSCRIPTION(length, options) {
+RilObject.prototype[REQUEST_GSM_SMS_BROADCAST_ACTIVATION] = null;
+RilObject.prototype[REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG] = null;
+RilObject.prototype[REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG] = null;
+RilObject.prototype[REQUEST_CDMA_SMS_BROADCAST_ACTIVATION] = null;
+RilObject.prototype[REQUEST_CDMA_SUBSCRIPTION] = function REQUEST_CDMA_SUBSCRIPTION(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
-  let result = Buf.readStringList();
+  let result = this.context.Buf.readStringList();
 
   this.iccInfo.mdn = result[0];
   // The result[1] is Home SID. (Already be handled in readCDMAHome())
   // The result[2] is Home NID. (Already be handled in readCDMAHome())
   // The result[3] is MIN.
   // The result[4] is PRL version.
 
-  ICCUtilsHelper.handleICCInfoChange();
-};
-RIL[REQUEST_CDMA_WRITE_SMS_TO_RUIM] = null;
-RIL[REQUEST_CDMA_DELETE_SMS_ON_RUIM] = null;
-RIL[REQUEST_DEVICE_IDENTITY] = function REQUEST_DEVICE_IDENTITY(length, options) {
+  this.context.ICCUtilsHelper.handleICCInfoChange();
+};
+RilObject.prototype[REQUEST_CDMA_WRITE_SMS_TO_RUIM] = null;
+RilObject.prototype[REQUEST_CDMA_DELETE_SMS_ON_RUIM] = null;
+RilObject.prototype[REQUEST_DEVICE_IDENTITY] = function REQUEST_DEVICE_IDENTITY(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
-  let result = Buf.readStringList();
+  let result = this.context.Buf.readStringList();
 
   // The result[0] is for IMEI. (Already be handled in REQUEST_GET_IMEI)
   // The result[1] is for IMEISV. (Already be handled in REQUEST_GET_IMEISV)
   // They are both ignored.
   this.ESN = result[2];
   this.MEID = result[3];
 };
-RIL[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE] = function REQUEST_EXIT_EMERGENCY_CALLBACK_MODE(length, options) {
+RilObject.prototype[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE] = function REQUEST_EXIT_EMERGENCY_CALLBACK_MODE(length, options) {
   if (options.internal) {
     return;
   }
 
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_GET_SMSC_ADDRESS] = function REQUEST_GET_SMSC_ADDRESS(length, options) {
-  this.SMSC = options.rilRequestError ? null : Buf.readString();
+RilObject.prototype[REQUEST_GET_SMSC_ADDRESS] = function REQUEST_GET_SMSC_ADDRESS(length, options) {
+  this.SMSC = options.rilRequestError ? null : this.context.Buf.readString();
 
   if (!options || options.rilMessageType !== "getSmscAddress") {
     return;
   }
 
   options.smscAddress = this.SMSC;
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SET_SMSC_ADDRESS] = null;
-RIL[REQUEST_REPORT_SMS_MEMORY_STATUS] = null;
-RIL[REQUEST_REPORT_STK_SERVICE_IS_RUNNING] = null;
-RIL[REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU] = null;
-RIL[REQUEST_STK_SEND_ENVELOPE_WITH_STATUS] = function REQUEST_STK_SEND_ENVELOPE_WITH_STATUS(length, options) {
+RilObject.prototype[REQUEST_SET_SMSC_ADDRESS] = null;
+RilObject.prototype[REQUEST_REPORT_SMS_MEMORY_STATUS] = null;
+RilObject.prototype[REQUEST_REPORT_STK_SERVICE_IS_RUNNING] = null;
+RilObject.prototype[REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU] = null;
+RilObject.prototype[REQUEST_STK_SEND_ENVELOPE_WITH_STATUS] = function REQUEST_STK_SEND_ENVELOPE_WITH_STATUS(length, options) {
   if (options.rilRequestError) {
     this.acknowledgeGsmSms(false, PDU_FCS_UNSPECIFIED);
     return;
   }
 
+  let Buf = this.context.Buf;
   let sw1 = Buf.readInt32();
   let sw2 = Buf.readInt32();
   if ((sw1 == ICC_STATUS_SAT_BUSY) && (sw2 === 0x00)) {
     this.acknowledgeGsmSms(false, PDU_FCS_USAT_BUSY);
     return;
   }
 
   let success = ((sw1 == ICC_STATUS_NORMAL_ENDING) && (sw2 === 0x00))
@@ -6059,50 +6210,51 @@ RIL[REQUEST_STK_SEND_ENVELOPE_WITH_STATU
   if (!responsePduLen) {
     this.acknowledgeGsmSms(success, success ? PDU_FCS_OK
                                          : PDU_FCS_USIM_DATA_DOWNLOAD_ERROR);
     return;
   }
 
   this.acknowledgeIncomingGsmSmsWithPDU(success, responsePduLen, options);
 };
-RIL[REQUEST_VOICE_RADIO_TECH] = function REQUEST_VOICE_RADIO_TECH(length, options) {
+RilObject.prototype[REQUEST_VOICE_RADIO_TECH] = function REQUEST_VOICE_RADIO_TECH(length, options) {
   if (options.rilRequestError) {
     if (DEBUG) {
-      debug("Error when getting voice radio tech: " + options.rilRequestError);
+      this.context.debug("Error when getting voice radio tech: " +
+                         options.rilRequestError);
     }
     return;
   }
-  let radioTech = Buf.readInt32List();
+  let radioTech = this.context.Buf.readInt32List();
   this._processRadioTech(radioTech[0]);
 };
-RIL[REQUEST_GET_UNLOCK_RETRY_COUNT] = function REQUEST_GET_UNLOCK_RETRY_COUNT(length, options) {
+RilObject.prototype[REQUEST_GET_UNLOCK_RETRY_COUNT] = function REQUEST_GET_UNLOCK_RETRY_COUNT(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
-  options.retryCount = length ? Buf.readInt32List()[0] : -1;
+  options.retryCount = length ? this.context.Buf.readInt32List()[0] : -1;
   this.sendChromeMessage(options);
 };
-RIL[RIL_REQUEST_GPRS_ATTACH] = null;
-RIL[RIL_REQUEST_GPRS_DETACH] = null;
-RIL[UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED] = function UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED() {
-  let radioState = Buf.readInt32();
+RilObject.prototype[RIL_REQUEST_GPRS_ATTACH] = null;
+RilObject.prototype[RIL_REQUEST_GPRS_DETACH] = null;
+RilObject.prototype[UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED] = function UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED() {
+  let radioState = this.context.Buf.readInt32();
   let newState;
   if (radioState == RADIO_STATE_UNAVAILABLE) {
     newState = GECKO_RADIOSTATE_UNAVAILABLE;
   } else if (radioState == RADIO_STATE_OFF) {
     newState = GECKO_RADIOSTATE_OFF;
   } else {
     newState = GECKO_RADIOSTATE_READY;
   }
 
   if (DEBUG) {
-    debug("Radio state changed from '" + this.radioState +
-          "' to '" + newState + "'");
+    this.context.debug("Radio state changed from '" + this.radioState +
+                       "' to '" + newState + "'");
   }
   if (this.radioState == newState) {
     return;
   }
 
   switch (radioState) {
   case RADIO_STATE_SIM_READY:
   case RADIO_STATE_SIM_NOT_READY:
@@ -6159,79 +6311,83 @@ RIL[UNSOLICITED_RESPONSE_RADIO_STATE_CHA
   // If _waitingRadioTech is set, we don't need to get icc status now.
   if (radioState == RADIO_STATE_UNAVAILABLE ||
       radioState == RADIO_STATE_OFF ||
       this._waitingRadioTech) {
     return;
   }
   this.getICCStatus();
 };
-RIL[UNSOLICITED_RESPONSE_CALL_STATE_CHANGED] = function UNSOLICITED_RESPONSE_CALL_STATE_CHANGED() {
+RilObject.prototype[UNSOLICITED_RESPONSE_CALL_STATE_CHANGED] = function UNSOLICITED_RESPONSE_CALL_STATE_CHANGED() {
   this.getCurrentCalls();
 };
-RIL[UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED] = function UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED() {
-  if (DEBUG) debug("Network state changed, re-requesting phone state and ICC status");
+RilObject.prototype[UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED] = function UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED() {
+  if (DEBUG) {
+    this.context.debug("Network state changed, re-requesting phone state and " +
+                       "ICC status");
+  }
   this.getICCStatus();
   this.requestNetworkInfo();
 };
-RIL[UNSOLICITED_RESPONSE_NEW_SMS] = function UNSOLICITED_RESPONSE_NEW_SMS(length) {
-  let [message, result] = GsmPDUHelper.processReceivedSms(length);
+RilObject.prototype[UNSOLICITED_RESPONSE_NEW_SMS] = function UNSOLICITED_RESPONSE_NEW_SMS(length) {
+  let [message, result] = this.context.GsmPDUHelper.processReceivedSms(length);
 
   if (message) {
     result = this._processSmsMultipart(message);
   }
 
   if (result == PDU_FCS_RESERVED || result == MOZ_FCS_WAIT_FOR_EXPLICIT_ACK) {
     return;
   }
 
   // Not reserved FCS values, send ACK now.
   this.acknowledgeGsmSms(result == PDU_FCS_OK, result);
 };
-RIL[UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT] = function UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT(length) {
+RilObject.prototype[UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT] = function UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT(length) {
   let result = this._processSmsStatusReport(length);
   this.acknowledgeGsmSms(result == PDU_FCS_OK, result);
 };
-RIL[UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM] = function UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM(length) {
-  let recordNumber = Buf.readInt32List()[0];
-
-  SimRecordHelper.readSMS(
+RilObject.prototype[UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM] = function UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM(length) {
+  let recordNumber = this.context.Buf.readInt32List()[0];
+
+  this.context.SimRecordHelper.readSMS(
     recordNumber,
     function onsuccess(message) {
       if (message && message.simStatus === 3) { //New Unread SMS
         this._processSmsMultipart(message);
       }
     }.bind(this),
     function onerror(errorMsg) {
       if (DEBUG) {
-        debug("Failed to Read NEW SMS on SIM #" + recordNumber + ", errorMsg: " + errorMsg);
+        this.context.debug("Failed to Read NEW SMS on SIM #" + recordNumber +
+                           ", errorMsg: " + errorMsg);
       }
     });
 };
-RIL[UNSOLICITED_ON_USSD] = function UNSOLICITED_ON_USSD() {
-  let [typeCode, message] = Buf.readStringList();
+RilObject.prototype[UNSOLICITED_ON_USSD] = function UNSOLICITED_ON_USSD() {
+  let [typeCode, message] = this.context.Buf.readStringList();
   if (DEBUG) {
-    debug("On USSD. Type Code: " + typeCode + " Message: " + message);
+    this.context.debug("On USSD. Type Code: " + typeCode + " Message: " + message);
   }
 
   this._ussdSession = (typeCode != "0" && typeCode != "2");
 
   this.sendChromeMessage({rilMessageType: "USSDReceived",
                           message: message,
                           sessionEnded: !this._ussdSession});
 };
-RIL[UNSOLICITED_NITZ_TIME_RECEIVED] = function UNSOLICITED_NITZ_TIME_RECEIVED() {
-  let dateString = Buf.readString();
+RilObject.prototype[UNSOLICITED_NITZ_TIME_RECEIVED] = function UNSOLICITED_NITZ_TIME_RECEIVED() {
+  let dateString = this.context.Buf.readString();
 
   // The data contained in the NITZ message is
   // in the form "yy/mm/dd,hh:mm:ss(+/-)tz,dt"
   // for example: 12/02/16,03:36:08-20,00,310410
   // See also bug 714352 - Listen for NITZ updates from rild.
 
-  if (DEBUG) debug("DateTimeZone string " + dateString);
+  if (DEBUG) this.context.debug("DateTimeZone string " + dateString);
 
   let now = Date.now();
 
   let year = parseInt(dateString.substr(0, 2), 10);
   let month = parseInt(dateString.substr(3, 2), 10);
   let day = parseInt(dateString.substr(6, 2), 10);
   let hours = parseInt(dateString.substr(9, 2), 10);
   let minutes = parseInt(dateString.substr(12, 2), 10);
@@ -6240,80 +6396,82 @@ RIL[UNSOLICITED_NITZ_TIME_RECEIVED] = fu
   let tz = parseInt(dateString.substr(17, 3), 10);
   // Note that |dst| is in 1-hour units and is already applied in |tz|.
   let dst = parseInt(dateString.substr(21, 2), 10);
 
   let timeInMS = Date.UTC(year + PDU_TIMESTAMP_YEAR_OFFSET, month - 1, day,
                           hours, minutes, seconds);
 
   if (isNaN(timeInMS)) {
-    if (DEBUG) debug("NITZ failed to convert date");
+    if (DEBUG) this.context.debug("NITZ failed to convert date");
     return;
   }
 
   this.sendChromeMessage({rilMessageType: "nitzTime",
                           networkTimeInMS: timeInMS,
                           networkTimeZoneInMinutes: -(tz * 15),
                           networkDSTInMinutes: -(dst * 60),
                           receiveTimeInMS: now});
 };
 
-RIL[UNSOLICITED_SIGNAL_STRENGTH] = function UNSOLICITED_SIGNAL_STRENGTH(length) {
+RilObject.prototype[UNSOLICITED_SIGNAL_STRENGTH] = function UNSOLICITED_SIGNAL_STRENGTH(length) {
   this[REQUEST_SIGNAL_STRENGTH](length, {rilRequestError: ERROR_SUCCESS});
 };
-RIL[UNSOLICITED_DATA_CALL_LIST_CHANGED] = function UNSOLICITED_DATA_CALL_LIST_CHANGED(length) {
-  if (RILQUIRKS_V5_LEGACY) {
+RilObject.prototype[UNSOLICITED_DATA_CALL_LIST_CHANGED] = function UNSOLICITED_DATA_CALL_LIST_CHANGED(length) {
+  if (this.v5Legacy) {
     this.getDataCallList();
     return;
   }
   this[REQUEST_DATA_CALL_LIST](length, {rilRequestError: ERROR_SUCCESS});
 };
-RIL[UNSOLICITED_SUPP_SVC_NOTIFICATION] = function UNSOLICITED_SUPP_SVC_NOTIFICATION(length) {
+RilObject.prototype[UNSOLICITED_SUPP_SVC_NOTIFICATION] = function UNSOLICITED_SUPP_SVC_NOTIFICATION(length) {
+  let Buf = this.context.Buf;
   let info = {};
   info.notificationType = Buf.readInt32();
   info.code = Buf.readInt32();
   info.index = Buf.readInt32();
   info.type = Buf.readInt32();
   info.number = Buf.readString();
 
   this._processSuppSvcNotification(info);
 };
 
-RIL[UNSOLICITED_STK_SESSION_END] = function UNSOLICITED_STK_SESSION_END() {
+RilObject.prototype[UNSOLICITED_STK_SESSION_END] = function UNSOLICITED_STK_SESSION_END() {
   this.sendChromeMessage({rilMessageType: "stksessionend"});
 };
-RIL[UNSOLICITED_STK_PROACTIVE_COMMAND] = function UNSOLICITED_STK_PROACTIVE_COMMAND() {
+RilObject.prototype[UNSOLICITED_STK_PROACTIVE_COMMAND] = function UNSOLICITED_STK_PROACTIVE_COMMAND() {
   this.processStkProactiveCommand();
 };
-RIL[UNSOLICITED_STK_EVENT_NOTIFY] = function UNSOLICITED_STK_EVENT_NOTIFY() {
+RilObject.prototype[UNSOLICITED_STK_EVENT_NOTIFY] = function UNSOLICITED_STK_EVENT_NOTIFY() {
   this.processStkProactiveCommand();
 };
-RIL[UNSOLICITED_STK_CALL_SETUP] = null;
-RIL[UNSOLICITED_SIM_SMS_STORAGE_FULL] = null;
-RIL[UNSOLICITED_SIM_REFRESH] = null;
-RIL[UNSOLICITED_CALL_RING] = function UNSOLICITED_CALL_RING() {
+RilObject.prototype[UNSOLICITED_STK_CALL_SETUP] = null;
+RilObject.prototype[UNSOLICITED_SIM_SMS_STORAGE_FULL] = null;
+RilObject.prototype[UNSOLICITED_SIM_REFRESH] = null;
+RilObject.prototype[UNSOLICITED_CALL_RING] = function UNSOLICITED_CALL_RING() {
+  let Buf = this.context.Buf;
   let info = {rilMessageType: "callRing"};
   let isCDMA = false; //XXX TODO hard-code this for now
   if (isCDMA) {
     info.isPresent = Buf.readInt32();
     info.signalType = Buf.readInt32();
     info.alertPitch = Buf.readInt32();
     info.signal = Buf.readInt32();
   }
   // At this point we don't know much other than the fact there's an incoming
   // call, but that's enough to bring up the Phone app already. We'll know
   // details once we get a call state changed notification and can then
   // dispatch DOM events etc.
   this.sendChromeMessage(info);
 };
-RIL[UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED] = function UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED() {
+RilObject.prototype[UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED] = function UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED() {
   this.getICCStatus();
 };
-RIL[UNSOLICITED_RESPONSE_CDMA_NEW_SMS] = function UNSOLICITED_RESPONSE_CDMA_NEW_SMS(length) {
-  let [message, result] = CdmaPDUHelper.processReceivedSms(length);
+RilObject.prototype[UNSOLICITED_RESPONSE_CDMA_NEW_SMS] = function UNSOLICITED_RESPONSE_CDMA_NEW_SMS(length) {
+  let [message, result] = this.context.CdmaPDUHelper.processReceivedSms(length);
 
   if (message) {
     if (message.teleservice === PDU_CDMA_MSG_TELESERIVCIE_ID_WAP) {
       result = this._processCdmaSmsWapPush(message);
     } else if (message.subMsgType === PDU_CDMA_MSG_TYPE_DELIVER_ACK) {
       result = this._processCdmaSmsStatusReport(message);
     } else {
       result = this._processSmsMultipart(message);
@@ -6322,81 +6480,84 @@ RIL[UNSOLICITED_RESPONSE_CDMA_NEW_SMS] =
 
   if (result == PDU_FCS_RESERVED || result == MOZ_FCS_WAIT_FOR_EXPLICIT_ACK) {
     return;
   }
 
   // Not reserved FCS values, send ACK now.
   this.acknowledgeCdmaSms(result == PDU_FCS_OK, result);
 };
-RIL[UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS] = function UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS(length) {
+RilObject.prototype[UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS] = function UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS(length) {
   let message;
   try {
-    message = GsmPDUHelper.readCbMessage(Buf.readInt32());
+    message =
+      this.context.GsmPDUHelper.readCbMessage(this.context.Buf.readInt32());
   } catch (e) {
     if (DEBUG) {
-      debug("Failed to parse Cell Broadcast message: " + JSON.stringify(e));
+      this.context.debug("Failed to parse Cell Broadcast message: " +
+                         JSON.stringify(e));
     }
     return;
   }
 
   message = this._processReceivedSmsCbPage(message);
   if (!message) {
     return;
   }
 
   message.rilMessageType = "cellbroadcast-received";
   this.sendChromeMessage(message);
 };
-RIL[UNSOLICITED_CDMA_RUIM_SMS_STORAGE_FULL] = null;
-RIL[UNSOLICITED_RESTRICTED_STATE_CHANGED] = null;
-RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE] = function UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE() {
+RilObject.prototype[UNSOLICITED_CDMA_RUIM_SMS_STORAGE_FULL] = null;
+RilObject.prototype[UNSOLICITED_RESTRICTED_STATE_CHANGED] = null;
+RilObject.prototype[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE] = function UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE() {
   this._handleChangedEmergencyCbMode(true);
 };
-RIL[UNSOLICITED_CDMA_CALL_WAITING] = function UNSOLICITED_CDMA_CALL_WAITING(length) {
+RilObject.prototype[UNSOLICITED_CDMA_CALL_WAITING] = function UNSOLICITED_CDMA_CALL_WAITING(length) {
+  let Buf = this.context.Buf;
   let call = {};
   call.number              = Buf.readString();
   call.numberPresentation  = Buf.readInt32();
   call.name                = Buf.readString();
   call.namePresentation    = Buf.readInt32();
   call.isPresent           = Buf.readInt32();
   call.signalType          = Buf.readInt32();
   call.alertPitch          = Buf.readInt32();
   call.signal              = Buf.readInt32();
   this.sendChromeMessage({rilMessageType: "cdmaCallWaiting",
                           number: call.number});
 };
-RIL[UNSOLICITED_CDMA_OTA_PROVISION_STATUS] = function UNSOLICITED_CDMA_OTA_PROVISION_STATUS() {
-  let status = Buf.readInt32List()[0];
+RilObject.prototype[UNSOLICITED_CDMA_OTA_PROVISION_STATUS] = function UNSOLICITED_CDMA_OTA_PROVISION_STATUS() {
+  let status = this.context.Buf.readInt32List()[0];
   this.sendChromeMessage({rilMessageType: "otastatuschange",
                           status: status});
 };
-RIL[UNSOLICITED_CDMA_INFO_REC] = function UNSOLICITED_CDMA_INFO_REC(length) {
-  let record = CdmaPDUHelper.decodeInformationRecord();
+RilObject.prototype[UNSOLICITED_CDMA_INFO_REC] = function UNSOLICITED_CDMA_INFO_REC(length) {
+  let record = this.context.CdmaPDUHelper.decodeInformationRecord();
   record.rilMessageType = "cdma-info-rec-received";
   this.sendChromeMessage(record);
 };
-RIL[UNSOLICITED_OEM_HOOK_RAW] = null;
-RIL[UNSOLICITED_RINGBACK_TONE] = null;
-RIL[UNSOLICITED_RESEND_INCALL_MUTE] = null;
-RIL[UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE] = function UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE() {
+RilObject.prototype[UNSOLICITED_OEM_HOOK_RAW] = null;
+RilObject.prototype[UNSOLICITED_RINGBACK_TONE] = null;
+RilObject.prototype[UNSOLICITED_RESEND_INCALL_MUTE] = null;
+RilObject.prototype[UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE] = function UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE() {
   this._handleChangedEmergencyCbMode(false);
 };
-RIL[UNSOLICITED_RIL_CONNECTED] = function UNSOLICITED_RIL_CONNECTED(length) {
+RilObject.prototype[UNSOLICITED_RIL_CONNECTED] = function UNSOLICITED_RIL_CONNECTED(length) {
   // Prevent response id collision between UNSOLICITED_RIL_CONNECTED and
   // UNSOLICITED_VOICE_RADIO_TECH_CHANGED for Akami on gingerbread branch.
   if (!length) {
     return;
   }
 
-  let version = Buf.readInt32List()[0];
-  RILQUIRKS_V5_LEGACY = (version < 5);
+  let version = this.context.Buf.readInt32List()[0];
+  this.v5Legacy = (version < 5);
   if (DEBUG) {
-    debug("Detected RIL version " + version);
-    debug("RILQUIRKS_V5_LEGACY is " + RILQUIRKS_V5_LEGACY);
+    this.context.debug("Detected RIL version " + version);
+    this.context.debug("this.v5Legacy is " + this.v5Legacy);
   }
 
   this.initRILState();
   // Always ensure that we are not in emergency callback mode when init.
   this.exitEmergencyCbMode();
   // Reset radio in the case that b2g restart (or crash).
   this.setRadioEnabled({enabled: false});
 };
@@ -6404,25 +6565,29 @@ RIL[UNSOLICITED_RIL_CONNECTED] = functio
 /**
  * This object exposes the functionality to parse and serialize PDU strings
  *
  * A PDU is a string containing a series of hexadecimally encoded octets
  * or nibble-swapped binary-coded decimals (BCDs). It contains not only the
  * message text but information about the sender, the SMS service center,
  * timestamp, etc.
  */
-let GsmPDUHelper = {
+function GsmPDUHelperObject(aContext) {
+  this.context = aContext;
+}
+GsmPDUHelperObject.prototype = {
+  context: null,
 
   /**
    * Read one character (2 bytes) from a RIL string and decode as hex.
    *
    * @return the nibble as a number.
    */
   readHexNibble: function() {
-    let nibble = Buf.readUint16();
+    let nibble = this.context.Buf.readUint16();
     if (nibble >= 48 && nibble <= 57) {
       nibble -= 48; // ASCII '0'..'9'
     } else if (nibble >= 65 && nibble <= 70) {
       nibble -= 55; // ASCII 'A'..'F'
     } else if (nibble >= 97 && nibble <= 102) {
       nibble -= 87; // ASCII 'a'..'f'
     } else {
       throw "Found invalid nibble during PDU parsing: " +
@@ -6439,17 +6604,17 @@ let GsmPDUHelper = {
    */
   writeHexNibble: function(nibble) {
     nibble &= 0x0f;
     if (nibble < 10) {
       nibble += 48; // ASCII '0'
     } else {
       nibble += 55; // ASCII 'A'
     }
-    Buf.writeUint16(nibble);
+    this.context.Buf.writeUint16(nibble);
   },
 
   /**
    * Read a hex-encoded octet (two nibbles).
    *
    * @return the octet as a number.
    */
   readHexOctet: function() {
@@ -6580,16 +6745,17 @@ let GsmPDUHelper = {
    * @param data
    *        Data to write (as a string or a number)
    */
   writeSwappedNibbleBCD: function(data) {
     data = data.toString();
     if (data.length % 2) {
       data += "F";
     }
+    let Buf = this.context.Buf;
     for (let i = 0; i < data.length; i += 2) {
       Buf.writeUint16(data.charCodeAt(i + 1));
       Buf.writeUint16(data.charCodeAt(i));
     }
   },
 
   /**
    * Write numerical data as swapped nibble BCD.
@@ -6598,16 +6764,17 @@ let GsmPDUHelper = {
    * @param data
    *        Data to write (as a string or a number)
    */
   writeSwappedNibbleBCDNum: function(data) {
     data = data.toString();
     if (data.length % 2) {
       data = "0" + data;
     }
+    let Buf = this.context.Buf;
     for (let i = 0; i < data.length; i += 2) {
       Buf.writeUint16(data.charCodeAt(i + 1));
       Buf.writeUint16(data.charCodeAt(i));
     }
   },
 
   /**
    * Read user data, convert to septets, look up relevant characters in a
@@ -6769,17 +6936,17 @@ let GsmPDUHelper = {
   readUCS2String: function(numOctets) {
     let str = "";
     let length = numOctets / 2;
     for (let i = 0; i < length; ++i) {
       let code = (this.readHexOctet() << 8) | this.readHexOctet();
       str += String.fromCharCode(code);
     }
 
-    if (DEBUG) debug("Read UCS2 string: " + str);
+    if (DEBUG) this.context.debug("Read UCS2 string: " + str);
 
     return str;
   },
 
   /**
    * Write user data as a UCS2 string.
    *
    * @param message
@@ -6815,23 +6982,23 @@ let GsmPDUHelper = {
      */
     let header = {
       length: 0,
       langIndex: PDU_NL_IDENTIFIER_DEFAULT,
       langShiftIndex: PDU_NL_IDENTIFIER_DEFAULT
     };
 
     header.length = this.readHexOctet();
-    if (DEBUG) debug("Read UDH length: " + header.length);
+    if (DEBUG) this.context.debug("Read UDH length: " + header.length);
 
     let dataAvailable = header.length;
     while (dataAvailable >= 2) {
       let id = this.readHexOctet();
       let length = this.readHexOctet();
-      if (DEBUG) debug("Read UDH id: " + id + ", length: " + length);
+      if (DEBUG) this.context.debug("Read UDH id: " + id + ", length: " + length);
 
       dataAvailable -= 2;
 
       switch (id) {
         case PDU_IEI_CONCATENATED_SHORT_MESSAGES_8BIT: {
           let ref = this.readHexOctet();
           let max = this.readHexOctet();
           let seq = this.readHexOctet();
@@ -6925,37 +7092,41 @@ let GsmPDUHelper = {
             // storeType == PDU_MWI_STORE_TYPE_DISCARD
             // only override mwi.discard here if it hasn't already been set
             mwi.discard = true;
           }
 
           mwi.msgCount = msgCount & 0xFF;
           mwi.active = mwi.msgCount > 0;
 
-          if (DEBUG) debug("MWI in TP_UDH received: " + JSON.stringify(mwi));
+          if (DEBUG) {
+            this.context.debug("MWI in TP_UDH received: " + JSON.stringify(mwi));
+          }
 
           break;
         default:
           if (DEBUG) {
-            debug("readUserDataHeader: unsupported IEI(" + id
-                  + "), " + length + " bytes.");
+            this.context.debug("readUserDataHeader: unsupported IEI(" + id +
+                               "), " + length + " bytes.");
           }
 
           // Read out unsupported data
           if (length) {
             let octets;
             if (DEBUG) octets = new Uint8Array(length);
 
             for (let i = 0; i < length; i++) {
               let octet = this.readHexOctet();
               if (DEBUG) octets[i] = octet;
             }
             dataAvailable -= length;
 
-            if (DEBUG) debug("readUserDataHeader: " + Array.slice(octets));
+            if (DEBUG) {
+              this.context.debug("readUserDataHeader: " + Array.slice(octets));
+            }
           }
           break;
       }
     }
 
     if (dataAvailable !== 0) {
       throw new Error("Illegal user data header found!");
     }
@@ -7009,36 +7180,38 @@ let GsmPDUHelper = {
    *        Length of useful semi-octets within the Address-Value field. For
    *        example, the lenth of "12345" should be 5, and 4 for "1234".
    *
    * @see 3GPP TS 23.040 9.1.2.5
    */
   readAddress: function(len) {
     // Address Length
     if (!len || (len < 0)) {
-      if (DEBUG) debug("PDU error: invalid sender address length: " + len);
+      if (DEBUG) {
+        this.context.debug("PDU error: invalid sender address length: " + len);
+      }
       return null;
     }
     if (len % 2 == 1) {
       len += 1;
     }
-    if (DEBUG) debug("PDU: Going to read address: " + len);
+    if (DEBUG) this.context.debug("PDU: Going to read address: " + len);
 
     // Type-of-Address
     let toa = this.readHexOctet();
     let addr = "";
 
     if ((toa & 0xF0) == PDU_TOA_ALPHANUMERIC) {
       addr = this.readSeptetsToString(Math.floor(len * 4 / 7), 0,
           PDU_NL_IDENTIFIER_DEFAULT , PDU_NL_IDENTIFIER_DEFAULT );
       return addr;
     }
     addr = this.readSwappedNibbleBcdString(len / 2);
     if (addr.length <= 0) {
-      if (DEBUG) debug("PDU error: no number provided");
+      if (DEBUG) this.context.debug("PDU error: no number provided");
       return null;
     }
     if ((toa & 0xF0) == (PDU_TOA_INTERNATIONAL)) {
       addr = '+' + addr;
     }
 
     return addr;
   },
@@ -7077,17 +7250,17 @@ let GsmPDUHelper = {
    *
    * @param msg
    *        message object for output.
    *
    * @see 3GPP TS 23.040 9.2.3.10, 3GPP TS 23.038 4.
    */
   readDataCodingScheme: function(msg) {
     let dcs = this.readHexOctet();
-    if (DEBUG) debug("PDU: read SMS dcs: " + dcs);
+    if (DEBUG) this.context.debug("PDU: read SMS dcs: " + dcs);
 
     // No message class by default.
     let messageClass = PDU_DCS_MSG_CLASS_NORMAL;
     // 7 bit is the default fallback encoding.
     let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
     switch (dcs & PDU_DCS_CODING_GROUP_BITS) {
       case 0x40: // bits 7..4 = 01xx
       case 0x50:
@@ -7129,27 +7302,28 @@ let GsmPDUHelper = {
               mwi = msg.mwi = {};
             }
 
             mwi.active = active;
             mwi.discard = (dcs & PDU_DCS_CODING_GROUP_BITS) == 0xC0;
             mwi.msgCount = active ? GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN : 0;
 
             if (DEBUG) {
-              debug("MWI in DCS received for voicemail: " + JSON.stringify(mwi));
+              this.context.debug("MWI in DCS received for voicemail: " +
+                                 JSON.stringify(mwi));
             }
             break;
           case PDU_DCS_MWI_TYPE_FAX:
-            if (DEBUG) debug("MWI in DCS received for fax");
+            if (DEBUG) this.context.debug("MWI in DCS received for fax");
             break;
           case PDU_DCS_MWI_TYPE_EMAIL:
-            if (DEBUG) debug("MWI in DCS received for email");
+            if (DEBUG) this.context.debug("MWI in DCS received for email");
             break;
           default:
-            if (DEBUG) debug("MWI in DCS received for \"other\"");
+            if (DEBUG) this.context.debug("MWI in DCS received for \"other\"");
             break;
         }
         break;
 
       case 0xF0: // bits 7..4 = 1111
         if (dcs & 0x04) {
           encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
         }
@@ -7160,17 +7334,17 @@ let GsmPDUHelper = {
         // Falling back to default encoding.
         break;
     }
 
     msg.dcs = dcs;
     msg.encoding = encoding;
     msg.messageClass = GECKO_SMS_MESSAGE_CLASSES[messageClass];
 
-    if (DEBUG) debug("PDU: message encoding is " + encoding + " bit.");
+    if (DEBUG) this.context.debug("PDU: message encoding is " + encoding + " bit.");
   },
 
   /**
    * Read GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
    *
    * @see 3GPP TS 23.040 9.2.3.11
    */
   readTimestamp: function() {
@@ -7238,17 +7412,17 @@ let GsmPDUHelper = {
    *
    * @param msg
    *        message object for output.
    * @param length
    *        length of user data to read in octets.
    */
   readUserData: function(msg, length) {
     if (DEBUG) {
-      debug("Reading " + length + " bytes of user data.");
+      this.context.debug("Reading " + length + " bytes of user data.");
     }
 
     let paddingBits = 0;
     if (msg.udhi) {
       this.readUserDataHeader(msg);
 
       if (msg.encoding == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
         let headerBits = (msg.header.length + 1) * 8;
@@ -7256,26 +7430,30 @@ let GsmPDUHelper = {
 
         length -= headerSeptets;
         paddingBits = headerSeptets * 7 - headerBits;
       } else {
         length -= (msg.header.length + 1);
       }
     }
 
-    if (DEBUG) debug("After header, " + length + " septets left of user data");
+    if (DEBUG) {
+      this.context.debug("After header, " + length + " septets left of user data");
+    }
 
     msg.body = null;
     msg.data = null;
     switch (msg.encoding) {
       case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
         // 7 bit encoding allows 140 octets, which means 160 characters
         // ((140x8) / 7 = 160 chars)
         if (length > PDU_MAX_USER_DATA_7BIT) {
-          if (DEBUG) debug("PDU error: user data is too long: " + length);
+          if (DEBUG) {
+            this.context.debug("PDU error: user data is too long: " + length);
+          }
           break;
         }
 
         let langIndex = msg.udhi ? msg.header.langIndex : PDU_NL_IDENTIFIER_DEFAULT;
         let langShiftIndex = msg.udhi ? msg.header.langShiftIndex : PDU_NL_IDENTIFIER_DEFAULT;
         msg.body = this.readSeptetsToString(length, paddingBits, langIndex,
                                             langShiftIndex);
         break;
@@ -7293,17 +7471,17 @@ let GsmPDUHelper = {
    *
    * @param msg
    *        message object for output.
    */
   readExtraParams: function(msg) {
     // Because each PDU octet is converted to two UCS2 char2, we should always
     // get even messageStringLength in this#_processReceivedSms(). So, we'll
     // always need two delimitors at the end.
-    if (Buf.getReadAvailable() <= 4) {
+    if (this.context.Buf.getReadAvailable() <= 4) {
       return;
     }
 
     // TP-Parameter-Indicator
     let pi;
     do {
       // `The most significant bit in octet 1 and any other TP-PI octets which
       // may be added later is reserved as an extension bit which when set to a
@@ -7402,26 +7580,28 @@ let GsmPDUHelper = {
    *
    * @param length
    *        Length of SMS string in the incoming parcel.
    *
    * @return Message parsed or null for invalid message.
    */
   processReceivedSms: function(length) {
     if (!length) {
-      if (DEBUG) debug("Received empty SMS!");
+      if (DEBUG) this.context.debug("Received empty SMS!");
       return [null, PDU_FCS_UNSPECIFIED];
     }
 
+    let Buf = this.context.Buf;
+
     // An SMS is a string, but we won't read it as such, so let's read the
     // string length and then defer to PDU parsing helper.
     let messageStringLength = Buf.readInt32();
-    if (DEBUG) debug("Got new SMS, length " + messageStringLength);
+    if (DEBUG) this.context.debug("Got new SMS, length " + messageStringLength);
     let message = this.readMessage();
-    if (DEBUG) debug("Got new SMS: " + JSON.stringify(message));
+    if (DEBUG) this.context.debug("Got new SMS: " + JSON.stringify(message));
 
     // Read string delimiters. See Buf.readString().
     Buf.readStringDelimiter(length);
 
     // Determine result
     if (!message) {
       return [null, PDU_FCS_UNSPECIFIED];
     }
@@ -7429,19 +7609,21 @@ let GsmPDUHelper = {
     if (message.epid == PDU_PID_SHORT_MESSAGE_TYPE_0) {
       // `A short message type 0 indicates that the ME must acknowledge receipt
       // of the short message but shall discard its contents.` ~ 3GPP TS 23.040
       // 9.2.3.9
       return [null, PDU_FCS_OK];
     }
 
     if (message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) {
+      let RIL = this.context.RIL;
       switch (message.epid) {
         case PDU_PID_ANSI_136_R_DATA:
         case PDU_PID_USIM_DATA_DOWNLOAD:
+          let ICCUtilsHelper = this.context.ICCUtilsHelper;
           if (ICCUtilsHelper.isICCServiceAvailable("DATA_DOWNLOAD_SMS_PP")) {
             // `If the service "data download via SMS Point-to-Point" is
             // allocated and activated in the (U)SIM Service Table, ... then the
             // ME shall pass the message transparently to the UICC using the
             // ENVELOPE (SMS-PP DOWNLOAD).` ~ 3GPP TS 31.111 7.1.1.1
             RIL.dataDownloadViaSMSPP(message);
 
             // `the ME shall not display the message, or alert the user of a
@@ -7554,18 +7736,19 @@ let GsmPDUHelper = {
    *        Table index used for normal 7-bit encoded character lookup.
    * @param langShiftIndex
    *        Table index used for escaped 7-bit encoded character lookup.
    * @param requestStatusReport
    *        Request status report.
    */
   writeMessage: function(options) {
     if (DEBUG) {
-      debug("writeMessage: " + JSON.stringify(options));
-    }
+      this.context.debug("writeMessage: " + JSON.stringify(options));
+    }
+    let Buf = this.context.Buf;
     let address = options.number;
     let body = options.body;
     let dcs = options.dcs;
     let userDataHeaderLength = options.userDataHeaderLength;
     let encodedBodyLength = options.encodedBodyLength;
     let langIndex = options.langIndex;
     let langShiftIndex = options.langShiftIndex;
 
@@ -7710,31 +7893,33 @@ let GsmPDUHelper = {
    * Read GSM CBS message serial number.
    *
    * @param msg
    *        message object for output.
    *
    * @see 3GPP TS 23.041 section 9.4.1.2.1
    */
   readCbSerialNumber: function(msg) {
+    let Buf = this.context.Buf;
     msg.serial = Buf.readUint8() << 8 | Buf.readUint8();
     msg.geographicalScope = (msg.serial >>> 14) & 0x03;
     msg.messageCode = (msg.serial >>> 4) & 0x03FF;
     msg.updateNumber = msg.serial & 0x0F;
   },
 
   /**
    * Read GSM CBS message message identifier.
    *
    * @param msg
    *        message object for output.
    *
    * @see 3GPP TS 23.041 section 9.4.1.2.2
    */
   readCbMessageIdentifier: function(msg) {
+    let Buf = this.context.Buf;
     msg.messageId = Buf.readUint8() << 8 | Buf.readUint8();
 
     if ((msg.format != CB_FORMAT_ETWS)
         && (msg.messageId >= CB_GSM_MESSAGEID_ETWS_BEGIN)
         && (msg.messageId <= CB_GSM_MESSAGEID_ETWS_END)) {
       // `In the case of transmitting CBS message for ETWS, a part of
       // Message Code can be used to command mobile terminals to activate
       // emergency user alert and message popup in order to alert the users.`
@@ -7754,18 +7939,18 @@ let GsmPDUHelper = {
    * Read CBS Data Coding Scheme.
    *
    * @param msg
    *        message object for output.
    *
    * @see 3GPP TS 23.038 section 5.
    */
   readCbDataCodingScheme: function(msg) {
-    let dcs = Buf.readUint8();
-    if (DEBUG) debug("PDU: read CBS dcs: " + dcs);
+    let dcs = this.context.Buf.readUint8();
+    if (DEBUG) this.context.debug("PDU: read CBS dcs: " + dcs);
 
     let language = null, hasLanguageIndicator = false;
     // `Any reserved codings shall be assumed to be the GSM 7bit default
     // alphabet.`
     let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
     let messageClass = PDU_DCS_MSG_CLASS_NORMAL;
 
     switch (dcs & PDU_DCS_CODING_GROUP_BITS) {
@@ -7833,17 +8018,17 @@ let GsmPDUHelper = {
    * Read GSM CBS message page parameter.
    *
    * @param msg
    *        message object for output.
    *
    * @see 3GPP TS 23.041 section 9.4.1.2.4
    */
   readCbPageParameter: function(msg) {
-    let octet = Buf.readUint8();
+    let octet = this.context.Buf.readUint8();
     msg.pageIndex = (octet >>> 4) & 0x0F;
     msg.numPages = octet & 0x0F;
     if (!msg.pageIndex || !msg.numPages) {
       // `If a mobile receives the code 0000 in either the first field or the
       // second field then it shall treat the CBS message exactly the same as a
       // CBS message with page parameter 0001 0001 (i.e. a single page message).`
       msg.pageIndex = msg.numPages = 1;
     }
@@ -7853,16 +8038,17 @@ let GsmPDUHelper = {
    * Read ETWS Primary Notification message warning type.
    *
    * @param msg
    *        message object for output.
    *
    * @see 3GPP TS 23.041 section 9.3.24
    */
   readCbWarningType: function(msg) {
+    let Buf = this.context.Buf;
     let word = Buf.readUint8() << 8 | Buf.readUint8();
     msg.etws = {
       warningType:        (word >>> 9) & 0x7F,
       popup:              word & 0x80 ? true : false,
       emergencyUserAlert: word & 0x100 ? true : false
     };
   },
 
@@ -7872,17 +8058,19 @@ let GsmPDUHelper = {
    * @param msg
    *        message object for output.
    * @param length
    *        length of cell broadcast data to read in octets.
    *
    * @see 3GPP TS 23.041 section 9.3.19
    */
   readGsmCbData: function(msg, length) {
+    let Buf = this.context.Buf;
     let bufAdapter = {
+      context: this.context,
       readHexOctet: function() {
         return Buf.readUint8();
       }
     };
 
     msg.body = null;
     msg.data = null;
     switch (msg.encoding) {
@@ -8022,30 +8210,30 @@ let GsmPDUHelper = {
     // bit 5-7: Text encoding.
     //          000 - GSM default alphabet.
     //          001 - UCS2 (16 bit).
     //          else - reserved.
     // bit 4: MS should add the letters for Country's Initials and a space
     //        to the text string if this bit is true.
     // bit 1-3: number of spare bits in last octet.
 
-    let codingInfo = GsmPDUHelper.readHexOctet();
+    let codingInfo = this.readHexOctet();
     if (!(codingInfo & 0x80)) {
       return null;
     }
 
     let textEncoding = (codingInfo & 0x70) >> 4;
     let shouldIncludeCountryInitials = !!(codingInfo & 0x08);
     let spareBits = codingInfo & 0x07;
     let resultString;
 
     switch (textEncoding) {
     case 0:
       // GSM Default alphabet.
-      resultString = GsmPDUHelper.readSeptetsToString(
+      resultString = this.readSeptetsToString(
         ((len - 1) * 8 - spareBits) / 7, 0,
         PDU_NL_IDENTIFIER_DEFAULT,
         PDU_NL_IDENTIFIER_DEFAULT);
       break;
     case 1:
       // UCS2 encoded.
       resultString = this.readUCS2String(len - 1);
       break;
@@ -8058,24 +8246,28 @@ let GsmPDUHelper = {
     // country initials to the resulting string.
     return resultString;
   }
 };
 
 /**
  * Provide buffer with bitwise read/write function so make encoding/decoding easier.
  */
-let BitBufferHelper = {
+function BitBufferHelperObject(/* unused */aContext) {
+  this.readBuffer = [];
+  this.writeBuffer = [];
+}
+BitBufferHelperObject.prototype = {
   readCache: 0,
   readCacheSize: 0,
-  readBuffer: [],
+  readBuffer: null,
   readIndex: 0,
   writeCache: 0,
   writeCacheSize: 0,
-  writeBuffer: [],
+  writeBuffer: null,
 
   // Max length is 32 because we use integer as read/write cache.
   // All read/write functions are implemented based on bitwise operation.
   readBits: function(length) {
     if (length <= 0 || length > 32) {
       return null;
     }
 
@@ -8201,17 +8393,22 @@ let BitBufferHelper = {
 
 /**
  * Helper for CDMA PDU
  *
  * Currently, some function are shared with GsmPDUHelper, they should be
  * moved from GsmPDUHelper to a common object shared among GsmPDUHelper and
  * CdmaPDUHelper.
  */
-let CdmaPDUHelper = {
+function CdmaPDUHelperObject(aContext) {
+  this.context = aContext;
+}
+CdmaPDUHelperObject.prototype = {
+  context: null,
+
   //       1..........C
   // Only "1234567890*#" is defined in C.S0005-D v2.0
   dtmfChars: ".1234567890*#...",
 
   /**
    * Entry point for SMS encoding, the options object is made compatible
    * with existing writeMessage() of GsmPDUHelper, but less key is used.
    *
@@ -8232,17 +8429,17 @@ let CdmaPDUHelper = {
    *        Reference number of concatenated SMS message
    * @param segmentMaxSeq
    *        Total number of concatenated SMS message
    * @param segmentSeq
    *        Sequence number of concatenated SMS message
    */
   writeMessage: function(options) {
     if (DEBUG) {
-      debug("cdma_writeMessage: " + JSON.stringify(options));
+      this.context.debug("cdma_writeMessage: " + JSON.stringify(options));
     }
 
     // Get encoding
     options.encoding = this.gsmDcsToCdmaEncoding(options.dcs);
 
     // Common Header
     if (options.segmentMaxSeq > 1) {
       this.writeInt(PDU_CDMA_MSG_TELESERIVCIE_ID_WEMT);
@@ -8278,21 +8475,21 @@ let CdmaPDUHelper = {
 
     encodeResult = null;
   },
 
   /**
    * Data writters
    */
   writeInt: function(value) {
-    Buf.writeInt32(value);
+    this.context.Buf.writeInt32(value);
   },
 
   writeByte: function(value) {
-    Buf.writeInt32(value & 0xFF);
+    this.context.Buf.writeInt32(value & 0xFF);
   },
 
   /**
    * Transform GSM DCS to CDMA encoding.
    */
   gsmDcsToCdmaEncoding: function(encoding) {
     switch (encoding) {
       case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
@@ -8375,17 +8572,17 @@ let CdmaPDUHelper = {
    *        Reference number of concatenated SMS message
    * @param segmentMaxSeq
    *        Total number of concatenated SMS message
    * @param segmentSeq
    *        Sequence number of concatenated SMS message
    */
   encodeUserData: function(options) {
     let userDataBuffer = [];
-    BitBufferHelper.startWrite(userDataBuffer);
+    this.context.BitBufferHelper.startWrite(userDataBuffer);
 
     // Message Identifier
     this.encodeUserDataMsgId(options);
 
     // User Data
     this.encodeUserDataMsg(options);
 
     // Reply Option
@@ -8395,16 +8592,17 @@ let CdmaPDUHelper = {
   },
 
   /**
    * User data subparameter encoder : Message Identifier
    *
    * @see 3GGP2 C.S0015-B 2.0, 4.5.1 Message Identifier
    */
   encodeUserDataMsgId: function(options) {
+    let BitBufferHelper = this.context.BitBufferHelper;
     BitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_MSG_ID, 8);
     BitBufferHelper.writeBits(3, 8);
     BitBufferHelper.writeBits(PDU_CDMA_MSG_TYPE_SUBMIT, 4);
     BitBufferHelper.writeBits(1, 16); // TODO: How to get message ID?
     if (options.segmentMaxSeq > 1) {
       BitBufferHelper.writeBits(1, 1);
     } else {
       BitBufferHelper.writeBits(0, 1);
@@ -8414,16 +8612,17 @@ let CdmaPDUHelper = {
   },
 
   /**
    * User data subparameter encoder : User Data
    *
    * @see 3GGP2 C.S0015-B 2.0, 4.5.2 User Data
    */
   encodeUserDataMsg: function(options) {
+    let BitBufferHelper = this.context.BitBufferHelper;
     BitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_BODY, 8);
     // Reserve space for length
     BitBufferHelper.writeBits(0, 8);
     let lengthPosition = BitBufferHelper.getWriteBufferSize();
 
     BitBufferHelper.writeBits(options.encoding, 5);
 
     // Add user data header for message segement
@@ -8517,16 +8716,17 @@ let CdmaPDUHelper = {
 
   /**
    * User data subparameter encoder : Reply Option
    *
    * @see 3GGP2 C.S0015-B 2.0, 4.5.11 Reply Option
    */
   encodeUserDataReplyOption: function(options) {
     if (options.requestStatusReport) {
+      let BitBufferHelper = this.context.BitBufferHelper;
       BitBufferHelper.writeBits(PDU_CDMA_MSG_USERDATA_REPLY_OPTION, 8);
       BitBufferHelper.writeBits(1, 8);
       BitBufferHelper.writeBits(0, 1); // USER_ACK_REQ
       BitBufferHelper.writeBits(1, 1); // DAK_REQ
       BitBufferHelper.flushWithPadding();
     }
   },
 
@@ -8633,40 +8833,40 @@ let CdmaPDUHelper = {
    *
    * @param length
    *        Length of SMS string in the incoming parcel.
    *
    * @return Message parsed or null for invalid message.
    */
   processReceivedSms: function(length) {
     if (!length) {
-      if (DEBUG) debug("Received empty SMS!");
+      if (DEBUG) this.context.debug("Received empty SMS!");
       return [null, PDU_FCS_UNSPECIFIED];
     }
 
     let message = this.readMessage();
-    if (DEBUG) debug("Got new SMS: " + JSON.stringify(message));
+    if (DEBUG) this.context.debug("Got new SMS: " + JSON.stringify(message));
 
     // Determine result
     if (!message) {
       return [null, PDU_FCS_UNSPECIFIED];
     }
 
     return [message, PDU_FCS_OK];
   },
 
   /**
    * Data readers
    */
   readInt: function() {
-    return Buf.readInt32();
+    return this.context.Buf.readInt32();
   },
 
   readByte: function() {
-    return (Buf.readInt32() & 0xFF);
+    return (this.context.Buf.readInt32() & 0xFF);
   },
 
   /**
    * Decode CDMA address data into address string
    *
    * @see 3GGP2 C.S0015-B 2.0, 3.4.3.3 Address Parameters
    *
    * Required key in addrInfo
@@ -8703,17 +8903,17 @@ let CdmaPDUHelper = {
       let id = this.readByte(),
           length = this.readByte(),
           userDataBuffer = [];
 
       for (let i = 0; i < length; i++) {
           userDataBuffer.push(this.readByte());
       }
 
-      BitBufferHelper.startRead(userDataBuffer);
+      this.context.BitBufferHelper.startRead(userDataBuffer);
 
       switch (id) {
         case PDU_CDMA_MSG_USERDATA_MSG_ID:
           message[id] = this.decodeUserDataMsgId();
           break;
         case PDU_CDMA_MSG_USERDATA_BODY:
           message[id] = this.decodeUserDataMsg(message[PDU_CDMA_MSG_USERDATA_MSG_ID].userHeader);
           break;
@@ -8741,32 +8941,34 @@ let CdmaPDUHelper = {
 
   /**
    * User data subparameter decoder: Message Identifier
    *
    * @see 3GGP2 C.S0015-B 2.0, 4.5.1 Message Identifier
    */
   decodeUserDataMsgId: function() {
     let result = {};
+    let BitBufferHelper = this.context.BitBufferHelper;
     result.msgType = BitBufferHelper.readBits(4);
     result.msgId = BitBufferHelper.readBits(16);
     result.userHeader = BitBufferHelper.readBits(1);
 
     return result;
   },
 
   /**
    * Decode user data header, we only care about segment information
    * on CDMA.
    *
    * This function is mostly copied from gsmPduHelper.readUserDataHeader() but
    * change the read function, because CDMA user header decoding is't byte-wise
    * aligned.
    */
   decodeUserDataHeader: function(encoding) {
+    let BitBufferHelper = this.context.BitBufferHelper;
     let header = {},
         headerSize = BitBufferHelper.readBits(8),
         userDataHeaderSize = headerSize + 1,
         headerPaddingBits = 0;
 
     // Calculate header size
     if (encoding === PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
       // Length is in 7-bit
@@ -8871,17 +9073,19 @@ let CdmaPDUHelper = {
             // storeType == PDU_MWI_STORE_TYPE_DISCARD
             // only override mwi.discard here if it hasn't already been set
             mwi.discard = true;
           }
 
           mwi.msgCount = msgCount & 0xFF;
           mwi.active = mwi.msgCount > 0;
 
-          if (DEBUG) debug("MWI in TP_UDH received: " + JSON.stringify(mwi));
+          if (DEBUG) {
+            this.context.debug("MWI in TP_UDH received: " + JSON.stringify(mwi));
+          }
           break;
         }
         default:
           // Drop unsupported id
           for (let i = 0; i < length; i++) {
             BitBufferHelper.readBits(8);
           }
       }
@@ -8913,16 +9117,17 @@ let CdmaPDUHelper = {
         return PDU_DCS_MSG_CODING_16BITS_ALPHABET;
     }
     return null;
   },
 
   decodeCdmaPDUMsg: function(encoding, msgType, msgBodySize) {
     const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
     const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
+    let BitBufferHelper = this.context.BitBufferHelper;
     let result = "";
     let msgDigit;
     switch (encoding) {
       case PDU_CDMA_MSG_CODING_OCTET:         // TODO : Require Test
         while(msgBodySize > 0) {
           msgDigit = String.fromCharCode(BitBufferHelper.readBits(8));
           result += msgDigit;
           msgBodySize--;
@@ -9045,21 +9250,22 @@ let CdmaPDUHelper = {
   },
 
   /**
    * User data subparameter decoder : User Data
    *
    * @see 3GGP2 C.S0015-B 2.0, 4.5.2 User Data
    */
   decodeUserDataMsg: function(hasUserHeader) {
+    let BitBufferHelper = this.context.BitBufferHelper;
     let result = {},
         encoding = BitBufferHelper.readBits(5),
         msgType;
 
-    if(encoding === PDU_CDMA_MSG_CODING_IS_91) {
+    if (encoding === PDU_CDMA_MSG_CODING_IS_91) {
       msgType = BitBufferHelper.readBits(8);
     }
     result.encoding = this.getCdmaMsgEncoding(encoding);
 
     let msgBodySize = BitBufferHelper.readBits(8);
 
     // For segmented SMS, a user header is included before sms content
     if (hasUserHeader) {
@@ -9088,16 +9294,17 @@ let CdmaPDUHelper = {
   },
 
   /**
    * User data subparameter decoder : Time Stamp
    *
    * @see 3GGP2 C.S0015-B 2.0, 4.5.4 Message Center Time Stamp
    */
   decodeUserDataTimestamp: function() {
+    let BitBufferHelper = this.context.BitBufferHelper;
     let year = this.decodeBcd(BitBufferHelper.readBits(8)),
         month = this.decodeBcd(BitBufferHelper.readBits(8)) - 1,
         date = this.decodeBcd(BitBufferHelper.readBits(8)),
         hour = this.decodeBcd(BitBufferHelper.readBits(8)),
         min = this.decodeBcd(BitBufferHelper.readBits(8)),
         sec = this.decodeBcd(BitBufferHelper.readBits(8));
 
     if (year >= 96 && year <= 99) {
@@ -9112,43 +9319,44 @@ let CdmaPDUHelper = {
   },
 
   /**
    * User data subparameter decoder : Reply Option
    *
    * @see 3GGP2 C.S0015-B 2.0, 4.5.11 Reply Option
    */
   decodeUserDataReplyOption: function() {
-    let replyAction = BitBufferHelper.readBits(4),
+    let replyAction = this.context.BitBufferHelper.readBits(4),
         result = { userAck: (replyAction & 0x8) ? true : false,
                    deliverAck: (replyAction & 0x4) ? true : false,
                    readAck: (replyAction & 0x2) ? true : false,
                    report: (replyAction & 0x1) ? true : false
                  };
 
     return result;
   },
 
   /**
    * User data subparameter decoder : Language Indicator
    *
    * @see 3GGP2 C.S0015-B 2.0, 4.5.14 Language Indicator
    */
   decodeLanguageIndicator: function() {
-    let language = BitBufferHelper.readBits(8);
+    let language = this.context.BitBufferHelper.readBits(8);
     let result = CB_CDMA_LANG_GROUP[language];
     return result;
   },
 
   /**
    * User data subparameter decoder : Call-Back Number
    *
    * @see 3GGP2 C.S0015-B 2.0, 4.5.15 Call-Back Number
    */
   decodeUserDataCallbackNumber: function() {
+    let BitBufferHelper = this.context.BitBufferHelper;
     let digitMode = BitBufferHelper.readBits(1);
     if (digitMode) {
       let numberType = BitBufferHelper.readBits(3),
           numberPlan = BitBufferHelper.readBits(4);
     }
     let numberFields = BitBufferHelper.readBits(8),
         result = "";
     for (let i = 0; i < numberFields; i++) {
@@ -9165,28 +9373,30 @@ let CdmaPDUHelper = {
   },
 
   /**
    * User data subparameter decoder : Message Status
    *
    * @see 3GGP2 C.S0015-B 2.0, 4.5.21 Message Status
    */
   decodeUserDataMsgStatus: function() {
+    let BitBufferHelper = this.context.BitBufferHelper;
     let result = {
       errorClass: BitBufferHelper.readBits(2),
       msgStatus: BitBufferHelper.readBits(6)
     };
 
     return result;
   },
 
   /**
    * Decode information record parcel.
    */
   decodeInformationRecord: function() {
+    let Buf = this.context.Buf;
     let record = {};
     let numOfRecords = Buf.readInt32();
 
     let type;
     for (let i = 0; i < numOfRecords; i++) {
       type = Buf.readInt32();
 
       switch (type) {
@@ -9289,25 +9499,32 @@ let CdmaPDUHelper = {
 
     return record;
   }
 };
 
 /**
  * Helper for processing ICC PDUs.
  */
-let ICCPDUHelper = {
+function ICCPDUHelperObject(aContext) {
+  this.context = aContext;
+}
+ICCPDUHelperObject.prototype = {
+  context: null,
+
   /**
    * Read GSM 8-bit unpacked octets,
    * which are default 7-bit alphabets with bit 8 set to 0.
    *
    * @param numOctets
    *        Number of octets to be read.
    */
   read8BitUnpackedToString: function(numOctets) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     let ret = "";
     let escapeFound = false;
     let i;
     const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
     const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
 
     for(i = 0; i < numOctets; i++) {
       let octet = GsmPDUHelper.readHexOctet();
@@ -9333,31 +9550,34 @@ let ICCPDUHelper = {
         }
       } else if (octet == PDU_NL_EXTENDED_ESCAPE) {
         escapeFound = true;
       } else {
         ret += langTable[octet];
       }
     }
 
+    let Buf = this.context.Buf;
     Buf.seekIncoming((numOctets - i) * Buf.PDU_HEX_OCTET_SIZE);
     return ret;
   },
 
   /**
    * Write GSM 8-bit unpacked octets.
    *
    * @param numOctets   Number of total octets to be writen, including trailing
    *                    0xff.
    * @param str         String to be written. Could be null.
    */
   writeStringTo8BitUnpacked: function(numOctets, str) {
     const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
     const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
 
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     // If the character is GSM extended alphabet, two octets will be written.
     // So we need to keep track of number of octets to be written.
     let i, j;
     let len = str ? str.length : 0;
     for (i = 0, j = 0; i < len && j < numOctets; i++) {
       let c = str.charAt(i);
       let octet = langTable.indexOf(c);
 
@@ -9390,16 +9610,19 @@ let ICCPDUHelper = {
    *
    * @see TS 101.221, Annex A.
    * @param scheme
    *        Coding scheme for UCS2 on UICC. One of 0x80, 0x81 or 0x82.
    * @param numOctets
    *        Number of octets to be read as UCS2 string.
    */
   readICCUCS2String: function(scheme, numOctets) {
+    let Buf = this.context.Buf;
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     let str = "";
     switch (scheme) {
       /**
        * +------+---------+---------+---------+---------+------+------+
        * | 0x80 | Ch1_msb | Ch1_lsb | Ch2_msb | Ch2_lsb | 0xff | 0xff |
        * +------+---------+---------+---------+---------+------+------+
        */
       case 0x80:
@@ -9483,16 +9706,17 @@ let ICCPDUHelper = {
   },
 
   /**
    * Read Alpha Id and Dialling number from TS TS 151.011 clause 10.5.1
    *
    * @param recordSize  The size of linear fixed record.
    */
   readAlphaIdDiallingNumber: function(recordSize) {
+    let Buf = this.context.Buf;
     let length = Buf.readInt32();
 
     let alphaLen = recordSize - ADN_FOOTER_SIZE_BYTES;
     let alphaId = this.readAlphaIdentifier(alphaLen);
 
     let number = this.readNumberWithLength();
 
     // Skip 2 unused octets, CCP and EXT1.
@@ -9510,16 +9734,19 @@ let ICCPDUHelper = {
   /**
    * Write Alpha Identifier and Dialling number from TS 151.011 clause 10.5.1
    *
    * @param recordSize  The size of linear fixed record.
    * @param alphaId     Alpha Identifier to be written.
    * @param number      Dialling Number to be written.
    */
   writeAlphaIdDiallingNumber: function(recordSize, alphaId, number) {
+    let Buf = this.context.Buf;
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     // Write String length
     let strLen = recordSize * 2;
     Buf.writeInt32(strLen);
 
     let alphaLen = recordSize - ADN_FOOTER_SIZE_BYTES;
     this.writeAlphaIdentifier(alphaLen, alphaId);
     this.writeNumberWithLength(number);
 
@@ -9545,22 +9772,23 @@ let ICCPDUHelper = {
    */
   readAlphaIdentifier: function(numOctets) {
     if (numOctets === 0) {
       return "";
     }
 
     let temp;
     // Read the 1st octet to determine the encoding.
-    if ((temp = GsmPDUHelper.readHexOctet()) == 0x80 ||
+    if ((temp = this.context.GsmPDUHelper.readHexOctet()) == 0x80 ||
          temp == 0x81 ||
          temp == 0x82) {
       numOctets--;
       return this.readICCUCS2String(temp, numOctets);
     } else {
+      let Buf = this.context.Buf;
       Buf.seekIncoming(-1 * Buf.PDU_HEX_OCTET_SIZE);
       return this.read8BitUnpackedToString(numOctets);
     }
   },
 
   /**
    * Write Alpha Identifier.
    *
@@ -9573,19 +9801,21 @@ let ICCPDUHelper = {
    * Unused octets will be written as 0xff.
    */
   writeAlphaIdentifier: function(numOctets, alphaId) {
     if (numOctets === 0) {
       return;
     }
 
     // If alphaId is empty or it's of GSM 8 bit.
-    if (!alphaId || ICCUtilsHelper.isGsm8BitAlphabet(alphaId)) {
+    if (!alphaId || this.context.ICCUtilsHelper.isGsm8BitAlphabet(alphaId)) {
       this.writeStringTo8BitUnpacked(numOctets, alphaId);
     } else {
+      let GsmPDUHelper = this.context.GsmPDUHelper;
+
       // Currently only support UCS2 coding scheme 0x80.
       GsmPDUHelper.writeHexOctet(0x80);
       numOctets--;
       // Now the alphaId is UCS2 string, each character will take 2 octets.
       if (alphaId.length * 2 > numOctets) {
         alphaId = alphaId.substring(0, Math.floor(numOctets / 2));
       }
       GsmPDUHelper.writeUCS2String(alphaId);
@@ -9612,68 +9842,75 @@ let ICCPDUHelper = {
    * 1 byte to store the TON/NPI, 0x81
    * 5 bytes to store the BCD number 2143658709.
    *
    * Here the definition of the length is different from SMS spec,
    * TS 23.040 9.1.2.5, which the length means
    * "number of useful semi-octets within the Address-Value field".
    */
   readDiallingNumber: function(len) {
-    if (DEBUG) debug("PDU: Going to read Dialling number: " + len);
+    if (DEBUG) this.context.debug("PDU: Going to read Dialling number: " + len);
     if (len === 0) {
       return "";
     }
 
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     // TOA = TON + NPI
     let toa = GsmPDUHelper.readHexOctet();
 
     let number = GsmPDUHelper.readSwappedNibbleBcdString(len - 1);
     if (number.length <= 0) {
-      if (DEBUG) debug("No number provided");
+      if (DEBUG) this.context.debug("No number provided");
       return "";
     }
     if ((toa >> 4) == (PDU_TOA_INTERNATIONAL >> 4)) {
       number = '+' + number;
     }
     return number;
   },
 
   /**
    * Write Dialling Number.
    *
    * @param number  The Dialling number
    */
   writeDiallingNumber: function(number) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     let toa = PDU_TOA_ISDN; // 81
     if (number[0] == '+') {
       toa = PDU_TOA_INTERNATIONAL | PDU_TOA_ISDN; // 91
       number = number.substring(1);
     }
     GsmPDUHelper.writeHexOctet(toa);
     GsmPDUHelper.writeSwappedNibbleBCD(number);
   },
 
   readNumberWithLength: function() {
+    let Buf = this.context.Buf;
     let number;
-    let numLen = GsmPDUHelper.readHexOctet();
+    let numLen = this.context.GsmPDUHelper.readHexOctet();
     if (numLen != 0xff) {
       if (numLen > ADN_MAX_BCD_NUMBER_BYTES) {
         throw new Error("invalid length of BCD number/SSC contents - " + numLen);
       }
 
       number = this.readDiallingNumber(numLen);
       Buf.seekIncoming((ADN_MAX_BCD_NUMBER_BYTES - numLen) * Buf.PDU_HEX_OCTET_SIZE);
     } else {
       Buf.seekIncoming(ADN_MAX_BCD_NUMBER_BYTES * Buf.PDU_HEX_OCTET_SIZE);
     }
 
     return number;
   },
 
   writeNumberWithLength: function(number) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     if (number) {
       let numStart = number[0] == "+" ? 1 : 0;
       number = number.substring(0, numStart) +
                number.substring(numStart)
                      .replace(/[^0-9*#,]/g, "")
                      .replace(/\*/g, "a")
                      .replace(/\#/g, "b")
                      .replace(/\,/g, "c");
@@ -9696,22 +9933,28 @@ let ICCPDUHelper = {
       // +1 for numLen
       for (let i = 0; i < ADN_MAX_BCD_NUMBER_BYTES + 1; i++) {
         GsmPDUHelper.writeHexOctet(0xff);
       }
     }
   }
 };
 
-let StkCommandParamsFactory = {
+function StkCommandParamsFactoryObject(aContext) {
+  this.context = aContext;
+}
+StkCommandParamsFactoryObject.prototype = {
+  context: null,
+
   createParam: function(cmdDetails, ctlvs) {
-    let method = StkCommandParamsFactory[cmdDetails.typeOfCommand];
+    let method = this[cmdDetails.typeOfCommand];
     if (typeof method != "function") {
       if (DEBUG) {
-        debug("Unknown proactive command " + cmdDetails.typeOfCommand.toString(16));
+        this.context.debug("Unknown proactive command " +
+                           cmdDetails.typeOfCommand.toString(16));
       }
       return null;
     }
     return method.call(this, cmdDetails, ctlvs);
   },
 
   /**
    * Construct a param for Refresh.
@@ -9721,43 +9964,43 @@ let StkCommandParamsFactory = {
    * @param ctlvs
    *        The all TLVs in this proactive command.
    */
   processRefresh: function(cmdDetails, ctlvs) {
     let refreshType = cmdDetails.commandQualifier;
     switch (refreshType) {
       case STK_REFRESH_FILE_CHANGE:
       case STK_REFRESH_NAA_INIT_AND_FILE_CHANGE:
-        let ctlv = StkProactiveCmdHelper.searchForTag(
+        let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
           COMPREHENSIONTLV_TAG_FILE_LIST, ctlvs);
         if (ctlv) {
           let list = ctlv.value.fileList;
           if (DEBUG) {
-            debug("Refresh, list = " + list);
+            this.context.debug("Refresh, list = " + list);
           }
-          ICCRecordHelper.fetchICCRecords();
+          this.context.ICCRecordHelper.fetchICCRecords();
         }
         break;
     }
     return null;
   },
 
   /**
    * Construct a param for Poll Interval.
    *
    * @param cmdDetails
    *        The value object of CommandDetails TLV.
    * @param ctlvs
    *        The all TLVs in this proactive command.
    */
   processPollInterval: function(cmdDetails, ctlvs) {
-    let ctlv = StkProactiveCmdHelper.searchForTag(
+    let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
         COMPREHENSIONTLV_TAG_DURATION, ctlvs);
     if (!ctlv) {
-      RIL.sendStkTerminalResponse({
+      this.context.RIL.sendStkTerminalResponse({
         command: cmdDetails,
         resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
       throw new Error("Stk Poll Interval: Required value missing : Duration");
     }
 
     return ctlv.value;
   },
 
@@ -9777,20 +10020,20 @@ let StkCommandParamsFactory = {
    * Construct a param for Set Up Event list.
    *
    * @param cmdDetails
    *        The value object of CommandDetails TLV.
    * @param ctlvs
    *        The all TLVs in this proactive command.
    */
   processSetUpEventList: function(cmdDetails, ctlvs) {
-    let ctlv = StkProactiveCmdHelper.searchForTag(
+    let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
         COMPREHENSIONTLV_TAG_EVENT_LIST, ctlvs);
     if (!ctlv) {
-      RIL.sendStkTerminalResponse({
+      this.context.RIL.sendStkTerminalResponse({
         command: cmdDetails,
         resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
       throw new Error("Stk Event List: Required value missing : Event List");
     }
 
     return ctlv.value || {eventList: null};
   },
 
@@ -9798,33 +10041,34 @@ let StkCommandParamsFactory = {
    * Construct a param for Select Item.
    *
    * @param cmdDetails
    *        The value object of CommandDetails TLV.
    * @param ctlvs
    *        The all TLVs in this proactive command.
    */
   processSelectItem: function(cmdDetails, ctlvs) {
+    let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
     let menu = {};
 
     let ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
     if (ctlv) {
       menu.title = ctlv.value.identifier;
     }
 
     menu.items = [];
     for (let i = 0; i < ctlvs.length; i++) {
       let ctlv = ctlvs[i];
       if (ctlv.tag == COMPREHENSIONTLV_TAG_ITEM) {
         menu.items.push(ctlv.value);
       }
     }
 
     if (menu.items.length === 0) {
-      RIL.sendStkTerminalResponse({
+      this.context.RIL.sendStkTerminalResponse({
         command: cmdDetails,
         resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
       throw new Error("Stk Menu: Required value missing : items");
     }
 
     ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ITEM_ID, ctlvs);
     if (ctlv) {
       menu.defaultItem = ctlv.value.identifier - 1;
@@ -9842,21 +10086,22 @@ let StkCommandParamsFactory = {
     if (ctlv) {
       menu.nextActionList = ctlv.value;
     }
 
     return menu;
   },
 
   processDisplayText: function(cmdDetails, ctlvs) {
+    let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
     let textMsg = {};
 
     let ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_TEXT_STRING, ctlvs);
     if (!ctlv) {
-      RIL.sendStkTerminalResponse({
+      this.context.RIL.sendStkTerminalResponse({
         command: cmdDetails,
         resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
       throw new Error("Stk Display Text: Required value missing : Text String");
     }
     textMsg.text = ctlv.value.textString;
 
     ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE, ctlvs);
     if (ctlv) {
@@ -9879,34 +10124,36 @@ let StkCommandParamsFactory = {
     }
 
     return textMsg;
   },
 
   processSetUpIdleModeText: function(cmdDetails, ctlvs) {
     let textMsg = {};
 
-    let ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_TEXT_STRING, ctlvs);
+    let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
+        COMPREHENSIONTLV_TAG_TEXT_STRING, ctlvs);
     if (!ctlv) {
-      RIL.sendStkTerminalResponse({
+      this.context.RIL.sendStkTerminalResponse({
         command: cmdDetails,
         resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
       throw new Error("Stk Set Up Idle Text: Required value missing : Text String");
     }
     textMsg.text = ctlv.value.textString;
 
     return textMsg;
   },
 
   processGetInkey: function(cmdDetails, ctlvs) {
+    let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
     let input = {};
 
     let ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_TEXT_STRING, ctlvs);
     if (!ctlv) {
-      RIL.sendStkTerminalResponse({
+      this.context.RIL.sendStkTerminalResponse({
         command: cmdDetails,
         resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
       throw new Error("Stk Get InKey: Required value missing : Text String");
     }
     input.text = ctlv.value.textString;
 
     // duration
     ctlv = StkProactiveCmdHelper.searchForTag(
@@ -9938,21 +10185,22 @@ let StkCommandParamsFactory = {
     if (cmdDetails.commandQualifier & 0x80) {
       input.isHelpAvailable = true;
     }
 
     return input;
   },
 
   processGetInput: function(cmdDetails, ctlvs) {
+    let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
     let input = {};
 
     let ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_TEXT_STRING, ctlvs);
     if (!ctlv) {
-      RIL.sendStkTerminalResponse({
+      this.context.RIL.sendStkTerminalResponse({
         command: cmdDetails,
         resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
       throw new Error("Stk Get Input: Required value missing : Text String");
     }
     input.text = ctlv.value.textString;
 
     ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_RESPONSE_LENGTH, ctlvs);
     if (ctlv) {
@@ -9991,66 +10239,69 @@ let StkCommandParamsFactory = {
     }
 
     return input;
   },
 
   processEventNotify: function(cmdDetails, ctlvs) {
     let textMsg = {};
 
-    let ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
+    let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
+        COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
     if (!ctlv) {
-      RIL.sendStkTerminalResponse({
+      this.context.RIL.sendStkTerminalResponse({
         command: cmdDetails,
         resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
       throw new Error("Stk Event Notfiy: Required value missing : Alpha ID");
     }
     textMsg.text = ctlv.value.identifier;
 
     return textMsg;
   },
 
   processSetupCall: function(cmdDetails, ctlvs) {
+    let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
     let call = {};
     let iter = Iterator(ctlvs);
 
     let ctlv = StkProactiveCmdHelper.searchForNextTag(COMPREHENSIONTLV_TAG_ALPHA_ID, iter);
     if (ctlv) {
       call.confirmMessage = ctlv.value.identifier;
     }
 
     ctlv = StkProactiveCmdHelper.searchForNextTag(COMPREHENSIONTLV_TAG_ALPHA_ID, iter);
     if (ctlv) {
       call.callMessage = ctlv.value.identifier;
     }
 
     ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ADDRESS, ctlvs);
     if (!ctlv) {
-      RIL.sendStkTerminalResponse({
+      this.context.RIL.sendStkTerminalResponse({
         command: cmdDetails,
         resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
       throw new Error("Stk Set Up Call: Required value missing : Adress");
     }
     call.address = ctlv.value.number;
 
     // see 3GPP TS 31.111 section 6.4.13
     ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_DURATION, ctlvs);
     if (ctlv) {
       call.duration = ctlv.value;
     }
 
     return call;
   },
 
   processLaunchBrowser: function(cmdDetails, ctlvs) {
+    let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
     let browser = {};
 
     let ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_URL, ctlvs);
     if (!ctlv) {
-      RIL.sendStkTerminalResponse({
+      this.context.RIL.sendStkTerminalResponse({
         command: cmdDetails,
         resultCode: STK_RESULT_REQUIRED_VALUES_MISSING});
       throw new Error("Stk Launch Browser: Required value missing : URL");
     }
     browser.url = ctlv.value.url;
 
     ctlv = StkProactiveCmdHelper.searchForTag(COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
     if (ctlv) {
@@ -10058,16 +10309,17 @@ let StkCommandParamsFactory = {
     }
 
     browser.mode = cmdDetails.commandQualifier & 0x03;
 
     return browser;
   },
 
   processPlayTone: function(cmdDetails, ctlvs) {
+    let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
     let playTone = {};
 
     let ctlv = StkProactiveCmdHelper.searchForTag(
         COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
     if (ctlv) {
       playTone.text = ctlv.value.identifier;
     }
 
@@ -10099,16 +10351,17 @@ let StkCommandParamsFactory = {
   processProvideLocalInfo: function(cmdDetails, ctlvs) {
     let provideLocalInfo = {
       localInfoType: cmdDetails.commandQualifier
     };
     return provideLocalInfo;
   },
 
   processTimerManagement: function(cmdDetails, ctlvs) {
+    let StkProactiveCmdHelper = this.context.StkProactiveCmdHelper;
     let timer = {
       timerAction: cmdDetails.commandQualifier
     };
 
     let ctlv = StkProactiveCmdHelper.searchForTag(
         COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER, ctlvs);
     if (ctlv) {
       timer.timerId = ctlv.value.timerId;
@@ -10129,102 +10382,108 @@ let StkCommandParamsFactory = {
     * @param cmdDetails
     *        The value object of CommandDetails TLV.
     * @param ctlvs
     *        The all TLVs in this proactive command.
     */
   processBipMessage: function(cmdDetails, ctlvs) {
     let bipMsg = {};
 
-    let ctlv = StkProactiveCmdHelper.searchForTag(
+    let ctlv = this.context.StkProactiveCmdHelper.searchForTag(
         COMPREHENSIONTLV_TAG_ALPHA_ID, ctlvs);
     if (ctlv) {
       bipMsg.text = ctlv.value.identifier;
     }
 
     return bipMsg;
   }
 };
-StkCommandParamsFactory[STK_CMD_REFRESH] = function STK_CMD_REFRESH(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_REFRESH] = function STK_CMD_REFRESH(cmdDetails, ctlvs) {
   return this.processRefresh(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_POLL_INTERVAL] = function STK_CMD_POLL_INTERVAL(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_POLL_INTERVAL] = function STK_CMD_POLL_INTERVAL(cmdDetails, ctlvs) {
   return this.processPollInterval(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_POLL_OFF] = function STK_CMD_POLL_OFF(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_POLL_OFF] = function STK_CMD_POLL_OFF(cmdDetails, ctlvs) {
   return this.processPollOff(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_PROVIDE_LOCAL_INFO] = function STK_CMD_PROVIDE_LOCAL_INFO(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_PROVIDE_LOCAL_INFO] = function STK_CMD_PROVIDE_LOCAL_INFO(cmdDetails, ctlvs) {
   return this.processProvideLocalInfo(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_SET_UP_EVENT_LIST] = function STK_CMD_SET_UP_EVENT_LIST(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_SET_UP_EVENT_LIST] = function STK_CMD_SET_UP_EVENT_LIST(cmdDetails, ctlvs) {
   return this.processSetUpEventList(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_SET_UP_MENU] = function STK_CMD_SET_UP_MENU(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_SET_UP_MENU] = function STK_CMD_SET_UP_MENU(cmdDetails, ctlvs) {
   return this.processSelectItem(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_SELECT_ITEM] = function STK_CMD_SELECT_ITEM(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_SELECT_ITEM] = function STK_CMD_SELECT_ITEM(cmdDetails, ctlvs) {
   return this.processSelectItem(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_DISPLAY_TEXT] = function STK_CMD_DISPLAY_TEXT(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_DISPLAY_TEXT] = function STK_CMD_DISPLAY_TEXT(cmdDetails, ctlvs) {
   return this.processDisplayText(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_SET_UP_IDLE_MODE_TEXT] = function STK_CMD_SET_UP_IDLE_MODE_TEXT(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_SET_UP_IDLE_MODE_TEXT] = function STK_CMD_SET_UP_IDLE_MODE_TEXT(cmdDetails, ctlvs) {
   return this.processSetUpIdleModeText(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_GET_INKEY] = function STK_CMD_GET_INKEY(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_GET_INKEY] = function STK_CMD_GET_INKEY(cmdDetails, ctlvs) {
   return this.processGetInkey(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_GET_INPUT] = function STK_CMD_GET_INPUT(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_GET_INPUT] = function STK_CMD_GET_INPUT(cmdDetails, ctlvs) {
   return this.processGetInput(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_SEND_SS] = function STK_CMD_SEND_SS(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_SS] = function STK_CMD_SEND_SS(cmdDetails, ctlvs) {
+  return this.processEventNotify(cmdDetails, ctlvs);
+};
+StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_USSD] = function STK_CMD_SEND_USSD(cmdDetails, ctlvs) {
   return this.processEventNotify(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_SEND_USSD] = function STK_CMD_SEND_USSD(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_SMS] = function STK_CMD_SEND_SMS(cmdDetails, ctlvs) {
   return this.processEventNotify(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_SEND_SMS] = function STK_CMD_SEND_SMS(cmdDetails, ctlvs) {
-  return this.processEventNotify(cmdDetails, ctlvs);
-};
-StkCommandParamsFactory[STK_CMD_SEND_DTMF] = function STK_CMD_SEND_DTMF(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_DTMF] = function STK_CMD_SEND_DTMF(cmdDetails, ctlvs) {
   return this.processEventNotify(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_SET_UP_CALL] = function STK_CMD_SET_UP_CALL(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_SET_UP_CALL] = function STK_CMD_SET_UP_CALL(cmdDetails, ctlvs) {
   return this.processSetupCall(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_LAUNCH_BROWSER] = function STK_CMD_LAUNCH_BROWSER(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_LAUNCH_BROWSER] = function STK_CMD_LAUNCH_BROWSER(cmdDetails, ctlvs) {
   return this.processLaunchBrowser(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_PLAY_TONE] = function STK_CMD_PLAY_TONE(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_PLAY_TONE] = function STK_CMD_PLAY_TONE(cmdDetails, ctlvs) {
   return this.processPlayTone(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_TIMER_MANAGEMENT] = function STK_CMD_TIMER_MANAGEMENT(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_TIMER_MANAGEMENT] = function STK_CMD_TIMER_MANAGEMENT(cmdDetails, ctlvs) {
   return this.processTimerManagement(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_OPEN_CHANNEL] = function STK_CMD_OPEN_CHANNEL(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_OPEN_CHANNEL] = function STK_CMD_OPEN_CHANNEL(cmdDetails, ctlvs) {
   return this.processBipMessage(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_CLOSE_CHANNEL] = function STK_CMD_CLOSE_CHANNEL(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_CLOSE_CHANNEL] = function STK_CMD_CLOSE_CHANNEL(cmdDetails, ctlvs) {
+  return this.processBipMessage(cmdDetails, ctlvs);
+};
+StkCommandParamsFactoryObject.prototype[STK_CMD_RECEIVE_DATA] = function STK_CMD_RECEIVE_DATA(cmdDetails, ctlvs) {
   return this.processBipMessage(cmdDetails, ctlvs);
 };
-StkCommandParamsFactory[STK_CMD_RECEIVE_DATA] = function STK_CMD_RECEIVE_DATA(cmdDetails, ctlvs) {
-  return this.processBipMessage(cmdDetails, ctlvs);
-};
-StkCommandParamsFactory[STK_CMD_SEND_DATA] = function STK_CMD_SEND_DATA(cmdDetails, ctlvs) {
+StkCommandParamsFactoryObject.prototype[STK_CMD_SEND_DATA] = function STK_CMD_SEND_DATA(cmdDetails, ctlvs) {
   return this.processBipMessage(cmdDetails, ctlvs);
 };
 
-let StkProactiveCmdHelper = {
+function StkProactiveCmdHelperObject(aContext) {
+  this.context = aContext;
+}
+StkProactiveCmdHelperObject.prototype = {
+  context: null,
+
   retrieve: function(tag, length) {
-    let method = StkProactiveCmdHelper[tag];
+    let method = this[tag];
     if (typeof method != "function") {
       if (DEBUG) {
-        debug("Unknown comprehension tag " + tag.toString(16));
-      }
+        this.context.debug("Unknown comprehension tag " + tag.toString(16));
+      }
+      let Buf = this.context.Buf;
       Buf.seekIncoming(length * Buf.PDU_HEX_OCTET_SIZE);
       return null;
     }
     return method.call(this, length);
   },
 
   /**
    * Command Details.
@@ -10232,16 +10491,17 @@ let StkProactiveCmdHelper = {
    * | Byte | Description         | Length |
    * |  1   | Command details Tag |   1    |
    * |  2   | Length = 03         |   1    |
    * |  3   | Command number      |   1    |
    * |  4   | Type of Command     |   1    |
    * |  5   | Command Qualifier   |   1    |
    */
   retrieveCommandDetails: function(length) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let cmdDetails = {
       commandNumber: GsmPDUHelper.readHexOctet(),
       typeOfCommand: GsmPDUHelper.readHexOctet(),
       commandQualifier: GsmPDUHelper.readHexOctet()
     };
     return cmdDetails;
   },
 
@@ -10250,16 +10510,17 @@ let StkProactiveCmdHelper = {
    *
    * | Byte | Description            | Length |
    * |  1   | Device Identity Tag    |   1    |
    * |  2   | Length = 02            |   1    |
    * |  3   | Source device Identity |   1    |
    * |  4   | Destination device Id  |   1    |
    */
   retrieveDeviceId: function(length) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let deviceId = {
       sourceId: GsmPDUHelper.readHexOctet(),
       destinationId: GsmPDUHelper.readHexOctet()
     };
     return deviceId;
   },
 
   /**
@@ -10268,31 +10529,32 @@ let StkProactiveCmdHelper = {
    * | Byte         | Description            | Length |
    * |  1           | Alpha Identifier Tag   |   1    |
    * | 2 ~ (Y-1)+2  | Length (X)             |   Y    |
    * | (Y-1)+3 ~    | Alpha identfier        |   X    |
    * | (Y-1)+X+2    |                        |        |
    */
   retrieveAlphaId: function(length) {
     let alphaId = {
-      identifier: ICCPDUHelper.readAlphaIdentifier(length)
+      identifier: this.context.ICCPDUHelper.readAlphaIdentifier(length)
     };
     return alphaId;
   },
 
   /**
    * Duration.
    *
    * | Byte | Description           | Length |
    * |  1   | Response Length Tag   |   1    |
    * |  2   | Lenth = 02            |   1    |
    * |  3   | Time unit             |   1    |
    * |  4   | Time interval         |   1    |
    */
   retrieveDuration: function(length) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let duration = {
       timeUnit: GsmPDUHelper.readHexOctet(),
       timeInterval: GsmPDUHelper.readHexOctet(),
     };
     return duration;
   },
 
   /**
@@ -10302,17 +10564,17 @@ let StkProactiveCmdHelper = {
    * |  1           | Alpha Identifier Tag   |   1    |
    * | 2 ~ (Y-1)+2  | Length (X)             |   Y    |
    * | (Y-1)+3      | TON and NPI            |   1    |
    * | (Y-1)+4 ~    | Dialling number        |   X    |
    * | (Y-1)+X+2    |                        |        |
    */
   retrieveAddress: function(length) {
     let address = {
-      number : ICCPDUHelper.readDiallingNumber(length)
+      number : this.context.ICCPDUHelper.readDiallingNumber(length)
     };
     return address;
   },
 
   /**
    * Text String.
    *
    * | Byte         | Description        | Length |
@@ -10323,27 +10585,29 @@ let StkProactiveCmdHelper = {
    * | (Y-1)+X+2    |                    |        |
    */
   retrieveTextString: function(length) {
     if (!length) {
       // null string.
       return {textString: null};
     }
 
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let text = {
       codingScheme: GsmPDUHelper.readHexOctet()
     };
 
     length--; // -1 for the codingScheme.
     switch (text.codingScheme & 0x0f) {
       case STK_TEXT_CODING_GSM_7BIT_PACKED:
         text.textString = GsmPDUHelper.readSeptetsToString(length * 8 / 7, 0, 0, 0);
         break;
       case STK_TEXT_CODING_GSM_8BIT:
-        text.textString = ICCPDUHelper.read8BitUnpackedToString(length);
+        text.textString =
+          this.context.ICCPDUHelper.read8BitUnpackedToString(length);
         break;
       case STK_TEXT_CODING_UCS2:
         text.textString = GsmPDUHelper.readUCS2String(length);
         break;
     }
     return text;
   },
 
@@ -10352,17 +10616,17 @@ let StkProactiveCmdHelper = {
    *
    * | Byte | Description     | Length |
    * |  1   | Tone Tag        |   1    |
    * |  2   | Lenth = 01      |   1    |
    * |  3   | Tone            |   1    |
    */
   retrieveTone: function(length) {
     let tone = {
-      tone: GsmPDUHelper.readHexOctet(),
+      tone: this.context.GsmPDUHelper.readHexOctet(),
     };
     return tone;
   },
 
   /**
    * Item.
    *
    * | Byte         | Description            | Length |
@@ -10376,47 +10640,48 @@ let StkProactiveCmdHelper = {
     // TS 102.223 ,clause 6.6.7 SET-UP MENU
     // If the "Item data object for item 1" is a null data object
     // (i.e. length = '00' and no value part), this is an indication to the ME
     // to remove the existing menu from the menu system in the ME.
     if (!length) {
       return null;
     }
     let item = {
-      identifier: GsmPDUHelper.readHexOctet(),
-      text: ICCPDUHelper.readAlphaIdentifier(length - 1)
+      identifier: this.context.GsmPDUHelper.readHexOctet(),
+      text: this.context.ICCPDUHelper.readAlphaIdentifier(length - 1)
     };
     return item;
   },
 
   /**
    * Item Identifier.
    *
    * | Byte | Description               | Length |
    * |  1   | Item Identifier Tag       |   1    |
    * |  2   | Lenth = 01                |   1    |
    * |  3   | Identifier of Item chosen |   1    |
    */
   retrieveItemId: function(length) {
     let itemId = {
-      identifier: GsmPDUHelper.readHexOctet()
+      identifier: this.context.GsmPDUHelper.readHexOctet()
     };
     return itemId;
   },
 
   /**
    * Response Length.
    *
    * | Byte | Description                | Length |
    * |  1   | Response Length Tag        |   1    |
    * |  2   | Lenth = 02                 |   1    |
    * |  3   | Minimum length of response |   1    |
    * |  4   | Maximum length of response |   1    |
    */
   retrieveResponseLength: function(length) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let rspLength = {
       minLength : GsmPDUHelper.readHexOctet(),
       maxLength : GsmPDUHelper.readHexOctet()
     };
     return rspLength;
   },
 
   /**
@@ -10425,23 +10690,23 @@ let StkProactiveCmdHelper = {
    * | Byte         | Description            | Length |
    * |  1           | File List Tag          |   1    |
    * | 2 ~ (Y-1)+2  | Length (X)             |   Y    |
    * | (Y-1)+3      | Number of files        |   1    |
    * | (Y-1)+4 ~    | Files                  |   X    |
    * | (Y-1)+X+2    |                        |        |
    */
   retrieveFileList: function(length) {
-    let num = GsmPDUHelper.readHexOctet();
+    let num = this.context.GsmPDUHelper.readHexOctet();
     let fileList = "";
     length--; // -1 for the num octet.
     for (let i = 0; i < 2 * length; i++) {
       // Didn't use readHexOctet here,
       // otherwise 0x00 will be "0", not "00"
-      fileList += String.fromCharCode(Buf.readUint16());
+      fileList += String.fromCharCode(this.context.Buf.readUint16());
     }
     return {
       fileList: fileList
     };
   },
 
   /**
    * Default Text.
@@ -10457,16 +10722,17 @@ let StkProactiveCmdHelper = {
    */
   retrieveEventList: function(length) {
     if (!length) {
       // null means an indication to ME to remove the existing list of events
       // in ME.
       return null;
     }
 
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let eventList = [];
     for (let i = 0; i < length; i++) {
       eventList.push(GsmPDUHelper.readHexOctet());
     }
     return {
       eventList: eventList
     };
   },
@@ -10476,32 +10742,33 @@ let StkProactiveCmdHelper = {
    *
    * | Byte  | Description          | Length |
    * |  1    | Timer Identifier Tag |   1    |
    * |  2    | Length = 01          |   1    |
    * |  3    | Timer Identifier     |   1    |
    */
   retrieveTimerId: function(length) {
     let id = {
-      timerId: GsmPDUHelper.readHexOctet()
+      timerId: this.context.GsmPDUHelper.readHexOctet()
     };
     return id;
   },
 
   /**
    * Timer Value.
    *
    * | Byte  | Description          | Length |
    * |  1    | Timer Value Tag      |   1    |
    * |  2    | Length = 03          |   1    |
    * |  3    | Hour                 |   1    |
    * |  4    | Minute               |   1    |
    * |  5    | Second               |   1    |
    */
   retrieveTimerValue: function(length) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let value = {
       timerValue: (GsmPDUHelper.readSwappedNibbleBcdNum(1) * 60 * 60) +
                   (GsmPDUHelper.readSwappedNibbleBcdNum(1) * 60) +
                   (GsmPDUHelper.readSwappedNibbleBcdNum(1))
     };
     return value;
   },
 
@@ -10521,16 +10788,17 @@ let StkProactiveCmdHelper = {
    *
    * | Byte      | Description         | Length |
    * |  1        | URL Tag             |   1    |
    * | 2 ~ (Y+1) | Length(X)           |   Y    |
    * | (Y+2) ~   | URL                 |   X    |
    * | (Y+1+X)   |                     |        |
    */
   retrieveUrl: function(length) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let s = "";
     for (let i = 0; i < length; i++) {
       s += String.fromCharCode(GsmPDUHelper.readHexOctet());
     }
     return {url: s};
   },
 
   /**
@@ -10538,16 +10806,17 @@ let StkProactiveCmdHelper = {
    *
    * | Byte  | Description      | Length |
    * |  1    | Next Action tag  |   1    |
    * |  1    | Length(X)        |   1    |
    * |  3~   | Next Action List |   X    |
    * | 3+X-1 |                  |        |
    */
   retrieveNextActionList: function(length) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let nextActionList = [];
     for (let i = 0; i < length; i++) {
       nextActionList.push(GsmPDUHelper.readHexOctet());
     }
     return nextActionList;
   },
 
   searchForTag: function(tag, ctlvs) {
@@ -10559,76 +10828,83 @@ let StkProactiveCmdHelper = {
     for (let [index, ctlv] in iter) {
       if ((ctlv.tag & ~COMPREHENSIONTLV_FLAG_CR) == tag) {
         return ctlv;
       }
     }
     return null;
   },
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_COMMAND_DETAILS] = function COMPREHENSIONTLV_TAG_COMMAND_DETAILS(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_COMMAND_DETAILS] = function COMPREHENSIONTLV_TAG_COMMAND_DETAILS(length) {
   return this.retrieveCommandDetails(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_DEVICE_ID] = function COMPREHENSIONTLV_TAG_DEVICE_ID(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_DEVICE_ID] = function COMPREHENSIONTLV_TAG_DEVICE_ID(length) {
   return this.retrieveDeviceId(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_ALPHA_ID] = function COMPREHENSIONTLV_TAG_ALPHA_ID(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ALPHA_ID] = function COMPREHENSIONTLV_TAG_ALPHA_ID(length) {
   return this.retrieveAlphaId(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_DURATION] = function COMPREHENSIONTLV_TAG_DURATION(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_DURATION] = function COMPREHENSIONTLV_TAG_DURATION(length) {
   return this.retrieveDuration(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_ADDRESS] = function COMPREHENSIONTLV_TAG_ADDRESS(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ADDRESS] = function COMPREHENSIONTLV_TAG_ADDRESS(length) {
   return this.retrieveAddress(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_TEXT_STRING] = function COMPREHENSIONTLV_TAG_TEXT_STRING(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TEXT_STRING] = function COMPREHENSIONTLV_TAG_TEXT_STRING(length) {
   return this.retrieveTextString(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_TONE] = function COMPREHENSIONTLV_TAG_TONE(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TONE] = function COMPREHENSIONTLV_TAG_TONE(length) {
   return this.retrieveTone(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_ITEM] = function COMPREHENSIONTLV_TAG_ITEM(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ITEM] = function COMPREHENSIONTLV_TAG_ITEM(length) {
   return this.retrieveItem(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_ITEM_ID] = function COMPREHENSIONTLV_TAG_ITEM_ID(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_ITEM_ID] = function COMPREHENSIONTLV_TAG_ITEM_ID(length) {
   return this.retrieveItemId(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_RESPONSE_LENGTH] = function COMPREHENSIONTLV_TAG_RESPONSE_LENGTH(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_RESPONSE_LENGTH] = function COMPREHENSIONTLV_TAG_RESPONSE_LENGTH(length) {
   return this.retrieveResponseLength(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_FILE_LIST] = function COMPREHENSIONTLV_TAG_FILE_LIST(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_FILE_LIST] = function COMPREHENSIONTLV_TAG_FILE_LIST(length) {
   return this.retrieveFileList(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_DEFAULT_TEXT] = function COMPREHENSIONTLV_TAG_DEFAULT_TEXT(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_DEFAULT_TEXT] = function COMPREHENSIONTLV_TAG_DEFAULT_TEXT(length) {
   return this.retrieveDefaultText(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_EVENT_LIST] = function COMPREHENSIONTLV_TAG_EVENT_LIST(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_EVENT_LIST] = function COMPREHENSIONTLV_TAG_EVENT_LIST(length) {
   return this.retrieveEventList(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER] = function COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER] = function COMPREHENSIONTLV_TAG_TIMER_IDENTIFIER(length) {
   return this.retrieveTimerId(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_TIMER_VALUE] = function COMPREHENSIONTLV_TAG_TIMER_VALUE(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_TIMER_VALUE] = function COMPREHENSIONTLV_TAG_TIMER_VALUE(length) {
   return this.retrieveTimerValue(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE] = function COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE] = function COMPREHENSIONTLV_TAG_IMMEDIATE_RESPONSE(length) {
   return this.retrieveImmediaResponse(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_URL] = function COMPREHENSIONTLV_TAG_URL(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_URL] = function COMPREHENSIONTLV_TAG_URL(length) {
   return this.retrieveUrl(length);
 };
-StkProactiveCmdHelper[COMPREHENSIONTLV_TAG_NEXT_ACTION_IND] = function COMPREHENSIONTLV_TAG_NEXT_ACTION_IND(length) {
+StkProactiveCmdHelperObject.prototype[COMPREHENSIONTLV_TAG_NEXT_ACTION_IND] = function COMPREHENSIONTLV_TAG_NEXT_ACTION_IND(length) {
   return this.retrieveNextActionList(length);
 };
 
-let ComprehensionTlvHelper = {
+function ComprehensionTlvHelperObject(aContext) {
+  this.context = aContext;
+}
+ComprehensionTlvHelperObject.prototype = {
+  context: null,
+
   /**
    * Decode raw data to a Comprehension-TLV.
    */
   decode: function() {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     let hlen = 0; // For header(tag field + length field) length.
     let temp = GsmPDUHelper.readHexOctet();
     hlen++;
 
     // TS 101.220, clause 7.1.1
     let tag, cr;
     switch (temp) {
       // TS 101.220, clause 7.1.1
@@ -10692,17 +10968,17 @@ let ComprehensionTlvHelper = {
       }
     } else {
       throw new Error("Invalid octet in Comprehension TLV :" + temp);
     }
 
     let ctlv = {
       tag: tag,
       length: length,
-      value: StkProactiveCmdHelper.retrieve(tag, length),
+      value: this.context.StkProactiveCmdHelper.retrieve(tag, length),
       cr: cr,
       hlen: hlen
     };
     return ctlv;
   },
 
   decodeChunks: function(length) {
     let chunks = [];
@@ -10717,16 +10993,18 @@ let ComprehensionTlvHelper = {
   },
 
   /**
    * Write Location Info Comprehension TLV.
    *
    * @param loc location Information.
    */
   writeLocationInfoTlv: function(loc) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_LOCATION_INFO |
                                COMPREHENSIONTLV_FLAG_CR);
     GsmPDUHelper.writeHexOctet(loc.gsmCellId > 0xffff ? 9 : 7);
     // From TS 11.14, clause 12.19
     // "The mobile country code (MCC), the mobile network code (MNC),
     // the location area code (LAC) and the cell ID are
     // coded as in TS 04.08."
     // And from TS 04.08 and TS 24.008,
@@ -10776,16 +11054,18 @@ let ComprehensionTlvHelper = {
 
   /**
    * Given a geckoError string, this function translates it into cause value
    * and write the value into buffer.
    *
    * @param geckoError Error string that is passed to gecko.
    */
   writeCauseTlv: function(geckoError) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     let cause = -1;
     for (let errorNo in RIL_ERROR_TO_GECKO_ERROR) {
       if (geckoError == RIL_ERROR_TO_GECKO_ERROR[errorNo]) {
         cause = errorNo;
         break;
       }
     }
     cause = (cause == -1) ? ERROR_SUCCESS : cause;
@@ -10800,22 +11080,26 @@ let ComprehensionTlvHelper = {
     // TS 04.08, clause 10.5.4.11: ext bit = 1 + 7 bits for cause.
     // +-----------------+----------------------------------+
     // | Ext = 1 (1 bit) |          Cause (7 bits)          |
     // +-----------------+----------------------------------+
     GsmPDUHelper.writeHexOctet(0x80 | cause);
   },
 
   writeDateTimeZoneTlv: function(date) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_DATE_TIME_ZONE);
     GsmPDUHelper.writeHexOctet(7);
     GsmPDUHelper.writeTimestamp(date);
   },
 
   writeLanguageTlv: function(language) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_LANGUAGE);
     GsmPDUHelper.writeHexOctet(2);
 
     // ISO 639-1, Alpha-2 code
     // TS 123.038, clause 6.2.1, GSM 7 bit Default Alphabet
     GsmPDUHelper.writeHexOctet(
       PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT].indexOf(language[0]));
     GsmPDUHelper.writeHexOctet(
@@ -10824,16 +11108,18 @@ let ComprehensionTlvHelper = {
 
   /**
    * Write Timer Value Comprehension TLV.
    *
    * @param seconds length of time during of the timer.
    * @param cr Comprehension Required or not
    */
   writeTimerValueTlv: function(seconds, cr) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     GsmPDUHelper.writeHexOctet(COMPREHENSIONTLV_TAG_TIMER_VALUE |
                                (cr ? COMPREHENSIONTLV_FLAG_CR : 0));
     GsmPDUHelper.writeHexOctet(3);
 
     // TS 102.223, clause 8.38
     // +----------------+------------------+-------------------+
     // | hours (1 byte) | minutes (1 btye) | secounds (1 byte) |
     // +----------------+------------------+-------------------+
@@ -10850,16 +11136,18 @@ let ComprehensionTlvHelper = {
     } else if (length >= 0x80) {
       return 2; // 0x81, len
     } else {
       return 1; // len
     }
   },
 
   writeLength: function(length) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     // TS 101.220 clause 7.1.2, Length Encoding.
     // Length   |  Byte 1  | Byte 2 | Byte 3 | Byte 4 |
     // 0 - 127  |  00 - 7f | N/A    | N/A    | N/A    |
     // 128-255  |  81      | 80 - ff| N/A    | N/A    |
     // 256-65535|  82      | 0100 - ffff     | N/A    |
     // 65536-   |  83      |     010000 - ffffff      |
     // 16777215
     if (length < 0x80) {
@@ -10877,24 +11165,31 @@ let ComprehensionTlvHelper = {
       GsmPDUHelper.writeHexOctet((length >> 8) & 0xff);
       GsmPDUHelper.writeHexOctet(length & 0xff);
     } else {
       throw new Error("Invalid length value :" + length);
     }
   },
 };
 
-let BerTlvHelper = {
+function BerTlvHelperObject(aContext) {
+  this.context = aContext;
+}
+BerTlvHelperObject.prototype = {
+  context: null,
+
   /**
    * Decode Ber TLV.
    *
    * @param dataLen
    *        The length of data in bytes.
    */
   decode: function(dataLen) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     let hlen = 0;
     let tag = GsmPDUHelper.readHexOctet();
     hlen++;
 
     // The length is coded onto 1 or 2 bytes.
     // Length    | Byte 1                | Byte 2
     // 0 - 127   | length ('00' to '7f') | N/A
     // 128 - 255 | '81'                  | length ('80' to 'ff')
@@ -10945,24 +11240,25 @@ let BerTlvHelper = {
 
   /**
    * Process the value part for proactive command TLV.
    *
    * @param length
    *        The length of data in bytes.
    */
   processProactiveCommand: function(length) {
-    let ctlvs = ComprehensionTlvHelper.decodeChunks(length);
+    let ctlvs = this.context.ComprehensionTlvHelper.decodeChunks(length);
     return ctlvs;
   },
 
   /**
    * Decode raw data to a Ber-TLV.
    */
   decodeInnerTlv: function() {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let tag = GsmPDUHelper.readHexOctet();
     let length = GsmPDUHelper.readHexOctet();
     return {
       tag: tag,
       length: length,
       value: this.retrieve(tag, length)
     };
   },
@@ -10981,34 +11277,36 @@ let BerTlvHelper = {
     }
     return chunks;
   },
 
   retrieve: function(tag, length) {
     let method = this[tag];
     if (typeof method != "function") {
       if (DEBUG) {
-        debug("Unknown Ber tag : 0x" + tag.toString(16));
-      }
+        this.context.debug("Unknown Ber tag : 0x" + tag.toString(16));
+      }
+      let Buf = this.context.Buf;
       Buf.seekIncoming(length * Buf.PDU_HEX_OCTET_SIZE);
       return null;
     }
     return method.call(this, length);
   },
 
   /**
    * File Size Data.
    *
    * | Byte        | Description                                | Length |
    * |  1          | Tag                                        |   1    |
    * |  2          | Length                                     |   1    |
    * |  3 to X+24  | Number of allocated data bytes in the file |   X    |
    * |             | , excluding structural information         |        |
    */
   retrieveFileSizeData: function(length) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let fileSizeData = 0;
     for (let i = 0; i < length; i++) {
       fileSizeData = fileSizeData << 8;
       fileSizeData += GsmPDUHelper.readHexOctet();
     }
 
     return {fileSizeData: fileSizeData};
   },
@@ -11020,16 +11318,17 @@ let BerTlvHelper = {
    * |  1      | Tag                   |   1    |
    * |  2      | Length                |   1    |
    * |  3      | File descriptor byte  |   1    |
    * |  4      | Data coding byte      |   1    |
    * |  5 ~ 6  | Record length         |   2    |
    * |  7      | Number of records     |   1    |
    */
   retrieveFileDescriptor: function(length) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let fileDescriptorByte = GsmPDUHelper.readHexOctet();
     let dataCodingByte = GsmPDUHelper.readHexOctet();
     // See TS 102 221 Table 11.5, we only care the least 3 bits for the
     // structure of file.
     let fileStructure = fileDescriptorByte & 0x07;
 
     let fileDescriptor = {
       fileStructure: fileStructure
@@ -11050,49 +11349,55 @@ let BerTlvHelper = {
    * File identifier.
    *
    * | Byte    | Description      | Length |
    * |  1      | Tag              |   1    |
    * |  2      | Length           |   1    |
    * |  3 ~ 4  | File identifier  |   2    |
    */
   retrieveFileIdentifier: function(length) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     return {fileId : (GsmPDUHelper.readHexOctet() << 8) +
                       GsmPDUHelper.readHexOctet()};
   },
 
   searchForNextTag: function(tag, iter) {
     for (let [index, tlv] in iter) {
       if (tlv.tag === tag) {
         return tlv;
       }
     }
     return null;
   }
 };
-BerTlvHelper[BER_FCP_TEMPLATE_TAG] = function BER_FCP_TEMPLATE_TAG(length) {
+BerTlvHelperObject.prototype[BER_FCP_TEMPLATE_TAG] = function BER_FCP_TEMPLATE_TAG(length) {
   return this.processFcpTemplate(length);
 };
-BerTlvHelper[BER_PROACTIVE_COMMAND_TAG] = function BER_PROACTIVE_COMMAND_TAG(length) {
+BerTlvHelperObject.prototype[BER_PROACTIVE_COMMAND_TAG] = function BER_PROACTIVE_COMMAND_TAG(length) {
   return this.processProactiveCommand(length);
 };
-BerTlvHelper[BER_FCP_FILE_SIZE_DATA_TAG] = function BER_FCP_FILE_SIZE_DATA_TAG(length) {
+BerTlvHelperObject.prototype[BER_FCP_FILE_SIZE_DATA_TAG] = function BER_FCP_FILE_SIZE_DATA_TAG(length) {
   return this.retrieveFileSizeData(length);
 };
-BerTlvHelper[BER_FCP_FILE_DESCRIPTOR_TAG] = function BER_FCP_FILE_DESCRIPTOR_TAG(length) {
+BerTlvHelperObject.prototype[BER_FCP_FILE_DESCRIPTOR_TAG] = function BER_FCP_FILE_DESCRIPTOR_TAG(length) {
   return this.retrieveFileDescriptor(length);
 };
-BerTlvHelper[BER_FCP_FILE_IDENTIFIER_TAG] = function BER_FCP_FILE_IDENTIFIER_TAG(length) {
+BerTlvHelperObject.prototype[BER_FCP_FILE_IDENTIFIER_TAG] = function BER_FCP_FILE_IDENTIFIER_TAG(length) {
   return this.retrieveFileIdentifier(length);
 };
 
 /**
  * ICC Helper for getting EF path.
  */
-let ICCFileHelper = {
+function ICCFileHelperObject(aContext) {
+  this.context = aContext;
+}
+ICCFileHelperObject.prototype = {
+  context: null,
+
   /**
    * This function handles only EFs that are common to RUIM, SIM, USIM
    * and other types of ICC cards.
    */
   getCommonEFPath: function(fileId) {
     switch (fileId) {
       case ICC_EF_ICCID:
         return EF_PATH_MF_SIM;
@@ -11181,85 +11486,91 @@ let ICCFileHelper = {
    * Helper function for getting the pathId for the specific ICC record
    * depeding on which type of ICC card we are using.
    *
    * @param fileId
    *        File id.
    * @return The pathId or null in case of an error or invalid input.
    */
   getEFPath: function(fileId) {
-    if (RIL.appType == null) {
+    let appType = this.context.RIL.appType;
+    if (appType == null) {
       return null;
     }
 
     let path = this.getCommonEFPath(fileId);
     if (path) {
       return path;
     }
 
-    switch (RIL.appType) {
+    switch (appType) {
       case CARD_APPTYPE_SIM:
         return this.getSimEFPath(fileId);
       case CARD_APPTYPE_USIM:
         return this.getUSimEFPath(fileId);
       case CARD_APPTYPE_RUIM:
         return this.getRuimEFPath(fileId);
       default:
         return null;
     }
   }
 };
 
 /**
  * Helper for ICC IO functionalities.
  */
-let ICCIOHelper = {
+function ICCIOHelperObject(aContext) {
+  this.context = aContext;
+}
+ICCIOHelperObject.prototype = {
+  context: null,
+
   /**
    * Load EF with type 'Linear Fixed'.
    *
    * @param fileId
    *        The file to operate on, one of the ICC_EF_* constants.
    * @param recordNumber [optional]
    *        The number of the record shall be loaded.
    * @param recordSize [optional]
    *        The size of the record.
    * @param callback [optional]
    *        The callback function shall be called when the record(s) is read.
    * @param onerror [optional]
    *        The callback function shall be called when failure.
    */
   loadLinearFixedEF: function(options) {
     let cb;
-    function readRecord(options) {
+    let readRecord = (function(options) {
       options.command = ICC_COMMAND_READ_RECORD;
       options.p1 = options.recordNumber || 1; // Record number
       options.p2 = READ_RECORD_ABSOLUTE_MODE;
       options.p3 = options.recordSize;
       options.callback = cb || options.callback;
-      RIL.iccIO(options);
-    }
+      this.context.RIL.iccIO(options);
+    }).bind(this);
 
     options.type = EF_TYPE_LINEAR_FIXED;
-    options.pathId = ICCFileHelper.getEFPath(options.fileId);
+    options.pathId = this.context.ICCFileHelper.getEFPath(options.fileId);
     if (options.recordSize) {
       readRecord(options);
       return;
     }
 
     cb = options.callback;
-    options.callback = readRecord.bind(this);
+    options.callback = readRecord;
     this.getResponse(options);
   },
 
   /**
    * Load next record from current record Id.
    */
   loadNextRecord: function(options) {
     options.p1++;
-    RIL.iccIO(options);
+    this.context.RIL.iccIO(options);
   },
 
   /**
    * Update EF with type 'Linear Fixed'.
    *
    * @param fileId
    *        The file to operate on, one of the ICC_EF_* constants.
    * @param recordNumber
@@ -11275,25 +11586,25 @@ let ICCIOHelper = {
    */
   updateLinearFixedEF: function(options) {
     if (!options.fileId || !options.recordNumber) {
       throw new Error("Unexpected fileId " + options.fileId +
                       " or recordNumber " + options.recordNumber);
     }
 
     options.type = EF_TYPE_LINEAR_FIXED;
-    options.pathId = ICCFileHelper.getEFPath(options.fileId);
+    options.pathId = this.context.ICCFileHelper.getEFPath(options.fileId);
     let cb = options.callback;
     options.callback = function callback(options) {
       options.callback = cb;
       options.command = ICC_COMMAND_UPDATE_RECORD;
       options.p1 = options.recordNumber;
       options.p2 = READ_RECORD_ABSOLUTE_MODE;
       options.p3 = options.recordSize;
-      RIL.iccIO(options);
+      this.context.RIL.iccIO(options);
     }.bind(this);
     this.getResponse(options);
   },
 
   /**
    * Load EF with type 'Transparent'.
    *
    * @param fileId
@@ -11305,54 +11616,56 @@ let ICCIOHelper = {
    */
   loadTransparentEF: function(options) {
     options.type = EF_TYPE_TRANSPARENT;
     let cb = options.callback;
     options.callback = function callback(options) {
       options.callback = cb;
       options.command = ICC_COMMAND_READ_BINARY;
       options.p3 = options.fileSize;
-      RIL.iccIO(options);
+      this.context.RIL.iccIO(options);
     }.bind(this);
     this.getResponse(options);
   },
 
   /**
    * Use ICC_COMMAND_GET_RESPONSE to query the EF.
    *
    * @param fileId
    *        The file to operate on, one of the ICC_EF_* constants.
    */
   getResponse: function(options) {
     options.command = ICC_COMMAND_GET_RESPONSE;
-    options.pathId = options.pathId || ICCFileHelper.getEFPath(options.fileId);
+    options.pathId = options.pathId ||
+                     this.context.ICCFileHelper.getEFPath(options.fileId);
     if (!options.pathId) {
       throw new Error("Unknown pathId for " + options.fileId.toString(16));
     }
     options.p1 = 0; // For GET_RESPONSE, p1 = 0
     options.p2 = 0; // For GET_RESPONSE, p2 = 0
     options.p3 = GET_RESPONSE_EF_SIZE_BYTES;
-    RIL.iccIO(options);
+    this.context.RIL.iccIO(options);
   },
 
   /**
    * Process ICC I/O response.
    */
   processICCIO: function(options) {
     let func = this[options.command];
     func.call(this, options);
   },
 
   /**
    * Process a ICC_COMMAND_GET_RESPONSE type command for REQUEST_SIM_IO.
    */
   processICCIOGetResponse: function(options) {
+    let Buf = this.context.Buf;
     let strLen = Buf.readInt32();
 
-    let peek = GsmPDUHelper.readHexOctet();
+    let peek = this.context.GsmPDUHelper.readHexOctet();
     Buf.seekIncoming(-1 * Buf.PDU_HEX_OCTET_SIZE);
     if (peek === BER_FCP_TEMPLATE_TAG) {
       this.processUSimGetResponse(options, strLen / 2);
     } else {
       this.processSimGetResponse(options);
     }
     Buf.readStringDelimiter(strLen);
 
@@ -11360,16 +11673,18 @@ let ICCIOHelper = {
       options.callback(options);
     }
   },
 
   /**
    * Helper function for processing USIM get response.
    */
   processUSimGetResponse: function(options, octetLen) {
+    let BerTlvHelper = this.context.BerTlvHelper;
+
     let berTlv = BerTlvHelper.decode(octetLen);
     // See TS 102 221 Table 11.4 for the content order of getResponse.
     let iter = Iterator(berTlv.value);
     let tlv = BerTlvHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG,
                                             iter);
     if (!tlv || (tlv.value.fileStructure !== UICC_EF_STRUCTURE[options.type])) {
       throw new Error("Expected EF type " + UICC_EF_STRUCTURE[options.type] +
                       " but read " + tlv.value.fileStructure);
@@ -11393,16 +11708,19 @@ let ICCIOHelper = {
     }
     options.fileSize = tlv.value.fileSizeData;
   },
 
   /**
    * Helper function for processing SIM get response.
    */
   processSimGetResponse: function(options) {
+    let Buf = this.context.Buf;
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     // The format is from TS 51.011, clause 9.2.1
 
     // Skip RFU, data[0] data[1].
     Buf.seekIncoming(2 * Buf.PDU_HEX_OCTET_SIZE);
 
     // File size, data[2], data[3]
     options.fileSize = (GsmPDUHelper.readHexOctet() << 8) |
                         GsmPDUHelper.readHexOctet();
@@ -11482,97 +11800,112 @@ let ICCIOHelper = {
       // description.
       let errorMsg = "ICC I/O Error code " + requestError +
                      " EF id = " + options.fileId.toString(16) +
                      " command = " + options.command.toString(16);
       if (options.sw1 && options.sw2) {
         errorMsg += "(" + options.sw1.toString(16) +
                     "/" + options.sw2.toString(16) + ")";
       }
-      debug(errorMsg);
+      this.context.debug(errorMsg);
     }
     onerror(requestError);
   },
 };
-ICCIOHelper[ICC_COMMAND_SEEK] = null;
-ICCIOHelper[ICC_COMMAND_READ_BINARY] = function ICC_COMMAND_READ_BINARY(options) {
+ICCIOHelperObject.prototype[ICC_COMMAND_SEEK] = null;
+ICCIOHelperObject.prototype[ICC_COMMAND_READ_BINARY] = function ICC_COMMAND_READ_BINARY(options) {
   this.processICCIOReadBinary(options);
 };
-ICCIOHelper[ICC_COMMAND_READ_RECORD] = function ICC_COMMAND_READ_RECORD(options) {
+ICCIOHelperObject.prototype[ICC_COMMAND_READ_RECORD] = function ICC_COMMAND_READ_RECORD(options) {
   this.processICCIOReadRecord(options);
 };
-ICCIOHelper[ICC_COMMAND_GET_RESPONSE] = function ICC_COMMAND_GET_RESPONSE(options) {
+ICCIOHelperObject.prototype[ICC_COMMAND_GET_RESPONSE] = function ICC_COMMAND_GET_RESPONSE(options) {
   this.processICCIOGetResponse(options);
 };
-ICCIOHelper[ICC_COMMAND_UPDATE_BINARY] = null;
-ICCIOHelper[ICC_COMMAND_UPDATE_RECORD] = function ICC_COMMAND_UPDATE_RECORD(options) {
+ICCIOHelperObject.prototype[ICC_COMMAND_UPDATE_BINARY] = null;
+ICCIOHelperObject.prototype[ICC_COMMAND_UPDATE_RECORD] = function ICC_COMMAND_UPDATE_RECORD(options) {
   this.processICCIOUpdateRecord(options);
 };
 
 /**
  * Helper for ICC records.
  */
-let ICCRecordHelper = {
+function ICCRecordHelperObject(aContext) {
+  this.context = aContext;
+}
+ICCRecordHelperObject.prototype = {
+  context: null,
+
   /**
    * Fetch ICC records.
    */
   fetchICCRecords: function() {
-    switch (RIL.appType) {
+    switch (this.context.RIL.appType) {
       case CARD_APPTYPE_SIM:
       case CARD_APPTYPE_USIM:
-        SimRecordHelper.fetchSimRecords();
+        this.context.SimRecordHelper.fetchSimRecords();
         break;
       case CARD_APPTYPE_RUIM:
-        RuimRecordHelper.fetchRuimRecords();
+        this.context.RuimRecordHelper.fetchRuimRecords();
         break;
     }
   },
 
   /**
    * Read the ICCID.
    */
   readICCID: function() {
     function callback() {
+      let Buf = this.context.Buf;
+      let RIL = this.context.RIL;
+
       let strLen = Buf.readInt32();
       let octetLen = strLen / 2;
-      RIL.iccInfo.iccid = GsmPDUHelper.readSwappedNibbleBcdString(octetLen);
+      RIL.iccInfo.iccid =
+        this.context.GsmPDUHelper.readSwappedNibbleBcdString(octetLen);
       Buf.readStringDelimiter(strLen);
 
-      if (DEBUG) debug("ICCID: " + RIL.iccInfo.iccid);
+      if (DEBUG) this.context.debug("ICCID: " + RIL.iccInfo.iccid);
       if (RIL.iccInfo.iccid) {
-        ICCUtilsHelper.handleICCInfoChange();
+        this.context.ICCUtilsHelper.handleICCInfoChange();
         RIL.reportStkServiceIsRunning();
       }
     }
 
-    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_ICCID,
-                                   callback: callback.bind(this)});
+    this.context.ICCIOHelper.loadTransparentEF({
+      fileId: ICC_EF_ICCID,
+      callback: callback.bind(this)
+    });
   },
 
   /**
    * Read ICC ADN like EF, i.e. EF_ADN, EF_FDN.
    *
    * @param fileId      EF id of the ADN or FDN.
    * @param onsuccess   Callback to be called when success.
    * @param onerror     Callback to be called when error.
    */
   readADNLike: function(fileId, onsuccess, onerror) {
+    let ICCIOHelper = this.context.ICCIOHelper;
+
     function callback(options) {
-      let contact = ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
+      let contact =
+        this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
       if (contact) {
         contact.recordId = options.p1;
         contacts.push(contact);
       }
 
       if (options.p1 < options.totalRecords) {
         ICCIOHelper.loadNextRecord(options);
       } else {
         if (DEBUG) {
           for (let i = 0; i < contacts.length; i++) {
-            debug("contact [" + i + "] " + JSON.stringify(contacts[i]));
+            this.context.debug("contact [" + i + "] " +
+                               JSON.stringify(contacts[i]));
           }
         }
         if (onsuccess) {
           onsuccess(contacts);
         }
       }
     }
 
@@ -11588,48 +11921,55 @@ let ICCRecordHelper = {
    * @param fileId      EF id of the ADN or FDN.
    * @param contact     The contact will be updated. (Shall have recordId property)
    * @param pin2        PIN2 is required when updating ICC_EF_FDN.
    * @param onsuccess   Callback to be called when success.
    * @param onerror     Callback to be called when error.
    */
   updateADNLike: function(fileId, contact, pin2, onsuccess, onerror) {
     function dataWriter(recordSize) {
-      ICCPDUHelper.writeAlphaIdDiallingNumber(recordSize,
-                                              contact.alphaId,
-                                              contact.number);
+      this.context.ICCPDUHelper.writeAlphaIdDiallingNumber(recordSize,
+                                                           contact.alphaId,
+                                                           contact.number);
     }
 
     function callback(options) {
       if (onsuccess) {
         onsuccess();
       }
     }
 
     if (!contact || !contact.recordId) {
-      let error = onerror || debug;
-      error(GECKO_ERROR_INVALID_PARAMETER);
+      if (onerror) onerror(GECKO_ERROR_INVALID_PARAMETER);
       return;
     }
 
-    ICCIOHelper.updateLinearFixedEF({fileId: fileId,
-                                     recordNumber: contact.recordId,
-                                     dataWriter: dataWriter.bind(this),
-                                     pin2: pin2,
-                                     callback: callback.bind(this),
-                                     onerror: onerror});
+    this.context.ICCIOHelper.updateLinearFixedEF({
+      fileId: fileId,
+      recordNumber: contact.recordId,
+      dataWriter: dataWriter.bind(this),
+      pin2: pin2,
+      callback: callback.bind(this),
+      onerror: onerror
+    });
   },
 
   /**
    * Read USIM/RUIM Phonebook.
    *
    * @param onsuccess   Callback to be called when success.
    * @param onerror     Callback to be called when error.
    */
   readPBR: function(onsuccess, onerror) {
+    let Buf = this.context.Buf;
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+    let ICCIOHelper = this.context.ICCIOHelper;
+    let ICCUtilsHelper = this.context.ICCUtilsHelper;
+    let RIL = this.context.RIL;
+
     function callback(options) {
       let strLen = Buf.readInt32();
       let octetLen = strLen / 2, readLen = 0;
 
       let pbrTlvs = [];
       while (readLen < octetLen) {
         let tag = GsmPDUHelper.readHexOctet();
         if (tag == 0xff) {
@@ -11647,18 +11987,17 @@ let ICCRecordHelper = {
         readLen += tlvLen + 2; // +2 for tag and tlvLen
       }
       Buf.readStringDelimiter(strLen);
 
       if (pbrTlvs.length > 0) {
         let pbr = ICCUtilsHelper.parsePbrTlvs(pbrTlvs);
         // EF_ADN is mandatory if and only if DF_PHONEBOOK is present.
         if (!pbr.adn) {
-          let error = onerror || debug;
-          error("Cannot access ADN.");
+          if (onerror) onerror("Cannot access ADN.");
           return;
         }
         pbrs.push(pbr);
       }
 
       if (options.p1 < options.totalRecords) {
         ICCIOHelper.loadNextRecord(options);
       } else {
@@ -11692,64 +12031,72 @@ let ICCRecordHelper = {
    *
    * @param fileId       EF id of the IAP.
    * @param recordNumber The number of the record shall be loaded.
    * @param onsuccess    Callback to be called when success.
    * @param onerror      Callback to be called when error.
    */
   readIAP: function(fileId, recordNumber, onsuccess, onerror) {
     function callback(options) {
+      let Buf = this.context.Buf;
       let strLen = Buf.readInt32();
       let octetLen = strLen / 2;
       this._iapRecordSize = options.recordSize;
 
-      let iap = GsmPDUHelper.readHexOctetArray(octetLen);
+      let iap = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
       Buf.readStringDelimiter(strLen);
 
       if (onsuccess) {
         onsuccess(iap);
       }
     }
 
-    ICCIOHelper.loadLinearFixedEF({fileId: fileId,
-                                   recordNumber: recordNumber,
-                                   recordSize: this._iapRecordSize,
-                                   callback: callback.bind(this),
-                                   onerror: onerror});
+    this.context.ICCIOHelper.loadLinearFixedEF({
+      fileId: fileId,
+      recordNumber: recordNumber,
+      recordSize: this._iapRecordSize,
+      callback: callback.bind(this),
+      onerror: onerror
+    });
   },
 
   /**
    * Update USIM/RUIM Phonebook EF_IAP.
    *
    * @see TS 131.102, clause 4.4.2.13
    *
    * @param fileId       EF id of the IAP.
    * @param recordNumber The identifier of the record shall be updated.
    * @param iap          The IAP value to be written.
    * @param onsuccess    Callback to be called when success.
    * @param onerror      Callback to be called when error.
    */
   updateIAP: function(fileId, recordNumber, iap, onsuccess, onerror) {
     let dataWriter = function dataWriter(recordSize) {
+      let Buf = this.context.Buf;
+      let GsmPDUHelper = this.context.GsmPDUHelper;
+
       // Write String length
       let strLen = recordSize * 2;
       Buf.writeInt32(strLen);
 
       for (let i = 0; i < iap.length; i++) {
         GsmPDUHelper.writeHexOctet(iap[i]);
       }
 
       Buf.writeStringDelimiter(strLen);
     }.bind(this);
 
-    ICCIOHelper.updateLinearFixedEF({fileId: fileId,
-                                     recordNumber: recordNumber,
-                                     dataWriter: dataWriter,
-                                     callback: onsuccess,
-                                     onerror: onerror});
+    this.context.ICCIOHelper.updateLinearFixedEF({
+      fileId: fileId,
+      recordNumber: recordNumber,
+      dataWriter: dataWriter,
+      callback: onsuccess,
+      onerror: onerror
+    });
   },
 
   /**
    * Cache EF_Email record size.
    */
   _emailRecordSize: null,
 
   /**
@@ -11760,16 +12107,19 @@ let ICCRecordHelper = {
    * @param fileId       EF id of the EMAIL.
    * @param fileType     The type of the EMAIL, one of the ICC_USIM_TYPE* constants.
    * @param recordNumber The number of the record shall be loaded.
    * @param onsuccess    Callback to be called when success.
    * @param onerror      Callback to be called when error.
    */
   readEmail: function(fileId, fileType, recordNumber, onsuccess, onerror) {
     function callback(options) {
+      let Buf = this.context.Buf;
+      let ICCPDUHelper = this.context.ICCPDUHelper;
+
       let strLen = Buf.readInt32();
       let octetLen = strLen / 2;
       let email = null;
       this._emailRecordSize = options.recordSize;
 
       // Read contact's email
       //
       // | Byte     | Description                 | Length | M/O
@@ -11789,21 +12139,23 @@ let ICCRecordHelper = {
 
       Buf.readStringDelimiter(strLen);
 
       if (onsuccess) {
         onsuccess(email);
       }
     }
 
-    ICCIOHelper.loadLinearFixedEF({fileId: fileId,
-                                   recordNumber: recordNumber,
-                                   recordSize: this._emailRecordSize,
-                                   callback: callback.bind(this),
-                                   onerror: onerror});
+    this.context.ICCIOHelper.loadLinearFixedEF({
+      fileId: fileId,
+      recordNumber: recordNumber,
+      recordSize: this._emailRecordSize,
+      callback: callback.bind(this),
+      onerror: onerror
+    });
   },
 
   /**
    * Update USIM/RUIM Phonebook EF_EMAIL.
    *
    * @see TS 131.102, clause 4.4.2.13
    *
    * @param pbr          Phonebook Reference File.
@@ -11812,36 +12164,42 @@ let ICCRecordHelper = {
    * @param adnRecordId  The record Id of ADN, only needed if the fileType of Email is TYPE2.
    * @param onsuccess    Callback to be called when success.
    * @param onerror      Callback to be called when error.
    */
   updateEmail: function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
     let fileId = pbr[USIM_PBR_EMAIL].fileId;
     let fileType = pbr[USIM_PBR_EMAIL].fileType;
     let dataWriter = function dataWriter(recordSize) {
+      let Buf = this.context.Buf;
+      let GsmPDUHelper = this.context.GsmPDUHelper;
+      let ICCPDUHelper = this.context.ICCPDUHelper;
+
       // Write String length
       let strLen = recordSize * 2;
       Buf.writeInt32(strLen);
 
       if (fileType == ICC_USIM_TYPE1_TAG) {
         ICCPDUHelper.writeStringTo8BitUnpacked(recordSize, email);
       } else {
         ICCPDUHelper.writeStringTo8BitUnpacked(recordSize - 2, email);
         GsmPDUHelper.writeHexOctet(pbr.adn.sfi || 0xff);
         GsmPDUHelper.writeHexOctet(adnRecordId);
       }
 
       Buf.writeStringDelimiter(strLen);
     }.bind(this);
 
-    ICCIOHelper.updateLinearFixedEF({fileId: fileId,
-                                     recordNumber: recordNumber,
-                                     dataWriter: dataWriter,
-                                     callback: onsuccess,
-                                     onerror: onerror});
+    this.context.ICCIOHelper.updateLinearFixedEF({
+      fileId: fileId,
+      recordNumber: recordNumber,
+      dataWriter: dataWriter,
+      callback: onsuccess,
+      onerror: onerror
+    });
  },
 
   /**
    * Cache EF_ANR record size.
    */
   _anrRecordSize: null,
 
   /**
@@ -11852,24 +12210,25 @@ let ICCRecordHelper = {
    * @param fileId       EF id of the ANR.
    * @param fileType     One of the ICC_USIM_TYPE* constants.
    * @param recordNumber The number of the record shall be loaded.
    * @param onsuccess    Callback to be called when success.
    * @param onerror      Callback to be called when error.
    */
   readANR: function(fileId, fileType, recordNumber, onsuccess, onerror) {
     function callback(options) {
+      let Buf = this.context.Buf;
       let strLen = Buf.readInt32();
       let number = null;
       this._anrRecordSize = options.recordSize;
 
       // Skip EF_AAS Record ID.
       Buf.seekIncoming(1 * Buf.PDU_HEX_OCTET_SIZE);
 
-      number = ICCPDUHelper.readNumberWithLength();
+      number = this.context.ICCPDUHelper.readNumberWithLength();
 
       // Skip 2 unused octets, CCP and EXT1.
       Buf.seekIncoming(2 * Buf.PDU_HEX_OCTET_SIZE);
 
       // For Type 2 there are two extra octets.
       if (fileType == ICC_USIM_TYPE2_TAG) {
         // Skip 2 unused octets, ADN SFI and Record Identifier.
         Buf.seekIncoming(2 * Buf.PDU_HEX_OCTET_SIZE);
@@ -11877,21 +12236,23 @@ let ICCRecordHelper = {
 
       Buf.readStringDelimiter(strLen);
 
       if (onsuccess) {
         onsuccess(number);
       }
     }
 
-    ICCIOHelper.loadLinearFixedEF({fileId: fileId,
-                                   recordNumber: recordNumber,
-                                   recordSize: this._anrRecordSize,
-                                   callback: callback.bind(this),
-                                   onerror: onerror});
+    this.context.ICCIOHelper.loadLinearFixedEF({
+      fileId: fileId,
+      recordNumber: recordNumber,
+      recordSize: this._anrRecordSize,
+      callback: callback.bind(this),
+      onerror: onerror
+    });
   },
 
   /**
    * Update USIM/RUIM Phonebook EF_ANR.
    *
    * @see TS 131.102, clause 4.4.2.9
    *
    * @param pbr          Phonebook Reference File.
@@ -11900,54 +12261,64 @@ let ICCRecordHelper = {
    * @param adnRecordId  The record Id of ADN, only needed if the fileType of Email is TYPE2.
    * @param onsuccess    Callback to be called when success.
    * @param onerror      Callback to be called when error.
    */
   updateANR: function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
     let fileId = pbr[USIM_PBR_ANR0].fileId;
     let fileType = pbr[USIM_PBR_ANR0].fileType;
     let dataWriter = function dataWriter(recordSize) {
+      let Buf = this.context.Buf;
+      let GsmPDUHelper = this.context.GsmPDUHelper;
+
       // Write String length
       let strLen = recordSize * 2;
       Buf.writeInt32(strLen);
 
       // EF_AAS record Id. Unused for now.
       GsmPDUHelper.writeHexOctet(0xff);
 
-      ICCPDUHelper.writeNumberWithLength(number);
+      this.context.ICCPDUHelper.writeNumberWithLength(number);
 
       // Write unused octets 0xff, CCP and EXT1.
       GsmPDUHelper.writeHexOctet(0xff);
       GsmPDUHelper.writeHexOctet(0xff);
 
       // For Type 2 there are two extra octets.
       if (fileType == ICC_USIM_TYPE2_TAG) {
         GsmPDUHelper.writeHexOctet(pbr.adn.sfi || 0xff);
         GsmPDUHelper.writeHexOctet(adnRecordId);
       }
 
       Buf.writeStringDelimiter(strLen);
     }.bind(this);
 
-    ICCIOHelper.updateLinearFixedEF({fileId: fileId,
-                                     recordNumber: recordNumber,
-                                     dataWriter: dataWriter,
-                                     callback: onsuccess,
-                                     onerror: onerror});
+    this.context.ICCIOHelper.updateLinearFixedEF({
+      fileId: fileId,
+      recordNumber: recordNumber,
+      dataWriter: dataWriter,
+      callback: onsuccess,
+      onerror: onerror
+    });
   },
 
   /**
    * Find free record id.
    *
    * @param fileId      EF id.
    * @param onsuccess   Callback to be called when success.
    * @param onerror     Callback to be called when error.
    */
   findFreeRecordId: function(fileId, onsuccess, onerror) {
+    let ICCIOHelper = this.context.ICCIOHelper;
+
     function callback(options) {
+      let Buf = this.context.Buf;
+      let GsmPDUHelper = this.context.GsmPDUHelper;
+
       let strLen = Buf.readInt32();
       let octetLen = strLen / 2;
       let readLen = 0;
 
       while (readLen < octetLen) {
         let octet = GsmPDUHelper.readHexOctet();
         readLen++;
         if (octet != 0xff) {
@@ -11967,212 +12338,240 @@ let ICCRecordHelper = {
 
       Buf.readStringDelimiter(strLen);
 
       if (options.p1 < options.totalRecords) {
         ICCIOHelper.loadNextRecord(options);
       } else {
         // No free record found.
         if (DEBUG) {
-          debug(CONTACT_ERR_NO_FREE_RECORD_FOUND);
+          this.context.debug(CONTACT_ERR_NO_FREE_RECORD_FOUND);
         }
         onerror(CONTACT_ERR_NO_FREE_RECORD_FOUND);
       }
     }
 
     ICCIOHelper.loadLinearFixedEF({fileId: fileId,
                                    callback: callback.bind(this),
                                    onerror: onerror});
   },
 };
 
 /**
  * Helper for (U)SIM Records.
  */
-let SimRecordHelper = {
+function SimRecordHelperObject(aContext) {
+  this.context = aContext;
+}
+SimRecordHelperObject.prototype = {
+  context: null,
+
   /**
    * Fetch (U)SIM records.
    */
   fetchSimRecords: function() {
-    RIL.getIMSI();
+    this.context.RIL.getIMSI();
     this.readAD();
     this.readSST();
   },
 
   /**
    * Read EF_phase.
    * This EF is only available in SIM.
    */
   readSimPhase: function() {
     function callback() {
+      let Buf = this.context.Buf;
       let strLen = Buf.readInt32();
 
+      let GsmPDUHelper = this.context.GsmPDUHelper;
       let phase = GsmPDUHelper.readHexOctet();
       // If EF_phase is coded '03' or greater, an ME supporting STK shall
       // perform the PROFILE DOWNLOAD procedure.
       if (RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD &&
           phase >= ICC_PHASE_2_PROFILE_DOWNLOAD_REQUIRED) {
-        RIL.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
+        this.context.RIL.sendStkTerminalProfile(STK_SUPPORTED_TERMINAL_PROFILE);
       }
 
       Buf.readStringDelimiter(strLen);
     }
 
-    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_PHASE,
-                                   callback: callback.bind(this)});
+    this.context.ICCIOHelper.loadTransparentEF({
+      fileId: ICC_EF_PHASE,
+      callback: callback.bind(this)
+    });
   },
 
   /**
    * Read the MSISDN from the (U)SIM.
    */
   readMSISDN: function() {
     function callback(options) {
-      let contact = ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
+      let RIL = this.context.RIL;
+
+      let contact =
+        this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
       if (!contact ||
           (RIL.iccInfo.msisdn !== undefined &&
            RIL.iccInfo.msisdn === contact.number)) {
         return;
       }
       RIL.iccInfo.msisdn = contact.number;
-      if (DEBUG) debug("MSISDN: " + RIL.iccInfo.msisdn);
-      ICCUtilsHelper.handleICCInfoChange();
-    }
-
-    ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_MSISDN,
-                                   callback: callback.bind(this)});
+      if (DEBUG) this.context.debug("MSISDN: " + RIL.iccInfo.msisdn);
+      this.context.ICCUtilsHelper.handleICCInfoChange();
+    }
+
+    this.context.ICCIOHelper.loadLinearFixedEF({
+      fileId: ICC_EF_MSISDN,
+      callback: callback.bind(this)
+    });
   },
 
   /**
    * Read the AD (Administrative Data) from the (U)SIM.
    */
   readAD: function() {
     function callback() {
+      let Buf = this.context.Buf;
       let strLen = Buf.readInt32();
       // Each octet is encoded into two chars.
       let octetLen = strLen / 2;
-      let ad = GsmPDUHelper.readHexOctetArray(octetLen);
+      let ad = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
       Buf.readStringDelimiter(strLen);
 
       if (DEBUG) {
         let str = "";
         for (let i = 0; i < ad.length; i++) {
           str += ad[i] + ", ";
         }
-        debug("AD: " + str);
-      }
-
+        this.context.debug("AD: " + str);
+      }
+
+      let ICCUtilsHelper = this.context.ICCUtilsHelper;
+      let RIL = this.context.RIL;
       // The 4th byte of the response is the length of MNC.
       let mccMnc = ICCUtilsHelper.parseMccMncFromImsi(RIL.iccInfoPrivate.imsi,
                                                       ad && ad[3]);
       if (mccMnc) {
         RIL.iccInfo.mcc = mccMnc.mcc;
         RIL.iccInfo.mnc = mccMnc.mnc;
         ICCUtilsHelper.handleICCInfoChange();
       }
     }
 
-    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_AD,
-                                   callback: callback.bind(this)});
+    this.context.ICCIOHelper.loadTransparentEF({
+      fileId: ICC_EF_AD,
+      callback: callback.bind(this)
+    });
   },
 
   /**
    * Read the SPN (Service Provider Name) from the (U)SIM.
    */
   readSPN: function() {
     function callback() {
+      let Buf = this.context.Buf;
       let strLen = Buf.readInt32();
       // Each octet is encoded into two chars.
       let octetLen = strLen / 2;
-      let spnDisplayCondition = GsmPDUHelper.readHexOctet();
+      let spnDisplayCondition = this.context.GsmPDUHelper.readHexOctet();
       // Minus 1 because the first octet is used to store display condition.
-      let spn = ICCPDUHelper.readAlphaIdentifier(octetLen - 1);
+      let spn = this.context.ICCPDUHelper.readAlphaIdentifier(octetLen - 1);
       Buf.readStringDelimiter(strLen);
 
       if (DEBUG) {
-        debug("SPN: spn = " + spn +
-              ", spnDisplayCondition = " + spnDisplayCondition);
-      }
-
+        this.context.debug("SPN: spn = " + spn +
+                           ", spnDisplayCondition = " + spnDisplayCondition);
+      }
+
+      let RIL = this.context.RIL;
       RIL.iccInfoPrivate.spnDisplayCondition = spnDisplayCondition;
       RIL.iccInfo.spn = spn;
+      let ICCUtilsHelper = this.context.ICCUtilsHelper;
       ICCUtilsHelper.updateDisplayCondition();
       ICCUtilsHelper.handleICCInfoChange();
     }
 
-    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_SPN,
-                                   callback: callback.bind(this)});
+    this.context.ICCIOHelper.loadTransparentEF({
+      fileId: ICC_EF_SPN,
+      callback: callback.bind(this)
+    });
   },
 
   /**
    * Read the (U)SIM Service Table from the (U)SIM.
    */
   readSST: function() {
     function callback() {
+      let Buf = this.context.Buf;
+      let RIL = this.context.RIL;
+
       let strLen = Buf.readInt32();
       // Each octet is encoded into two chars.
       let octetLen = strLen / 2;
-      let sst = GsmPDUHelper.readHexOctetArray(octetLen);
+      let sst = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
       Buf.readStringDelimiter(strLen);
       RIL.iccInfoPrivate.sst = sst;
       if (DEBUG) {
         let str = "";
         for (let i = 0; i < sst.length; i++) {
           str += sst[i] + ", ";
         }
-        debug("SST: " + str);
-      }
-
+        this.context.debug("SST: " + str);
+      }
+
+      let ICCUtilsHelper = this.context.ICCUtilsHelper;
       if (ICCUtilsHelper.isICCServiceAvailable("MSISDN")) {
-        if (DEBUG) debug("MSISDN: MSISDN is available");
+        if (DEBUG) this.context.debug("MSISDN: MSISDN is available");
         this.readMSISDN();
       } else {
-        if (DEBUG) debug("MSISDN: MSISDN service is not available");
+        if (DEBUG) this.context.debug("MSISDN: MSISDN service is not available");
       }
 
       // Fetch SPN and PLMN list, if some of them are available.
       if (ICCUtilsHelper.isICCServiceAvailable("SPN")) {
-        if (DEBUG) debug("SPN: SPN is available");
+        if (DEBUG) this.context.debug("SPN: SPN is available");
         this.readSPN();
       } else {
-        if (DEBUG) debug("SPN: SPN service is not available");
+        if (DEBUG) this.context.debug("SPN: SPN service is not available");
       }
 
       if (ICCUtilsHelper.isICCServiceAvailable("MDN")) {
-        if (DEBUG) debug("MDN: MDN available.");
+        if (DEBUG) this.context.debug("MDN: MDN available.");
         this.readMBDN();
       } else {
-        if (DEBUG) debug("MDN: MDN service is not available");
+        if (DEBUG) this.context.debug("MDN: MDN service is not available");
       }
 
       if (ICCUtilsHelper.isICCServiceAvailable("MWIS")) {
-        if (DEBUG) debug("MWIS: MWIS is available");
+        if (DEBUG) this.context.debug("MWIS: MWIS is available");
         this.readMWIS();
       } else {
-        if (DEBUG) debug("MWIS: MWIS is not available");
+        if (DEBUG) this.context.debug("MWIS: MWIS is not available");
       }
 
       if (ICCUtilsHelper.isICCServiceAvailable("SPDI")) {
-        if (DEBUG) debug("SPDI: SPDI available.");
+        if (DEBUG) this.context.debug("SPDI: SPDI available.");
         this.readSPDI();
       } else {
-        if (DEBUG) debug("SPDI: SPDI service is not available");
+        if (DEBUG) this.context.debug("SPDI: SPDI service is not available");
       }
 
       if (ICCUtilsHelper.isICCServiceAvailable("PNN")) {
-        if (DEBUG) debug("PNN: PNN is available");
+        if (DEBUG) this.context.debug("PNN: PNN is available");
         this.readPNN();
       } else {
-        if (DEBUG) debug("PNN: PNN is not available");
+        if (DEBUG) this.context.debug("PNN: PNN is not available");
       }
 
       if (ICCUtilsHelper.isICCServiceAvailable("OPL")) {
-        if (DEBUG) debug("OPL: OPL is available");
+        if (DEBUG) this.context.debug("OPL: OPL is available");
         this.readOPL();
       } else {
-        if (DEBUG) debug("OPL: OPL is not available");
+        if (DEBUG) this.context.debug("OPL: OPL is not available");
       }
 
       if (ICCUtilsHelper.isICCServiceAvailable("CBMI")) {
         this.readCBMI();
       } else {
         RIL.cellBroadcastConfigs.CBMI = null;
       }
       if (ICCUtilsHelper.isICCServiceAvailable("DATA_DOWNLOAD_SMS_CB")) {
@@ -12184,56 +12583,66 @@ let SimRecordHelper = {
         this.readCBMIR();
       } else {
         RIL.cellBroadcastConfigs.CBMIR = null;
       }
       RIL._mergeAllCellBroadcastConfigs();
     }
 
     // ICC_EF_UST has the same value with ICC_EF_SST.
-    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_SST,
-                                   callback: callback.bind(this)});
+    this.context.ICCIOHelper.loadTransparentEF({
+      fileId: ICC_EF_SST,
+      callback: callback.bind(this)
+    });
   },
 
   /**
    * Read (U)SIM MBDN. (Mailbox Dialling Number)
    *
    * @see TS 131.102, clause 4.2.60
    */
   readMBDN: function() {
     function callback(options) {
-      let contact = ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
+      let RIL = this.context.RIL;
+      let contact =
+        this.context.ICCPDUHelper.readAlphaIdDiallingNumber(options.recordSize);
       if (!contact ||
           (RIL.iccInfoPrivate.mbdn !== undefined &&
            RIL.iccInfoPrivate.mbdn === contact.number)) {
         return;
       }
       RIL.iccInfoPrivate.mbdn = contact.number;
       if (DEBUG) {
-        debug("MBDN, alphaId="+contact.alphaId+" number="+contact.number);
+        this.context.debug("MBDN, alphaId=" + contact.alphaId +
+                           " number=" + contact.number);
       }
       contact.rilMessageType = "iccmbdn";
       RIL.sendChromeMessage(contact);
     }
 
-    ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_MBDN,
-                                   callback: callback.bind(this)});
+    this.context.ICCIOHelper.loadLinearFixedEF({
+      fileId: ICC_EF_MBDN,
+      callback: callback.bind(this)
+    });
   },
 
   /**
    * Read ICC MWIS. (Message Waiting Indication Status)
    *
    * @see TS 31.102, clause 4.2.63 for USIM and TS 51.011, clause 10.3.45 for SIM.
    */
   readMWIS: function() {
     function callback(options) {
+      let Buf = this.context.Buf;
+      let RIL = this.context.RIL;
+
       let strLen = Buf.readInt32();
       // Each octet is encoded into two chars.
       let octetLen = strLen / 2;
-      let mwis = GsmPDUHelper.readHexOctetArray(octetLen);
+      let mwis = this.context.GsmPDUHelper.readHexOctetArray(octetLen);
       Buf.readStringDelimiter(strLen);
       if (!mwis) {
         return;
       }
       RIL.iccInfoPrivate.mwis = mwis; //Keep raw MWIS for updateMWIS()
 
       let mwi = {};
       // b8 b7 B6 b5 b4 b3 b2 b1   4.2.63, TS 31.102 version 11.6.0
@@ -12259,68 +12668,80 @@ let SimRecordHelper = {
       } else {
         mwi.msgCount = 0;
       }
 
       RIL.sendChromeMessage({ rilMessageType: "iccmwis",
                               mwi: mwi });
     }
 
-    ICCIOHelper.loadLinearFixedEF({ fileId: ICC_EF_MWIS,
-                                    recordNumber: 1, // Get 1st Subscriber Profile.
-                                    callback: callback });
+    this.context.ICCIOHelper.loadLinearFixedEF({
+      fileId: ICC_EF_MWIS,
+      recordNumber: 1, // Get 1st Subscriber Profile.
+      callback: callback.bind(this)
+    });
   },
 
   /**
    * Update ICC MWIS. (Message Waiting Indication Status)
    *
    * @see TS 31.102, clause 4.2.63 for USIM and TS 51.011, clause 10.3.45 for SIM.
    */
   updateMWIS: function(mwi) {
+    let RIL = this.context.RIL;
     if (!RIL.iccInfoPrivate.mwis) {
       return;
     }
 
     function dataWriter(recordSize) {
       let mwis = RIL.iccInfoPrivate.mwis;
 
       let msgCount =
           (mwi.msgCount === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) ? 0 : mwi.msgCount;
 
       [mwis[0], mwis[1]] = (mwi.active) ? [(mwis[0] | 0x01), msgCount]
                                         : [(mwis[0] & 0xFE), 0];
 
       let strLen = recordSize * 2;
+      let Buf = this.context.Buf;
       Buf.writeInt32(strLen);
 
+      let GsmPDUHelper = this.context.GsmPDUHelper;
       for (let i = 0; i < mwis.length; i++) {
         GsmPDUHelper.writeHexOctet(mwis[i]);
       }
 
       Buf.writeStringDelimiter(strLen);
     }
 
-    ICCIOHelper.updateLinearFixedEF({ fileId: ICC_EF_MWIS,
-                                      recordNumber: 1, // Update 1st Subscriber Profile.
-                                      dataWriter: dataWriter });
+    this.context.ICCIOHelper.updateLinearFixedEF({
+      fileId: ICC_EF_MWIS,
+      recordNumber: 1, // Update 1st Subscriber Profile.
+      dataWriter: dataWriter.bind(this)
+    });
   },
 
   /**
    * Read the SPDI (Service Provider Display Information) from the (U)SIM.
    *
    * See TS 131.102 section 4.2.66 for USIM and TS 51.011 section 10.3.50
    * for SIM.
    */
   readSPDI: function() {
     function callback() {
+      let Buf = this.context.Buf;
       let strLen = Buf.readInt32();
       let octetLen = strLen / 2;
       let readLen = 0;
       let endLoop = false;
+
+      let RIL = this.context.RIL;
       RIL.iccInfoPrivate.SPDI = null;
+
+      let GsmPDUHelper = this.context.GsmPDUHelper;
       while ((readLen < octetLen) && !endLoop) {
         let tlvTag = GsmPDUHelper.readHexOctet();
         let tlvLen = GsmPDUHelper.readHexOctet();
         readLen += 2; // For tag and length fields.
         switch (tlvTag) {
         case SPDI_TAG_SPDI:
           // The value part itself is a TLV.
           continue;
@@ -12337,64 +12758,75 @@ let SimRecordHelper = {
           break;
         }
       }
 
       // Consume unread octets.
       Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
       Buf.readStringDelimiter(strLen);
 
-      if (DEBUG) debug("SPDI: " + JSON.stringify(RIL.iccInfoPrivate.SPDI));
+      if (DEBUG) {
+        this.context.debug("SPDI: " + JSON.stringify(RIL.iccInfoPrivate.SPDI));
+      }
+      let ICCUtilsHelper = this.context.ICCUtilsHelper;
       if (ICCUtilsHelper.updateDisplayCondition()) {
         ICCUtilsHelper.handleICCInfoChange();
       }
     }
 
     // PLMN List is Servive 51 in USIM, EF_SPDI
-    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_SPDI,
-                                   callback: callback.bind(this)});
+    this.context.ICCIOHelper.loadTransparentEF({
+      fileId: ICC_EF_SPDI,
+      callback: callback.bind(this)
+    });
   },
 
   _readCbmiHelper: function(which) {
+    let RIL = this.context.RIL;
+
     function callback() {
+      let Buf = this.context.Buf;
       let strLength = Buf.readInt32();
 
       // Each Message Identifier takes two octets and each octet is encoded
       // into two chars.
       let numIds = strLength / 4, list = null;
       if (numIds) {
         list = [];
+        let GsmPDUHelper = this.context.GsmPDUHelper;
         for (let i = 0, id; i < numIds; i++) {
           id = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
           // `Unused entries shall be set to 'FF FF'.`
           if (id != 0xFFFF) {
             list.push(id);
             list.push(id + 1);
           }
         }
       }
       if (DEBUG) {
-        debug(which + ": " + JSON.stringify(list));
+        this.context.debug(which + ": " + JSON.stringify(list));
       }
 
       Buf.readStringDelimiter(strLength);
 
       RIL.cellBroadcastConfigs[which] = list;
       RIL._mergeAllCellBroadcastConfigs();
     }
 
     function onerror() {
       RIL.cellBroadcastConfigs[which] = null;
       RIL._mergeAllCellBroadcastConfigs();
     }
 
     let fileId = GLOBAL["ICC_EF_" + which];
-    ICCIOHelper.loadTransparentEF({fileId: fileId,
-                                   callback: callback.bind(this),
-                                   onerror: onerror.bind(this)});
+    this.context.ICCIOHelper.loadTransparentEF({
+      fileId: fileId,
+      callback: callback.bind(this),
+      onerror: onerror.bind(this)
+    });
   },
 
   /**
    * Read EFcbmi (Cell Broadcast Message Identifier selection)
    *
    * @see 3GPP TS 31.102 v110.02.0 section 4.2.14 EFcbmi
    * @see 3GPP TS 51.011 v5.0.0 section 10.3.13 EFcbmi
    */
@@ -12414,66 +12846,76 @@ let SimRecordHelper = {
 
   /**
    * Read EFcbmir (Cell Broadcast Message Identifier Range selection)
    *
    * @see 3GPP TS 31.102 v110.02.0 section 4.2.22 EFcbmir
    * @see 3GPP TS 51.011 v5.0.0 section 10.3.28 EFcbmir
    */
   readCBMIR: function() {
+    let RIL = this.context.RIL;
+
     function callback() {
+      let Buf = this.context.Buf;
       let strLength = Buf.readInt32();
 
       // Each Message Identifier range takes four octets and each octet is
       // encoded into two chars.
       let numIds = strLength / 8, list = null;
       if (numIds) {
         list = [];
+        let GsmPDUHelper = this.context.GsmPDUHelper;
         for (let i = 0, from, to; i < numIds; i++) {
           // `Bytes one and two of each range identifier equal the lower value
           // of a cell broadcast range, bytes three and four equal the upper
           // value of a cell broadcast range.`
           from = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
           to = GsmPDUHelper.readHexOctet() << 8 | GsmPDUHelper.readHexOctet();
           // `Unused entries shall be set to 'FF FF'.`
           if ((from != 0xFFFF) && (to != 0xFFFF)) {
             list.push(from);
             list.push(to + 1);
           }
         }
       }
       if (DEBUG) {
-        debug("CBMIR: " + JSON.stringify(list));
+        this.context.debug("CBMIR: " + JSON.stringify(list));
       }
 
       Buf.readStringDelimiter(strLength);
 
       RIL.cellBroadcastConfigs.CBMIR = list;
       RIL._mergeAllCellBroadcastConfigs();
     }
 
     function onerror() {
       RIL.cellBroadcastConfigs.CBMIR = null;
       RIL._mergeAllCellBroadcastConfigs();
     }
 
-    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_CBMIR,
-                                   callback: callback.bind(this),
-                                   onerror: onerror.bind(this)});
+    this.context.ICCIOHelper.loadTransparentEF({
+      fileId: ICC_EF_CBMIR,
+      callback: callback.bind(this),
+      onerror: onerror.bind(this)
+    });
   },
 
   /**
    * Read OPL (Operator PLMN List) from (U)SIM.
    *
    * See 3GPP TS 31.102 Sec. 4.2.59 for USIM
    *     3GPP TS 51.011 Sec. 10.3.42 for SIM.
    */
   readOPL: function() {
+    let ICCIOHelper = this.context.ICCIOHelper;
     let opl = [];
     function callback(options) {
+      let Buf = this.context.Buf;
+      let GsmPDUHelper = this.context.GsmPDUHelper;
+
       let strLen = Buf.readInt32();
       // The first 7 bytes are LAI (for UMTS) and the format of LAI is defined
       // in 3GPP TS 23.003, Sec 4.1
       //    +-------------+---------+
       //    | Octet 1 - 3 | MCC/MNC |
       //    +-------------+---------+
       //    | Octet 4 - 7 |   LAC   |
       //    +-------------+---------+
@@ -12506,48 +12948,52 @@ let SimRecordHelper = {
         // LAC/TAC
         oplElement.lacTacStart =
           (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
         oplElement.lacTacEnd =
           (GsmPDUHelper.readHexOctet() << 8) | GsmPDUHelper.readHexOctet();
         // PLMN Network Name Record Identifier
         oplElement.pnnRecordId = GsmPDUHelper.readHexOctet();
         if (DEBUG) {
-          debug("OPL: [" + (opl.length + 1) + "]: " + JSON.stringify(oplElement));
+          this.context.debug("OPL: [" + (opl.length + 1) + "]: " +
+                             JSON.stringify(oplElement));
         }
         opl.push(oplElement);
       } else {
         Buf.seekIncoming(5 * Buf.PDU_HEX_OCTET_SIZE);
       }
       Buf.readStringDelimiter(strLen);
 
       if (options.p1 < options.totalRecords) {
         ICCIOHelper.loadNextRecord(options);
       } else {
-        RIL.iccInfoPrivate.OPL = opl;
+        this.context.RIL.iccInfoPrivate.OPL = opl;
       }
     }
 
     ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_OPL,
                                    callback: callback.bind(this)});
   },
 
   /**
    * Read PNN (PLMN Network Name) from (U)SIM.
    *
    * See 3GPP TS 31.102 Sec. 4.2.58 for USIM
    *     3GPP TS 51.011 Sec. 10.3.41 for SIM.
    */
   readPNN: function() {
+    let ICCIOHelper = this.context.ICCIOHelper;
     function callback(options) {
       let pnnElement;
+      let Buf = this.context.Buf;
       let strLen = Buf.readInt32();
       let octetLen = strLen / 2;
       let readLen = 0;
 
+      let GsmPDUHelper = this.context.GsmPDUHelper;
       while (readLen < octetLen) {
         let tlvTag = GsmPDUHelper.readHexOctet();
 
         if (tlvTag == 0xFF) {
           // Unused byte
           readLen++;
           Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
           break;
@@ -12579,20 +13025,20 @@ let SimRecordHelper = {
       }
 
       // Will ignore remaining records when got the contents of a record are all 0xff.
       if (pnnElement && options.p1 < options.totalRecords) {
         ICCIOHelper.loadNextRecord(options);
       } else {
         if (DEBUG) {
           for (let i = 0; i < pnn.length; i++) {
-            debug("PNN: [" + i + "]: " + JSON.stringify(pnn[i]));
+            this.context.debug("PNN: [" + i + "]: " + JSON.stringify(pnn[i]));
           }
         }
-        RIL.iccInfoPrivate.PNN = pnn;
+        this.context.RIL.iccInfoPrivate.PNN = pnn;
       }
     }
 
     let pnn = [];
     ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_PNN,
                                    callback: callback.bind(this)});
   },
 
@@ -12603,27 +13049,31 @@ let SimRecordHelper = {
    *  not a problem in our case (0xFF 0xFF 0xFF).
    *
    *  @param length The number of PLMN records.
    *  @return An array of string corresponding to the PLMNs.
    */
   readPLMNEntries: function(length) {
     let plmnList = [];
     // Each PLMN entry has 3 bytes.
-    if (DEBUG) debug("readPLMNEntries: PLMN entries length = " + length);
+    if (DEBUG) {
+      this.context.debug("PLMN entries length = " + length);
+    }
+    let GsmPDUHelper = this.context.GsmPDUHelper;
     let index = 0;
     while (index < length) {
       // Unused entries will be 0xFFFFFF, according to EF_SPDI
       // specs (TS 131 102, section 4.2.66)
       try {
         let plmn = [GsmPDUHelper.readHexOctet(),
                     GsmPDUHelper.readHexOctet(),
                     GsmPDUHelper.readHexOctet()];
-        if (DEBUG) debug("readPLMNEntries: Reading PLMN entry: [" + index +
-                         "]: '" + plmn + "'");
+        if (DEBUG) {
+          this.context.debug("Reading PLMN entry: [" + index + "]: '" + plmn + "'");
+        }
         if (plmn[0] != 0xFF &&
             plmn[1] != 0xFF &&
             plmn[2] != 0xFF) {
           let semiOctets = [];
           for (let idx = 0; idx < plmn.length; idx++) {
             semiOctets.push((plmn[idx] & 0xF0) >> 4);
             semiOctets.push(plmn[idx] & 0x0F);
           }
@@ -12646,45 +13096,51 @@ let SimRecordHelper = {
               // 0-2: MCC
               plmnEntry.mcc = buf;
               buf = "";
             } else if (i === 5) {
               // 3-5: MNC
               plmnEntry.mnc = buf;
             }
           }
-          if (DEBUG) debug("readPLMNEntries: PLMN = " + plmnEntry.mcc + ", " + plmnEntry.mnc);
+          if (DEBUG) {
+            this.context.debug("PLMN = " + plmnEntry.mcc + ", " + plmnEntry.mnc);
+          }
           plmnList.push(plmnEntry);
         }
       } catch (e) {
-        if (DEBUG) debug("readPLMNEntries: PLMN entry " + index + " is invalid.");
+        if (DEBUG) {
+          this.context.debug("PLMN entry " + index + " is invalid.");
+        }
         break;
       }
       index ++;
     }
     return plmnList;
   },
 
   /**
    * Read the SMS from the ICC.
    *
    * @param recordNumber The number of the record shall be loaded.
    * @param onsuccess    Callback to be called when success.
    * @param onerror      Callback to be called when error.
    */
   readSMS: function(recordNumber, onsuccess, onerror) {
     function callback(options) {
+      let Buf = this.context.Buf;
       let strLen = Buf.readInt32();
 
       // TS 51.011, 10.5.3 EF_SMS
       // b3 b2 b1
       //  0  0  1 message received by MS from network; message read
       //  0  1  1 message received by MS from network; message to be read
       //  1  1  1 MS originating message; message to be sent
       //  1  0  1 MS originating message; message sent to the network:
+      let GsmPDUHelper = this.context.GsmPDUHelper;
       let status = GsmPDUHelper.readHexOctet();
 
       let message = GsmPDUHelper.readMessage();
       message.simStatus = status;
 
       // Consumes the remaining buffer
       Buf.seekIncoming(Buf.getReadAvailable() - Buf.PDU_HEX_OCTET_SIZE);
 
@@ -12692,57 +13148,69 @@ let SimRecordHelper = {
 
       if (message) {
         onsuccess(message);
       } else {
         onerror("Failed to decode SMS on SIM #" + recordNumber);
       }
     }
 
-    ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_SMS,
-                                   recordNumber: recordNumber,
-                                   callback: callback,
-                                   onerror: onerror});
-  },
-};
-
-let RuimRecordHelper = {
+    this.context.ICCIOHelper.loadLinearFixedEF({
+      fileId: ICC_EF_SMS,
+      recordNumber: recordNumber,
+      callback: callback.bind(this),
+      onerror: onerror
+    });
+  },
+};
+
+function RuimRecordHelperObject(aContext) {
+  this.context = aContext;
+}
+RuimRecordHelperObject.prototype = {
+  context: null,
+
   fetchRuimRecords: function() {
     this.getIMSI_M();
     this.readCST();
     this.readCDMAHome();
-    RIL.getCdmaSubscription();
+    this.context.RIL.getCdmaSubscription();
   },
 
   /**
    * Get IMSI_M from CSIM/RUIM.
    * See 3GPP2 C.S0065 Sec. 5.2.2
    */
   getIMSI_M: function() {
     function callback() {
+      let Buf = this.context.Buf;
       let strLen = Buf.readInt32();
-      let encodedImsi = GsmPDUHelper.readHexOctetArray(strLen / 2);
+      let encodedImsi = this.context.GsmPDUHelper.readHexOctetArray(strLen / 2);
       Buf.readStringDelimiter(strLen);
 
       if ((encodedImsi[CSIM_IMSI_M_PROGRAMMED_BYTE] & 0x80)) { // IMSI_M programmed
+        let RIL = this.context.RIL;
         RIL.iccInfoPrivate.imsi = this.decodeIMSI(encodedImsi);
         RIL.sendChromeMessage({rilMessageType: "iccimsi",
                                imsi: RIL.iccInfoPrivate.imsi});
 
+        let ICCUtilsHelper = this.context.ICCUtilsHelper;
         let mccMnc = ICCUtilsHelper.parseMccMncFromImsi(RIL.iccInfoPrivate.imsi);
         if (mccMnc) {
           RIL.iccInfo.mcc = mccMnc.mcc;
           RIL.iccInfo.mnc = mccMnc.mnc;
           ICCUtilsHelper.handleICCInfoChange();
         }
       }
     }
 
-    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_CSIM_IMSI_M,
-                                   callback: callback.bind(this)});
+    this.context.ICCIOHelper.loadTransparentEF({
+      fileId: ICC_EF_CSIM_IMSI_M,
+      callback: callback.bind(this)
+    });
   },
 
   /**
    * Decode IMSI from IMSI_M
    * See 3GPP2 C.S0005 Sec. 2.3.1
    * +---+---------+------------+---+--------+---------+---+---------+--------+
    * |RFU|   MCC   | programmed |RFU|  MNC   |  MIN1   |RFU|   MIN2  |  CLASS |
    * +---+---------+------------+---+--------+---------+---+---------+--------+
@@ -12806,35 +13274,42 @@ let RuimRecordHelper = {
     return s;
   },
 
   /**
    * Read CDMAHOME for CSIM.
    * See 3GPP2 C.S0023 Sec. 3.4.8.
    */
   readCDMAHome: function() {
+    let ICCIOHelper = this.context.ICCIOHelper;
+
     function callback(options) {
+      let Buf = this.context.Buf;
+      let GsmPDUHelper = this.context.GsmPDUHelper;
+
       let strLen = Buf.readInt32();
       let tempOctet = GsmPDUHelper.readHexOctet();
       cdmaHomeSystemId.push(((GsmPDUHelper.readHexOctet() & 0x7f) << 8) | tempOctet);
       tempOctet = GsmPDUHelper.readHexOctet();
       cdmaHomeNetworkId.push(((GsmPDUHelper.readHexOctet() & 0xff) << 8) | tempOctet);
 
       // Consuming the last octet: band class.
       Buf.seekIncoming(Buf.PDU_HEX_OCTET_SIZE);
 
       Buf.readStringDelimiter(strLen);
       if (options.p1 < options.totalRecords) {
         ICCIOHelper.loadNextRecord(options);
       } else {
         if (DEBUG) {
-          debug("CDMAHome system id: " + JSON.stringify(cdmaHomeSystemId));
-          debug("CDMAHome network id: " + JSON.stringify(cdmaHomeNetworkId));
-        }
-        RIL.cdmaHome = {
+          this.context.debug("CDMAHome system id: " +
+                             JSON.stringify(cdmaHomeSystemId));
+          this.context.debug("CDMAHome network id: " +
+                             JSON.stringify(cdmaHomeNetworkId));
+        }
+        this.context.RIL.cdmaHome = {
           systemId: cdmaHomeSystemId,
           networkId: cdmaHomeNetworkId
         };
       }
     }
 
     let cdmaHomeSystemId = [], cdmaHomeNetworkId = [];
     ICCIOHelper.loadLinearFixedEF({fileId: ICC_EF_CSIM_CDMAHOME,
@@ -12842,42 +13317,51 @@ let RuimRecordHelper = {
   },
 
   /**
    * Read CDMA Service Table.
    * See 3GPP2 C.S0023 Sec. 3.4.18
    */
   readCST: function() {
     function callback() {
+      let Buf = this.context.Buf;
+      let RIL = this.context.RIL;
+
       let strLen = Buf.readInt32();
       // Each octet is encoded into two chars.
-      RIL.iccInfoPrivate.cst = GsmPDUHelper.readHexOctetArray(strLen / 2);
+      RIL.iccInfoPrivate.cst =
+        this.context.GsmPDUHelper.readHexOctetArray(strLen / 2);
       Buf.readStringDelimiter(strLen);
 
       if (DEBUG) {
         let str = "";
         for (let i = 0; i < RIL.iccInfoPrivate.cst.length; i++) {
           str += RIL.iccInfoPrivate.cst[i] + ", ";
         }
-        debug("CST: " + str);
-      }
-
-      if (ICCUtilsHelper.isICCServiceAvailable("SPN")) {
-        if (DEBUG) debug("SPN: SPN is available");
+        this.context.debug("CST: " + str);
+      }
+
+      if (this.context.ICCUtilsHelper.isICCServiceAvailable("SPN")) {
+        if (DEBUG) this.context.debug("SPN: SPN is available");
         this.readSPN();
       }
     }
-    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_CSIM_CST,
-                                   callback: callback.bind(this)});
+    this.context.ICCIOHelper.loadTransparentEF({
+      fileId: ICC_EF_CSIM_CST,
+      callback: callback.bind(this)
+    });
   },
 
   readSPN: function() {
     function callback() {
+      let Buf = this.context.Buf;
       let strLen = Buf.readInt32();
       let octetLen = strLen / 2;
+
+      let GsmPDUHelper = this.context.GsmPDUHelper;
       let displayCondition = GsmPDUHelper.readHexOctet();
       let codingScheme = GsmPDUHelper.readHexOctet();
       // Skip one octet: language indicator.
       Buf.seekIncoming(Buf.PDU_HEX_OCTET_SIZE);
       let readLen = 3;
 
       // SPN String ends up with 0xff.
       let userDataBuffer = [];
@@ -12886,61 +13370,71 @@ let RuimRecordHelper = {
         let octet = GsmPDUHelper.readHexOctet();
         readLen++;
         if (octet == 0xff) {
           break;
         }
         userDataBuffer.push(octet);
       }
 
-      BitBufferHelper.startRead(userDataBuffer);
-
+      this.context.BitBufferHelper.startRead(userDataBuffer);
+
+      let CdmaPDUHelper = this.context.CdmaPDUHelper;
       let msgLen;
       switch (CdmaPDUHelper.getCdmaMsgEncoding(codingScheme)) {
       case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
         msgLen = Math.floor(userDataBuffer.length * 8 / 7);
         break;
       case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
         msgLen = userDataBuffer.length;
         break;
       case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
         msgLen = Math.floor(userDataBuffer.length / 2);
         break;
       }
 
+      let RIL = this.context.RIL;
       RIL.iccInfo.spn = CdmaPDUHelper.decodeCdmaPDUMsg(codingScheme, null, msgLen);
       if (DEBUG) {
-        debug("CDMA SPN: " + RIL.iccInfo.spn +
-              ", Display condition: " + displayCondition);
+        this.context.debug("CDMA SPN: " + RIL.iccInfo.spn +
+                           ", Display condition: " + displayCondition);
       }
       RIL.iccInfoPrivate.spnDisplayCondition = displayCondition;
       Buf.seekIncoming((octetLen - readLen) * Buf.PDU_HEX_OCTET_SIZE);
       Buf.readStringDelimiter(strLen);
     }
 
-    ICCIOHelper.loadTransparentEF({fileId: ICC_EF_CSIM_SPN,
-                                   callback: callback.bind(this)});
+    this.context.ICCIOHelper.loadTransparentEF({
+      fileId: ICC_EF_CSIM_SPN,
+      callback: callback.bind(this)
+    });
   }
 };
 
 /**
  * Helper functions for ICC utilities.
  */
-let ICCUtilsHelper = {
+function ICCUtilsHelperObject(aContext) {
+  this.context = aContext;
+}
+ICCUtilsHelperObject.prototype = {
+  context: null,
+
   /**
    * Get network names by using EF_OPL and EF_PNN
    *
    * @See 3GPP TS 31.102 sec. 4.2.58 and sec. 4.2.59 for USIM,
    *      3GPP TS 51.011 sec. 10.3.41 and sec. 10.3.42 for SIM.
    *
    * @param mcc   The mobile country code of the network.
    * @param mnc   The mobile network code of the network.
    * @param lac   The location area code of the network.
    */
   getNetworkNameFromICC: function(mcc, mnc, lac) {
+    let RIL = this.context.RIL;
     let iccInfoPriv = RIL.iccInfoPrivate;
     let iccInfo = RIL.iccInfo;
     let pnnEntry;
 
     if (!mcc || !mnc || !lac) {
       return null;
     }
 
@@ -12999,16 +13493,18 @@ let ICCUtilsHelper = {
 
   /**
    * This will compute the spnDisplay field of the network.
    * See TS 22.101 Annex A and TS 51.011 10.3.11 for details.
    *
    * @return True if some of iccInfo is changed in by this function.
    */
   updateDisplayCondition: function() {
+    let RIL = this.context.RIL;
+
     // If EFspn isn't existed in SIM or it haven't been read yet, we should
     // just set isDisplayNetworkNameRequired = true and
     // isDisplaySpnRequired = false
     let iccInfo = RIL.iccInfo;
     let iccInfoPriv = RIL.iccInfoPrivate;
     let displayCondition = iccInfoPriv.spnDisplayCondition;
     let origIsDisplayNetworkNameRequired = iccInfo.isDisplayNetworkNameRequired;
     let origIsDisplaySPNRequired = iccInfo.isDisplaySpnRequired;
@@ -13088,46 +13584,53 @@ let ICCUtilsHelper = {
             break;
           }
         }
       }
 
       if (isOnMatchingPlmn) {
         // The first bit of display condition tells us if we should display
         // registered PLMN.
-        if (DEBUG) debug("updateDisplayCondition: PLMN is HPLMN or PLMN is in PLMN list");
+        if (DEBUG) {
+          this.context.debug("PLMN is HPLMN or PLMN " + "is in PLMN list");
+        }
 
         // TS 31.102 Sec. 4.2.66 and TS 51.011 Sec. 10.3.50
         // EF_SPDI contains a list of PLMNs in which the Service Provider Name
         // shall be displayed.
         iccInfo.isDisplaySpnRequired = true;
         iccInfo.isDisplayNetworkNameRequired = (displayCondition & 0x01) !== 0;
       } else {
         // The second bit of display condition tells us if we should display
         // registered PLMN.
-        if (DEBUG) debug("updateICCDisplayName: PLMN isn't HPLMN and PLMN isn't in PLMN list");
+        if (DEBUG) {
+          this.context.debug("PLMN isn't HPLMN and PLMN isn't in PLMN list");
+        }
 
         // We didn't found the requirement of displaying network name if
         // current PLMN isn't HPLMN nor one of PLMN in SPDI. So we keep
         // isDisplayNetworkNameRequired false.
         iccInfo.isDisplayNetworkNameRequired = false;
         iccInfo.isDisplaySpnRequired = (displayCondition & 0x02) === 0;
       }
     }
 
     if (DEBUG) {
-      debug("updateDisplayCondition: isDisplayNetworkNameRequired = " + iccInfo.isDisplayNetworkNameRequired);
-      debug("updateDisplayCondition: isDisplaySpnRequired = " + iccInfo.isDisplaySpnRequired);
+      this.context.debug("isDisplayNetworkNameRequired = " +
+                         iccInfo.isDisplayNetworkNameRequired);
+      this.context.debug("isDisplaySpnRequired = " + iccInfo.isDisplaySpnRequired);
     }
 
     return ((origIsDisplayNetworkNameRequired !== iccInfo.isDisplayNetworkNameRequired) ||
             (origIsDisplaySPNRequired !== iccInfo.isDisplaySpnRequired));
   },
 
   decodeSimTlvs: function(tlvsLen) {
+    let GsmPDUHelper = this.context.GsmPDUHelper;
+
     let index = 0;
     let tlvs = [];
     while (index < tlvsLen) {
       let simTlv = {
         tag : GsmPDUHelper.readHexOctet(),
         length : GsmPDUHelper.readHexOctet(),
       };
       simTlv.value = GsmPDUHelper.readHexOctetArray(simTlv.length);
@@ -13168,29 +13671,31 @@ let ICCUtilsHelper = {
 
     return pbr;
   },
 
   /**
    * Update the ICC information to RadioInterfaceLayer.
    */
   handleICCInfoChange: function() {
+    let RIL = this.context.RIL;
     RIL.iccInfo.rilMessageType = "iccinfochange";
     RIL.sendChromeMessage(RIL.iccInfo);
   },
 
   /**
    * Get whether specificed (U)SIM service is available.
    *
    * @param geckoService
    *        Service name like "ADN", "BDN", etc.
    *
    * @return true if the service is enabled, false otherwise.
    */
   isICCServiceAvailable: function(geckoService) {
+    let RIL = this.context.RIL;
     let serviceTable = RIL._isCdma ? RIL.iccInfoPrivate.cst:
                                      RIL.iccInfoPrivate.sst;
     let index, bitmask;
     if (RIL.appType == CARD_APPTYPE_SIM || RIL.appType == CARD_APPTYPE_RUIM) {
       /**
        * Service id is valid in 1..N, and 2 bits are used to code each service.
        *
        * +----+--  --+----+----+
@@ -13293,80 +13798,92 @@ let ICCUtilsHelper = {
     // MCC is the first 3 digits of IMSI.
     let mcc = imsi.substr(0,3);
     if (!mncLength) {
       // Check the MCC table to decide the length of MNC.
       let index = MCC_TABLE_FOR_MNC_LENGTH_IS_3.indexOf(mcc);
       mncLength = (index !== -1) ? 3 : 2;
     }
     let mnc = imsi.substr(3, mncLength);
-    if (DEBUG) debug("IMSI: " + imsi + " MCC: " + mcc + " MNC: " + mnc);
+    if (DEBUG) {
+      this.context.debug("IMSI: " + imsi + " MCC: " + mcc + " MNC: " + mnc);
+    }
 
     return { mcc: mcc, mnc: mnc};
   },
 };
 
 /**
  * Helper for ICC Contacts.
  */
-let ICCContactHelper = {
+function ICCContactHelperObject(aContext) {
+  this.context = aContext;
+}
+ICCContactHelperObject.prototype = {
+  context: null,
+
   /**
    * Helper function to check DF_PHONEBOOK.
    */
   hasDfPhoneBook: function(appType) {
     switch (appType) {
       case CARD_APPTYPE_SIM:
         return false;
       case CARD_APPTYPE_USIM:
         return true;
       case CARD_APPTYPE_RUIM:
+        let ICCUtilsHelper = this.context.ICCUtilsHelper;
         return ICCUtilsHelper.isICCServiceAvailable("ENHANCED_PHONEBOOK");
       default:
         return false;
     }
   },
 
   /**
    * Helper function to read ICC contacts.
    *
    * @param appType       One of CARD_APPTYPE_*.
    * @param contactType   "adn" or "fdn".
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   readICCContacts: function(appType, contactType, onsuccess, onerror) {
+    let ICCRecordHelper = this.context.ICCRecordHelper;
+
     switch (contactType) {
       case "adn":
         if (!this.hasDfPhoneBook(appType)) {
           ICCRecordHelper.readADNLike(ICC_EF_ADN, onsuccess, onerror);
         } else {
           this.readUSimContacts(onsuccess, onerror);
         }
         break;
       case "fdn":
         ICCRecordHelper.readADNLike(ICC_EF_FDN, onsuccess, onerror);
         break;
       default:
         if (DEBUG) {
-          debug("Unsupported contactType :" + contactType);
+          this.context.debug("Unsupported contactType :" + contactType);
         }
         onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
         break;
     }
   },
 
   /**
    * Helper function to find free contact record.
    *
    * @param appType       One of CARD_APPTYPE_*.
    * @param contactType   "adn" or "fdn".
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   findFreeICCContact: function(appType, contactType, onsuccess, onerror) {
+    let ICCRecordHelper = this.context.ICCRecordHelper;
+
     switch (contactType) {
       case "adn":
         if (!this.hasDfPhoneBook(appType)) {
           ICCRecordHelper.findFreeRecordId(ICC_EF_ADN, onsuccess.bind(null, 0), onerror);
         } else {
           let gotPbrCb = function gotPbrCb(pbrs) {
             this.findUSimFreeADNRecordId(pbrs, onsuccess, onerror);
           }.bind(this);
@@ -13374,35 +13891,37 @@ let ICCContactHelper = {
           ICCRecordHelper.readPBR(gotPbrCb, onerror);
         }
         break;
       case "fdn":
         ICCRecordHelper.findFreeRecordId(ICC_EF_FDN, onsuccess.bind(null, 0), onerror);
         break;
       default:
         if (DEBUG) {
-          debug("Unsupported contactType :" + contactType);
+          this.context.debug("Unsupported contactType :" + contactType);
         }
         onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
         break;
     }
   },
 
    /**
     * Find free ADN record id in USIM.
     *
     * @param pbrs          All Phonebook Reference Files read.
     * @param onsuccess     Callback to be called when success.
     * @param onerror       Callback to be called when error.
     */
   findUSimFreeADNRecordId: function(pbrs, onsuccess, onerror) {
+    let ICCRecordHelper = this.context.ICCRecordHelper;
+
     (function findFreeRecordId(pbrIndex) {
       if (pbrIndex >= pbrs.length) {
         if (DEBUG) {
-          debug(CONTACT_ERR_NO_FREE_RECORD_FOUND);
+          this.context.debug(CONTACT_ERR_NO_FREE_RECORD_FOUND);
         }
         onerror(CONTACT_ERR_NO_FREE_RECORD_FOUND);
         return;
       }
 
       let pbr = pbrs[pbrIndex];
       ICCRecordHelper.findFreeRecordId(
         pbr.adn.fileId,
@@ -13417,16 +13936,18 @@ let ICCContactHelper = {
    * @param appType       One of CARD_APPTYPE_*.
    * @param contactType   "adn" or "fdn".
    * @param contact       The contact will be added.
    * @param pin2          PIN2 is required for FDN.
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   addICCContact: function(appType, contactType, contact, pin2, onsuccess, onerror) {
+    let ICCContactHelper = this.context.ICCContactHelper;
+
     let foundFreeCb = function foundFreeCb(pbrIndex, recordId) {
       contact.pbrIndex = pbrIndex;
       contact.recordId = recordId;
       ICCContactHelper.updateICCContact(appType, contactType, contact, pin2, onsuccess, onerror);
     };
 
     // Find free record first.
     ICCContactHelper.findFreeICCContact(appType, contactType, foundFreeCb, onerror);
@@ -13438,16 +13959,18 @@ let ICCContactHelper = {
    * @param appType       One of CARD_APPTYPE_*.
    * @param contactType   "adn" or "fdn".
    * @param contact       The contact will be updated.
    * @param pin2          PIN2 is required for FDN.
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   updateICCContact: function(appType, contactType, contact, pin2, onsuccess, onerror) {
+    let ICCRecordHelper = this.context.ICCRecordHelper;
+
     switch (contactType) {
       case "adn":
         if (!this.hasDfPhoneBook(appType)) {
           ICCRecordHelper.updateADNLike(ICC_EF_ADN, contact, null, onsuccess, onerror);
         } else {
           this.updateUSimContact(contact, onsuccess, onerror);
         }
         break;
@@ -13455,17 +13978,17 @@ let ICCContactHelper = {
         if (!pin2) {
           onerror(GECKO_ERROR_SIM_PIN2);
           return;
         }
         ICCRecordHelper.updateADNLike(ICC_EF_FDN, contact, pin2, onsuccess, onerror);
         break;
       default:
         if (DEBUG) {
-          debug("Unsupported contactType :" + contactType);
+          this.context.debug("Unsupported contactType :" + contactType);
         }
         onerror(CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
         break;
     }
   },
 
   /**
    * Read contacts from USIM.
@@ -13473,17 +13996,17 @@ let ICCContactHelper = {
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   readUSimContacts: function(onsuccess, onerror) {
     let gotPbrCb = function gotPbrCb(pbrs) {
       this.readAllPhonebookSets(pbrs, onsuccess, onerror);
     }.bind(this);
 
-    ICCRecordHelper.readPBR(gotPbrCb, onerror);
+    this.context.ICCRecordHelper.readPBR(gotPbrCb, onerror);
   },
 
   /**
    * Read all Phonebook sets.
    *
    * @param pbrs          All Phonebook Reference Files read.
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
@@ -13521,28 +14044,29 @@ let ICCContactHelper = {
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   readPhonebookSet: function(pbr, onsuccess, onerror) {
     let gotAdnCb = function gotAdnCb(contacts) {
       this.readSupportedPBRFields(pbr, contacts, onsuccess, onerror);
     }.bind(this);
 
-    ICCRecordHelper.readADNLike(pbr.adn.fileId, gotAdnCb, onerror);
+    this.context.ICCRecordHelper.readADNLike(pbr.adn.fileId, gotAdnCb, onerror);
   },
 
   /**
    * Read supported Phonebook fields.
    *
    * @param pbr         Phone Book Reference file.
    * @param contacts    Contacts stored on ICC.
    * @param onsuccess   Callback to be called when success.
    * @param onerror     Callback to be called when error.
    */
   readSupportedPBRFields: function(pbr, contacts, onsuccess, onerror) {
+    let ICCContactHelper = this.context.ICCContactHelper;
     let fieldIndex = 0;
     (function readField() {
       let field = USIM_PBR_FIELDS[fieldIndex];
       fieldIndex += 1;
       if (!field) {
         if (onsuccess) {
           onsuccess(contacts);
         }
@@ -13565,16 +14089,17 @@ let ICCContactHelper = {
   readPhonebookField: function(pbr, contacts, field, onsuccess, onerror) {
     if (!pbr[field]) {
       if (onsuccess) {
         onsuccess(contacts);
       }
       return;
     }
 
+    let ICCContactHelper = this.context.ICCContactHelper;
     (function doReadContactField(n) {
       if (n >= contacts.length) {
         // All contact's fields are read.
         if (onsuccess) {
           onsuccess(contacts);
         }
         return;
       }
@@ -13618,28 +14143,29 @@ let ICCContactHelper = {
           }
         }
 
         if (onsuccess) {
           onsuccess();
         }
       }.bind(this);
 
+      let ICCRecordHelper = this.context.ICCRecordHelper;
       // Detect EF to be read, for anr, it could have anr0, anr1,...
       let ef = field.startsWith(USIM_PBR_ANR) ? USIM_PBR_ANR : field;
       switch (ef) {
         case USIM_PBR_EMAIL:
           ICCRecordHelper.readEmail(fileId, fileType, recordId, gotFieldCb, onerror);
           break;
         case USIM_PBR_ANR:
           ICCRecordHelper.readANR(fileId, fileType, recordId, gotFieldCb, onerror);
           break;
         default:
           if (DEBUG) {
-            debug("Unsupported field :" + field);
+            this.context.debug("Unsupported field :" + field);
           }
           onerror(CONTACT_ERR_FIELD_NOT_SUPPORTED);
           break;
       }
     }.bind(this);
 
     this.getContactFieldRecordId(pbr, contact, field, gotRecordIdCb, onerror);
   },
@@ -13669,20 +14195,21 @@ let ICCContactHelper = {
         let indexInIAP = pbr[field].indexInIAP;
         let recordId = iap[indexInIAP];
 
         if (onsuccess) {
           onsuccess(recordId);
         }
       }.bind(this);
 
-      ICCRecordHelper.readIAP(pbr.iap.fileId, contact.recordId, gotIapCb, onerror);
+      this.context.ICCRecordHelper.readIAP(pbr.iap.fileId, contact.recordId,
+                                           gotIapCb, onerror);
     } else {
       if (DEBUG) {
-        debug("USIM PBR files in Type 3 format are not supported.");
+        this.context.debug("USIM PBR files in Type 3 format are not supported.");
       }
       onerror(CONTACT_ERR_REQUEST_NOT_SUPPORTED);
     }
   },
 
   /**
    * Update USIM contact.
    *
@@ -13690,51 +14217,53 @@ let ICCContactHelper = {
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   updateUSimContact: function(contact, onsuccess, onerror) {
     let gotPbrCb = function gotPbrCb(pbrs) {
       let pbr = pbrs[contact.pbrIndex];
       if (!pbr) {
         if (DEBUG) {
-          debug(CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
+          this.context.debug(CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
         }
         onerror(CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
         return;
       }
       this.updatePhonebookSet(pbr, contact, onsuccess, onerror);
     }.bind(this);
 
-    ICCRecordHelper.readPBR(gotPbrCb, onerror);
+    this.context.ICCRecordHelper.readPBR(gotPbrCb, onerror);
   },
 
   /**
    * Update fields in Phonebook Reference File.
    *
    * @param pbr           Phonebook Reference File to be read.
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   updatePhonebookSet: function(pbr, contact, onsuccess, onerror) {
     let updateAdnCb = function() {
       this.updateSupportedPBRFields(pbr, contact, onsuccess, onerror);
     }.bind(this);
 
-    ICCRecordHelper.updateADNLike(pbr.adn.fileId, contact, null, updateAdnCb, onerror);
+    this.context.ICCRecordHelper.updateADNLike(pbr.adn.fileId, contact, null,
+                                               updateAdnCb, onerror);
   },
 
   /**
    * Update supported Phonebook fields.
    *
    * @param pbr         Phone Book Reference file.
    * @param contact     Contact to be updated.
    * @param onsuccess   Callback to be called when success.
    * @param onerror     Callback to be called when error.
    */
   updateSupportedPBRFields: function(pbr, contact, onsuccess, onerror) {
+    let ICCContactHelper = this.context.ICCContactHelper;
     let fieldIndex = 0;
     (function updateField() {
       let field = USIM_PBR_FIELDS[fieldIndex];
       fieldIndex += 1;
       if (!field) {
         if (onsuccess) {
           onsuccess();
         }
@@ -13762,55 +14291,59 @@ let ICCContactHelper = {
    */
   updateContactField: function(pbr, contact, field, onsuccess, onerror) {
     if (pbr[field].fileType === ICC_USIM_TYPE1_TAG) {
       this.updateContactFieldType1(pbr, contact, field, onsuccess, onerror);
     } else if (pbr[field].fileType === ICC_USIM_TYPE2_TAG) {
       this.updateContactFieldType2(pbr, contact, field, onsuccess, onerror);
     } else {
       if (DEBUG) {
-        debug("USIM PBR files in Type 3 format are not supported.");
+        this.context.debug("USIM PBR files in Type 3 format are not supported.");
       }
       onerror(CONTACT_ERR_REQUEST_NOT_SUPPORTED);
     }
   },
 
   /**
    * Update Type 1 USIM contact fields.
    *
    * @param pbr           The phonebook reference file.
    * @param contact       The contact needs to be updated.
    * @param field         Phonebook field to be updated.
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   updateContactFieldType1: function(pbr, contact, field, onsuccess, onerror) {
+    let ICCRecordHelper = this.context.ICCRecordHelper;
+
     if (field === USIM_PBR_EMAIL) {
       ICCRecordHelper.updateEmail(pbr, contact.recordId, contact.email, null, onsuccess, onerror);
     } else if (field === USIM_PBR_ANR0) {
       let anr = Array.isArray(contact.anr) ? contact.anr[0] : null;
       ICCRecordHelper.updateANR(pbr, contact.recordId, anr, null, onsuccess, onerror);
     } else {
      if (DEBUG) {
-       debug("Unsupported field :" + field);
+       this.context.debug("Unsupported field :" + field);
      }
      onerror(CONTACT_ERR_FIELD_NOT_SUPPORTED);
     }
   },
 
   /**
    * Update Type 2 USIM contact fields.
    *
    * @param pbr           The phonebook reference file.
    * @param contact       The contact needs to be updated.
    * @param field         Phonebook field to be updated.
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   updateContactFieldType2: function(pbr, contact, field, onsuccess, onerror) {
+    let ICCRecordHelper = this.context.ICCRecordHelper;
+
     // Case 1 : EF_IAP[adnRecordId] doesn't have a value(0xff)
     //   Find a free recordId for EF_field
     //   Update field with that free recordId.
     //   Update IAP.
     //
     // Case 2: EF_IAP[adnRecordId] has a value
     //   update EF_field[iap[field.indexInIAP]]
 
@@ -13833,17 +14366,17 @@ let ICCContactHelper = {
       // Case 2.
       if (field === USIM_PBR_EMAIL) {
         ICCRecordHelper.updateEmail(pbr, recordId, contact.email, contact.recordId, onsuccess, onerror);
       } else if (field === USIM_PBR_ANR0) {
         let anr = Array.isArray(contact.anr) ? contact.anr[0] : null;
         ICCRecordHelper.updateANR(pbr, recordId, anr, contact.recordId, onsuccess, onerror);
       } else {
         if (DEBUG) {
-          debug("Unsupported field :" + field);
+          this.context.debug("Unsupported field :" + field);
         }
         onerror(CONTACT_ERR_FIELD_NOT_SUPPORTED);
       }
 
     }.bind(this);
 
     ICCRecordHelper.readIAP(pbr.iap.fileId, contact.recordId, gotIapCb, onerror);
   },
@@ -13853,31 +14386,33 @@ let ICCContactHelper = {
    *
    * @param pbr           The phonebook reference file.
    * @param contact       The contact needs to be updated.
    * @param field         Phonebook field to be updated.
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    */
   addContactFieldType2: function(pbr, contact, field, onsuccess, onerror) {
+    let ICCRecordHelper = this.context.ICCRecordHelper;
+
     let successCb = function successCb(recordId) {
       let updateCb = function updateCb() {
         this.updateContactFieldIndexInIAP(pbr, contact.recordId, field, recordId, onsuccess, onerror);
       }.bind(this);
 
       if (field === USIM_PBR_EMAIL) {
         ICCRecordHelper.updateEmail(pbr, recordId, contact.email, contact.recordId, updateCb, onerror);
       } else if (field === USIM_PBR_ANR0) {
         ICCRecordHelper.updateANR(pbr, recordId, contact.anr[0], contact.recordId, updateCb, onerror);
       }
     }.bind(this);
 
     let errorCb = function errorCb(errorMsg) {
       if (DEBUG) {
-        debug(errorMsg + " USIM field " + field);
+        this.context.debug(errorMsg + " USIM field " + field);
       }
       onerror(errorMsg);
     }.bind(this);
 
     ICCRecordHelper.findFreeRecordId(pbr[field].fileId, successCb, errorCb);
   },
 
   /**
@@ -13887,35 +14422,128 @@ let ICCContactHelper = {
    * @param recordNumber  The record identifier of EF_IAP.
    * @param field         Phonebook field.
    * @param value         The value of 'field' in IAP.
    * @param onsuccess     Callback to be called when success.
    * @param onerror       Callback to be called when error.
    *
    */
   updateContactFieldIndexInIAP: function(pbr, recordNumber, field, value, onsuccess, onerror) {
+    let ICCRecordHelper = this.context.ICCRecordHelper;
+
     let gotIAPCb = function gotIAPCb(iap) {
       iap[pbr[field].indexInIAP] = value;
       ICCRecordHelper.updateIAP(pbr.iap.fileId, recordNumber, iap, onsuccess, onerror);
     }.bind(this);
     ICCRecordHelper.readIAP(pbr.iap.fileId, recordNumber, gotIAPCb, onerror);
   },
 };
 
 /**
  * Global stuff.
  */
 
-// Initialize buffers. This is a separate function so that unit tests can
-// re-initialize the buffers at will.
-Buf.init();
-
-function onRILMessage(data) {
-  Buf.processIncoming(data);
+function Context(aClientId) {
+  this.clientId = aClientId;
+
+  this.Buf = new BufObject(this);
+  this.Buf.init();
+
+  this.RIL = new RilObject(this);
+  this.RIL.initRILState();
+}
+Context.prototype = {
+  clientId: null,
+  Buf: null,
+  RIL: null,
+
+  debug: function(aMessage) {
+    GLOBAL.debug("[" + this.clientId + "] " + aMessage);
+  }
+};
+
+(function() {
+  let lazySymbols = [
+    "BerTlvHelper", "BitBufferHelper", "CdmaPDUHelper",
+    "ComprehensionTlvHelper", "GsmPDUHelper", "ICCContactHelper",
+    "ICCFileHelper", "ICCIOHelper", "ICCPDUHelper", "ICCRecordHelper",
+    "ICCUtilsHelper", "RuimRecordHelper", "SimRecordHelper",
+    "StkCommandParamsFactory", "StkProactiveCmdHelper",
+  ];
+
+  for (let i = 0; i < lazySymbols.length; i++) {
+    let symbol = lazySymbols[i];
+    Object.defineProperty(Context.prototype, symbol, {
+      get: function() {
+        let real = new GLOBAL[symbol + "Object"](this);
+        Object.defineProperty(this, symbol, {
+          value: real,
+          enumerable: true
+        });
+        return real;
+      },
+      configurable: true,
+      enumerable: true
+    });
+  }
+})();
+
+let ContextPool = {
+  _contexts: [],
+
+  handleRilMessage: function(aClientId, aUint8Array) {
+    let context = this._contexts[aClientId];
+    context.Buf.processIncoming(aUint8Array);
+  },
+
+  handleChromeMessage: function(aMessage) {
+    let clientId = aMessage.rilMessageClientId;
+    if (clientId != null) {
+      let context = this._contexts[clientId];
+      context.RIL.handleChromeMessage(aMessage);
+      return;
+    }
+
+    if (DEBUG) debug("Received global chrome message " + JSON.stringify(aMessage));
+    let method = this[aMessage.rilMessageType];
+    if (typeof method != "function") {
+      if (DEBUG) {
+        debug("Don't know what to do");
+      }
+      return;
+    }
+    method.call(this, aMessage);
+  },
+
+  setInitialOptions: function(aOptions) {
+    DEBUG = DEBUG_WORKER || aOptions.debug;
+    RIL_EMERGENCY_NUMBERS = aOptions.rilEmergencyNumbers;
+    RIL_CELLBROADCAST_DISABLED = aOptions.cellBroadcastDisabled;
+    RIL_CLIR_MODE = aOptions.clirMode;
+
+    let quirks = aOptions.quirks;
+    RILQUIRKS_CALLSTATE_EXTRA_UINT32 = quirks.callstateExtraUint32;
+    RILQUIRKS_V5_LEGACY = quirks.v5Legacy;
+    RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = quirks.requestUseDialEmergencyCall;
+    RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = quirks.simAppStateExtraFields;
+    RILQUIRKS_EXTRA_UINT32_2ND_CALL = quirks.extraUint2ndCall;
+    RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT = quirks.haveQueryIccLockRetryCount;
+    RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD = quirks.sendStkProfileDownload;
+    RILQUIRKS_DATA_REGISTRATION_ON_DEMAND = quirks.dataRegistrationOnDemand;
+  },
+
+  registerClient: function(aOptions) {
+    let clientId = aOptions.clientId;
+    this._contexts[clientId] = new Context(clientId);
+  },
+};
+
+function onRILMessage(aClientId, aUint8Array) {
+  ContextPool.handleRilMessage(aClientId, aUint8Array);
 }
 
 onmessage = function onmessage(event) {
-  RIL.handleChromeMessage(event.data);
+  ContextPool.handleChromeMessage(event.data);
 };
 
 onerror = function onerror(event) {
-  if (DEBUG) debug("RIL Worker error" + event.message + "\n");
-};
+  if (DEBUG) debug("onerror" + event.message + "\n");
+};
--- a/dom/system/gonk/tests/header_helpers.js
+++ b/dom/system/gonk/tests/header_helpers.js
@@ -38,25 +38,21 @@ function newWorker(custom_ns) {
     postMessage: function(message) {
     },
 
     // Define these variables inside the worker scope so ES5 strict mode
     // doesn't flip out.
     onmessage: undefined,
     onerror: undefined,
 
-    CLIENT_ID: 0,
     DEBUG: true
   };
   // The 'self' variable in a worker points to the worker's own namespace.
   worker_ns.self = worker_ns;
 
-  // systemlibs.js utilizes ctypes for loading native libraries.
-  Cu.import("resource://gre/modules/ctypes.jsm", worker_ns);
-
   // Copy the custom definitions over.
   for (let key in custom_ns) {
     worker_ns[key] = custom_ns[key];
   }
 
   // fake require() for toolkit/components/workerloader/require.js
   let require = (function() {
     return function require(script) {
@@ -71,16 +67,19 @@ function newWorker(custom_ns) {
     value: require,
     enumerable: true,
     configurable: false
   });
 
   // Load the RIL worker itself.
   worker_ns.importScripts("ril_worker.js");
 
+  // Register at least one client.
+  worker_ns.ContextPool.registerClient({ clientId: 0 });
+
   return worker_ns;
 }
 
 /**
  * Create a parcel suitable for postRILMessage().
  *
  * @param fakeParcelSize
  *        Value to be written to parcel size field for testing
--- a/dom/system/gonk/tests/test_ril_worker_barring_password.js
+++ b/dom/system/gonk/tests/test_ril_worker_barring_password.js
@@ -10,39 +10,41 @@ function run_test() {
 const PIN = "0000";
 const NEW_PIN = "1234";
 
 /**
  * Helper function.
  */
 function newUint8Worker() {
   let worker = newWorker();
+  let context = worker.ContextPool._contexts[0];
   let index = 0; // index for read
   let buf = [];
 
-  worker.Buf.writeUint8 = function(value) {
+  context.Buf.writeUint8 = function(value) {
     buf.push(value);
   };
 
-  worker.Buf.readUint8 = function() {
+  context.Buf.readUint8 = function() {
     return buf[index++];
   };
 
-  worker.Buf.seekIncoming = function(offset) {
+  context.Buf.seekIncoming = function(offset) {
     index += offset;
   };
 
   worker.debug = do_print;
 
   return worker;
 }
 
 add_test(function test_change_call_barring_password() {
   let worker = newUint8Worker();
-  let buf = worker.Buf;
+  let context = worker.ContextPool._contexts[0];
+  let buf = context.Buf;
 
   function do_test(facility, pin, newPin) {
     buf.sendParcel = function fakeSendParcel () {
       // Request Type.
       do_check_eq(this.readInt32(), REQUEST_CHANGE_BARRING_PASSWORD);
 
       // Token : we don't care.
       this.readInt32();
@@ -50,17 +52,17 @@ add_test(function test_change_call_barri
       let parcel = this.readStringList();
       do_check_eq(parcel.length, 3);
       do_check_eq(parcel[0], facility);
       do_check_eq(parcel[1], pin);
       do_check_eq(parcel[2], newPin);
     };
 
     let options = {facility: facility, pin: pin, newPin: newPin};
-    worker.RIL.changeCallBarringPassword(options);
+    context.RIL.changeCallBarringPassword(options);
   }
 
   do_test(ICC_CB_FACILITY_BA_ALL, PIN, NEW_PIN);
 
   run_next_test();
 });
 
 add_test(function test_check_change_call_barring_password_result() {
@@ -68,20 +70,21 @@ add_test(function test_check_change_call
   let worker = newWorker({
     postMessage: function(message) {
       do_check_eq(barringPasswordOptions.pin, PIN);
       do_check_eq(barringPasswordOptions.newPin, NEW_PIN);
       do_check_eq(message.errorMsg, GECKO_ERROR_SUCCESS);
     }
   });
 
-  worker.RIL.changeCallBarringPassword =
+  let context = worker.ContextPool._contexts[0];
+  context.RIL.changeCallBarringPassword =
     function fakeChangeCallBarringPassword(options) {
       barringPasswordOptions = options;
-      worker.RIL[REQUEST_CHANGE_BARRING_PASSWORD](0, {
+      context.RIL[REQUEST_CHANGE_BARRING_PASSWORD](0, {
         rilRequestError: ERROR_SUCCESS
       });
     }
 
-  worker.RIL.changeCallBarringPassword({pin: PIN, newPin: NEW_PIN});
+  context.RIL.changeCallBarringPassword({pin: PIN, newPin: NEW_PIN});
 
   run_next_test();
 });
--- a/dom/system/gonk/tests/test_ril_worker_buf.js
+++ b/dom/system/gonk/tests/test_ril_worker_buf.js
@@ -26,55 +26,57 @@ function add_test_incoming_parcel(parcel
 
     if (!parcel) {
       parcel = newIncomingParcel(-1,
                                  worker.RESPONSE_TYPE_UNSOLICITED,
                                  worker.REQUEST_VOICE_REGISTRATION_STATE,
                                  [0, 0, 0, 0]);
     }
 
+    let context = worker.ContextPool._contexts[0];
     // supports only requests less or equal than UINT8_MAX(255).
-    let buf = worker.Buf;
+    let buf = context.Buf;
     let request = parcel[buf.PARCEL_SIZE_SIZE + buf.UINT32_SIZE];
-    worker.RIL[request] = function ril_request_handler() {
-      handler(worker);
-      worker.postMessage();
+    context.RIL[request] = function ril_request_handler() {
+      handler.apply(this, arguments);
     };
 
-    worker.onRILMessage(parcel);
+    worker.onRILMessage(0, parcel);
 
     // end of incoming parcel's trip, let's do next test.
     run_next_test();
   });
 }
 
 // Test normal parcel handling.
 add_test_incoming_parcel(null,
-  function test_normal_parcel_handling(worker) {
+  function test_normal_parcel_handling() {
+    let self = this;
     do_check_throws(function normal_handler() {
       // reads exactly the same size, should not throw anything.
-      worker.Buf.readInt32();
+      self.context.Buf.readInt32();
     });
   }
 );
 
 // Test parcel under read.
 add_test_incoming_parcel(null,
-  function test_parcel_under_read(worker) {
+  function test_parcel_under_read() {
+    let self = this;
     do_check_throws(function under_read_handler() {
       // reads less than parcel size, should not throw.
-      worker.Buf.readUint16();
+      self.context.Buf.readUint16();
     });
   }
 );
 
 // Test parcel over read.
 add_test_incoming_parcel(null,
-  function test_parcel_over_read(worker) {
-    let buf = worker.Buf;
+  function test_parcel_over_read() {
+    let buf = this.context.Buf;
 
     // read all data available
     while (buf.readAvailable > 0) {
       buf.readUint8();
     }
 
     do_check_throws(function over_read_handler() {
       // reads more than parcel size, should throw an error.
@@ -89,31 +91,32 @@ add_test(function test_incoming_parcel_b
     postRILMessage: function(data) {
       // do nothing
     },
     postMessage: function(message) {
       // do nothing
     }
   });
 
+  let context = worker.ContextPool._contexts[0];
   // A convenient alias.
-  let buf = worker.Buf;
+  let buf = context.Buf;
 
   // Allocate an array of specified size and set each of its elements to value.
   function calloc(length, value) {
     let array = new Array(length);
     for (let i = 0; i < length; i++) {
       array[i] = value;
     }
     return array;
   }
 
   // Do nothing in handleParcel().
   let request = worker.REQUEST_VOICE_REGISTRATION_STATE;
-  worker.RIL[request] = null;
+  context.RIL[request] = null;
 
   // Prepare two parcels, whose sizes are both smaller than the incoming buffer
   // size but larger when combined, to trigger the bug.
   let pA_dataLength = buf.incomingBufferLength / 2;
   let pA = newIncomingParcel(-1,
                              worker.RESPONSE_TYPE_UNSOLICITED,
                              request,
                              calloc(pA_dataLength, 1));
@@ -123,50 +126,50 @@ add_test(function test_incoming_parcel_b
   let pB = newIncomingParcel(-1,
                              worker.RESPONSE_TYPE_UNSOLICITED,
                              request,
                              calloc(pB_dataLength, 1));
   let pB_parcelSize = pB.length - buf.PARCEL_SIZE_SIZE;
 
   // First, send an incomplete pA and verifies related data pointer:
   let p1 = pA.subarray(0, pA.length - 1);
-  worker.onRILMessage(p1);
+  worker.onRILMessage(0, p1);
   // The parcel should not have been processed.
   do_check_eq(buf.readAvailable, 0);
   // buf.currentParcelSize should have been set because incoming data has more
   // than 4 octets.
   do_check_eq(buf.currentParcelSize, pA_parcelSize);
   // buf.readIncoming should contains remaining unconsumed octets count.
   do_check_eq(buf.readIncoming, p1.length - buf.PARCEL_SIZE_SIZE);
   // buf.incomingWriteIndex should be ready to accept the last octet.
   do_check_eq(buf.incomingWriteIndex, p1.length);
 
   // Second, send the last octet of pA and whole pB. The Buf should now expand
   // to cover both pA & pB.
   let p2 = new Uint8Array(1 + pB.length);
   p2.set(pA.subarray(pA.length - 1), 0);
   p2.set(pB, 1);
-  worker.onRILMessage(p2);
+  worker.onRILMessage(0, p2);
   // The parcels should have been both consumed.
   do_check_eq(buf.readAvailable, 0);
   // No parcel data remains.
   do_check_eq(buf.currentParcelSize, 0);
   // No parcel data remains.
   do_check_eq(buf.readIncoming, 0);
   // The Buf should now expand to cover both pA & pB.
   do_check_eq(buf.incomingWriteIndex, pA.length + pB.length);
 
   // end of incoming parcel's trip, let's do next test.
   run_next_test();
 });
 
 // Test Buf.readUint8Array.
 add_test_incoming_parcel(null,
-  function test_buf_readUint8Array(worker) {
-    let buf = worker.Buf;
+  function test_buf_readUint8Array() {
+    let buf = this.context.Buf;
 
     let u8array = buf.readUint8Array(1);
     do_check_eq(u8array instanceof Uint8Array, true);
     do_check_eq(u8array.length, 1);
     do_check_eq(buf.readAvailable, 3);
 
     u8array = buf.readUint8Array(2);
     do_check_eq(u8array.length, 2);
--- a/dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js
+++ b/dom/system/gonk/tests/test_ril_worker_cdma_info_rec.js
@@ -18,25 +18,26 @@ function newWorkerWithParcel(parcelBuf) 
     postMessage: function(message) {
       // Do nothing
     }
   });
 
   let index = 0; // index for read
   let buf = parcelBuf;
 
-  worker.Buf.readUint8 = function() {
+  let context = worker.ContextPool._contexts[0];
+  context.Buf.readUint8 = function() {
     return buf[index++];
   };
 
-  worker.Buf.readUint16 = function() {
+  context.Buf.readUint16 = function() {
     return buf[index++];
   };
 
-  worker.Buf.readInt32 = function() {
+  context.Buf.readInt32 = function() {
     return buf[index++];
   };
 
   return worker;
 }
 
 // Test CDMA information record decoder.
 
@@ -45,17 +46,18 @@ function newWorkerWithParcel(parcelBuf) 
  */
 add_test(function test_display() {
   let worker = newWorkerWithParcel([
                 0x01, // one inforemation record
                 0x00, // type: display
                 0x09, // length: 9
                 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E, 0x66,
                 0x6F, 0x00]);
-  let helper = worker.CdmaPDUHelper;
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.CdmaPDUHelper;
   let record = helper.decodeInformationRecord();
 
   do_check_eq(record.display, "Test Info");
 
   run_next_test();
 });
 
 /**
@@ -67,17 +69,18 @@ add_test(function test_extended_display(
                 0x07, // type: extended display
                 0x0E, // length: 14
                 0x80, // header byte
                 0x80, // Blank
                 0x81, // Skip
                 0x9B, // Text
                 0x09, 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E,
                 0x66, 0x6F, 0x00]);
-  let helper = worker.CdmaPDUHelper;
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.CdmaPDUHelper;
   let record = helper.decodeInformationRecord();
 
   do_check_eq(record.extendedDisplay.indicator, 1);
   do_check_eq(record.extendedDisplay.type, 0);
   do_check_eq(record.extendedDisplay.records.length, 3);
   do_check_eq(record.extendedDisplay.records[0].tag, 0x80);
   do_check_eq(record.extendedDisplay.records[1].tag, 0x81);
   do_check_eq(record.extendedDisplay.records[2].tag, 0x9B);
@@ -98,17 +101,18 @@ add_test(function test_mixed() {
                 0x07, // type: extended display
                 0x0E, // length: 14
                 0x80, // header byte
                 0x80, // Blank
                 0x81, // Skip
                 0x9B, // Text
                 0x09, 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6E,
                 0x66, 0x6F, 0x00]);
-  let helper = worker.CdmaPDUHelper;
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.CdmaPDUHelper;
   let record = helper.decodeInformationRecord();
 
   do_check_eq(record.display, "Test Info");
   do_check_eq(record.extendedDisplay.indicator, 1);
   do_check_eq(record.extendedDisplay.type, 0);
   do_check_eq(record.extendedDisplay.records.length, 3);
   do_check_eq(record.extendedDisplay.records[0].tag, 0x80);
   do_check_eq(record.extendedDisplay.records[1].tag, 0x81);
--- a/dom/system/gonk/tests/test_ril_worker_cellbroadcast.js
+++ b/dom/system/gonk/tests/test_ril_worker_cellbroadcast.js
@@ -28,38 +28,39 @@ add_test(function test_ril_worker_GsmPDU
     postRILMessage: function(data) {
       // Do nothing
     },
     postMessage: function(message) {
       // Do nothing
     }
   });
 
+  let context = worker.ContextPool._contexts[0];
   function test_dcs(dcs, encoding, language, hasLanguageIndicator, messageClass) {
-    worker.Buf.readUint8 = function() {
+    context.Buf.readUint8 = function() {
       return dcs;
     };
 
     let msg = {};
-    worker.GsmPDUHelper.readCbDataCodingScheme(msg);
+    context.GsmPDUHelper.readCbDataCodingScheme(msg);
 
     do_check_eq(msg.dcs, dcs);
     do_check_eq(msg.encoding, encoding);
     do_check_eq(msg.language, language);
     do_check_eq(msg.hasLanguageIndicator, hasLanguageIndicator);
     do_check_eq(msg.messageClass, messageClass);
   }
 
   function test_dcs_throws(dcs) {
-    worker.Buf.readUint8 = function() {
+    context.Buf.readUint8 = function() {
       return dcs;
     };
 
     do_check_throws(function() {
-      worker.GsmPDUHelper.readCbDataCodingScheme({});
+      context.GsmPDUHelper.readCbDataCodingScheme({});
     }, "Unsupported CBS data coding scheme: " + dcs);
   }
 
   // Group 0000
   for (let i = 0; i < 16; i++) {
     test_dcs(i, PDU_DCS_MSG_CODING_7BITS_ALPHABET, CB_DCS_LANG_GROUP_1[i],
              false, GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]);
   }
@@ -137,35 +138,36 @@ add_test(function test_ril_worker_GsmPDU
     postRILMessage: function(data) {
       // Do nothing
     },
     postMessage: function(message) {
       // Do nothing
     }
   });
 
+  let context = worker.ContextPool._contexts[0];
   function test_data(options, expected) {
     let readIndex = 0;
-    worker.Buf.readUint8 = function() {
+    context.Buf.readUint8 = function() {
       return options[3][readIndex++];
     };
-    worker.Buf.readUint8Array = function(length) {
+    context.Buf.readUint8Array = function(length) {
       let array = new Uint8Array(length);
       for (let i = 0; i < length; i++) {
         array[i] = this.readUint8();
       }
       return array;
     };
 
     let msg = {
       encoding: options[0],
       language: options[1],
       hasLanguageIndicator: options[2]
     };
-    worker.GsmPDUHelper.readGsmCbData(msg, options[3].length);
+    context.GsmPDUHelper.readGsmCbData(msg, options[3].length);
 
     do_check_eq(msg.body, expected[0]);
     do_check_eq(msg.data == null, expected[1] == null);
     if (expected[1] != null) {
       do_check_eq(msg.data.length, expected[1].length);
       for (let i = 0; i < expected[1].length; i++) {
         do_check_eq(msg.data[i], expected[1][i]);
       }
@@ -213,17 +215,18 @@ add_test(function test_ril_worker__check
     postRILMessage: function(data) {
       // Do nothing
     },
     postMessage: function(message) {
       // Do nothing
     }
   });
 
-  let ril = worker.RIL;
+  let context = worker.ContextPool._contexts[0];
+  let ril = context.RIL;
 
   function test(from, to, expected) {
     do_check_eq(expected, ril._checkCellBroadcastMMISettable(from, to));
   }
 
   test(-2, -1, false);
   test(-1, 0, false);
   test(0, 1, true);
@@ -263,17 +266,18 @@ add_test(function test_ril_worker__merge
     postRILMessage: function(data) {
       // Do nothing
     },
     postMessage: function(message) {
       // Do nothing
     }
   });
 
-  let ril = worker.RIL;
+  let context = worker.ContextPool._contexts[0];
+  let ril = context.RIL;
 
   function test(olist, from, to, expected) {
     let result = ril._mergeCellBroadcastConfigs(olist, from, to);
     do_check_eq(JSON.stringify(expected), JSON.stringify(result));
   }
 
   test(null, 0, 1, [0, 1]);
 
--- a/dom/system/gonk/tests/test_ril_worker_cellbroadcast_config.js
+++ b/dom/system/gonk/tests/test_ril_worker_cellbroadcast_config.js
@@ -11,37 +11,38 @@ add_test(function test_ril_worker_cellbr
   let worker = newWorker({
     postRILMessage: function(id, parcel) {
       // Do nothing
     },
     postMessage: function(message) {
       // Do nothing
     }
   });
+  let context = worker.ContextPool._contexts[0];
 
   let parcelTypes = [];
-  let org_newParcel = worker.Buf.newParcel;
-  worker.Buf.newParcel = function(type, options) {
+  let org_newParcel = context.Buf.newParcel;
+  context.Buf.newParcel = function(type, options) {
     parcelTypes.push(type);
     org_newParcel.apply(this, arguments);
   };
 
   function setup(isCdma) {
-    worker.RIL._isCdma = isCdma;
-    worker.RIL.cellBroadcastDisabled = false;
-    worker.RIL.mergedCellBroadcastConfig = [1, 2, 4, 7];  // 1, 4-6
+    context.RIL._isCdma = isCdma;
+    context.RIL.cellBroadcastDisabled = false;
+    context.RIL.mergedCellBroadcastConfig = [1, 2, 4, 7];  // 1, 4-6
     parcelTypes = [];
   }
 
   function test(isCdma, expectedRequest) {
     setup(isCdma);
-    worker.RIL.setCellBroadcastDisabled({disabled: true});
+    context.RIL.setCellBroadcastDisabled({disabled: true});
     // Makesure that request parcel is sent out.
     do_check_neq(parcelTypes.indexOf(expectedRequest), -1);
-    do_check_eq(worker.RIL.cellBroadcastDisabled, true);
+    do_check_eq(context.RIL.cellBroadcastDisabled, true);
   }
 
   test(false, REQUEST_GSM_SMS_BROADCAST_ACTIVATION);
   test(true, REQUEST_CDMA_SMS_BROADCAST_ACTIVATION);
 
   run_next_test();
 });
 
@@ -50,16 +51,17 @@ add_test(function test_ril_worker_cellbr
   let worker = newWorker({
     postRILMessage: function(id, parcel) {
       currentParcel = parcel;
     },
     postMessage: function(message) {
       // Do nothing
     }
   });
+  let context = worker.ContextPool._contexts[0];
 
   function U32ArrayFromParcelArray(pa) {
     do_print(pa);
     let out = [];
     for (let i = 0; i < pa.length; i += 4) {
       let data = pa[i] + (pa[i+1] << 8) + (pa[i+2] << 16) + (pa[i+3] << 24);
       out.push(data);
     }
@@ -77,18 +79,18 @@ add_test(function test_ril_worker_cellbr
         return;
       }
 
       found = true;
       // Check parcel. Data start from 4th word (32bit)
       do_check_eq(u32Parcel.slice(3).toString(), expected);
     };
 
-    worker.RIL._isCdma = isCdma;
-    worker.RIL.setSmsBroadcastConfig(configs);
+    context.RIL._isCdma = isCdma;
+    context.RIL.setSmsBroadcastConfig(configs);
 
     // Makesure that request parcel is sent out.
     do_check_true(found);
   }
 
   // (GSM) RIL writes the following data to outgoing parcel:
   //   nums [(from, to, 0, 0xFF, 1), ... ]
   test(false,
@@ -108,22 +110,23 @@ add_test(function test_ril_worker_cellbr
   let worker = newWorker({
     postRILMessage: function(id, parcel) {
       // Do nothing
     },
     postMessage: function(message) {
       // Do nothing
     }
   });
+  let context = worker.ContextPool._contexts[0];
 
   function test(isCdma, configs, expected) {
-    worker.RIL._isCdma = isCdma;
-    worker.RIL.cellBroadcastConfigs = configs;
-    worker.RIL._mergeAllCellBroadcastConfigs();
-    do_check_eq(worker.RIL.mergedCellBroadcastConfig.toString(), expected);
+    context.RIL._isCdma = isCdma;
+    context.RIL.cellBroadcastConfigs = configs;
+    context.RIL._mergeAllCellBroadcastConfigs();
+    do_check_eq(context.RIL.mergedCellBroadcastConfig.toString(), expected);
   }
 
   let configs = {
     MMI:    [1, 2, 4, 7],   // 1, 4-6
     CBMI:   [6, 9],         // 6-8
     CBMID:  [8, 11],        // 8-10
     CBMIR:  [10, 13]        // 10-12
   };
--- a/dom/system/gonk/tests/test_ril_worker_cf.js
+++ b/dom/system/gonk/tests/test_ril_worker_cf.js
@@ -11,17 +11,18 @@ function toaFromString(number) {
   let worker = newWorker({
     postRILMessage: function(data) {
       // Do nothing
     },
     postMessage: function(message) {
       // Do nothing
     }
   });
-  return worker.RIL._toaFromString(number);
+  let context = worker.ContextPool._contexts[0];
+  return context.RIL._toaFromString(number);
 }
 
 add_test(function test_toaFromString_empty() {
   let retval = toaFromString("");
 
   do_check_eq(retval, TOA_UNKNOWN);
 
   run_next_test();
@@ -68,24 +69,25 @@ function _getWorker() {
       return _worker;
     }
   };
 }
 
 add_test(function test_setCallForward_unconditional() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.RIL.setCallForward = function fakeSetCallForward(options) {
-    worker.RIL[REQUEST_SET_CALL_FORWARD](0, {
+  context.RIL.setCallForward = function fakeSetCallForward(options) {
+    context.RIL[REQUEST_SET_CALL_FORWARD](0, {
       rilRequestError: ERROR_SUCCESS
     });
   };
 
-  worker.RIL.setCallForward({
+  context.RIL.setCallForward({
     action: Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_ACTION_REGISTRATION,
     reason: Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_UNCONDITIONAL,
     serviceClass: ICC_SERVICE_CLASS_VOICE,
     number: "666222333",
     timeSeconds: 10
   });
 
   let postedMessage = workerHelper.postedMessage;
@@ -94,46 +96,47 @@ add_test(function test_setCallForward_un
   do_check_true(postedMessage.success);
 
   run_next_test();
 });
 
 add_test(function test_queryCallForwardStatus_unconditional() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.RIL.setCallForward = function fakeSetCallForward(options) {
-    worker.RIL[REQUEST_SET_CALL_FORWARD](0, {
+  context.RIL.setCallForward = function fakeSetCallForward(options) {
+    context.RIL[REQUEST_SET_CALL_FORWARD](0, {
       rilRequestError: ERROR_SUCCESS
     });
   };
 
-  worker.Buf.readInt32 = function fakeReadUint32() {
-    return worker.Buf.int32Array.pop();
+  context.Buf.readInt32 = function fakeReadUint32() {
+    return context.Buf.int32Array.pop();
   };
 
-  worker.Buf.readString = function fakeReadString() {
+  context.Buf.readString = function fakeReadString() {
     return "+34666222333";
   };
 
-  worker.RIL.queryCallForwardStatus = function fakeQueryCallForward(options) {
-    worker.Buf.int32Array = [
+  context.RIL.queryCallForwardStatus = function fakeQueryCallForward(options) {
+    context.Buf.int32Array = [
       0,   // rules.timeSeconds
       145, // rules.toa
       49,  // rules.serviceClass
       Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_UNCONDITIONAL, // rules.reason
       1,   // rules.active
       1    // rulesLength
     ];
-    worker.RIL[REQUEST_QUERY_CALL_FORWARD_STATUS](1, {
+    context.RIL[REQUEST_QUERY_CALL_FORWARD_STATUS](1, {
       rilRequestError: ERROR_SUCCESS
     });
   };
 
-  worker.RIL.queryCallForwardStatus({
+  context.RIL.queryCallForwardStatus({
     action: Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_ACTION_QUERY_STATUS,
     reason: Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_UNCONDITIONAL,
     serviceClass: ICC_SERVICE_CLASS_VOICE,
     number: "666222333",
     timeSeconds: 10
   });
 
   let postedMessage = workerHelper.postedMessage;
--- a/dom/system/gonk/tests/test_ril_worker_clip.js
+++ b/dom/system/gonk/tests/test_ril_worker_clip.js
@@ -24,59 +24,61 @@ function _getWorker() {
       return _worker;
     }
   };
 }
 
 add_test(function test_queryCLIP_provisioned() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.Buf.readInt32 = function fakeReadUint32() {
-    return worker.Buf.int32Array.pop();
+  context.Buf.readInt32 = function fakeReadUint32() {
+    return context.Buf.int32Array.pop();
   };
 
-  worker.RIL.queryCLIP = function fakeQueryCLIP(options) {
-    worker.Buf.int32Array = [
+  context.RIL.queryCLIP = function fakeQueryCLIP(options) {
+    context.Buf.int32Array = [
       1,  // CLIP provisioned.
       1   // Length.
     ];
-    worker.RIL[REQUEST_QUERY_CLIP](1, {
+    context.RIL[REQUEST_QUERY_CLIP](1, {
       rilRequestError: ERROR_SUCCESS
     });
   };
 
-  worker.RIL.queryCLIP({});
+  context.RIL.queryCLIP({});
 
   let postedMessage = workerHelper.postedMessage;
 
   do_check_eq(postedMessage.errorMsg, undefined);
   do_check_true(postedMessage.success);
   do_check_eq(postedMessage.provisioned, 1);
   run_next_test();
 });
 
 add_test(function test_getCLIP_error_generic_failure_invalid_length() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.Buf.readInt32 = function fakeReadUint32() {
-    return worker.Buf.int32Array.pop();
+  context.Buf.readInt32 = function fakeReadUint32() {
+    return context.Buf.int32Array.pop();
   };
 
-  worker.RIL.queryCLIP = function fakeQueryCLIP(options) {
-    worker.Buf.int32Array = [
+  context.RIL.queryCLIP = function fakeQueryCLIP(options) {
+    context.Buf.int32Array = [
       1,  // CLIP provisioned.
       0   // Length.
     ];
-    worker.RIL[REQUEST_QUERY_CLIP](1, {
+    context.RIL[REQUEST_QUERY_CLIP](1, {
       rilRequestError: ERROR_SUCCESS
     });
   };
 
-  worker.RIL.queryCLIP({});
+  context.RIL.queryCLIP({});
 
   let postedMessage = workerHelper.postedMessage;
 
   do_check_eq(postedMessage.errorMsg, "GenericFailure");
   do_check_false(postedMessage.success);
   run_next_test();
 });
--- a/dom/system/gonk/tests/test_ril_worker_clir.js
+++ b/dom/system/gonk/tests/test_ril_worker_clir.js
@@ -33,112 +33,116 @@ function _getWorker() {
       return _worker;
     }
   };
 }
 
 add_test(function test_setCLIR_success() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.RIL.setCLIR = function fakeSetCLIR(options) {
-    worker.RIL[REQUEST_SET_CLIR](0, {
+  context.RIL.setCLIR = function fakeSetCLIR(options) {
+    context.RIL[REQUEST_SET_CLIR](0, {
       rilMessageType: "setCLIR",
       rilRequestError: ERROR_SUCCESS
     });
   };
 
-  worker.RIL.setCLIR({
+  context.RIL.setCLIR({
     clirMode: CLIR_DEFAULT
   });
 
   let postedMessage = workerHelper.postedMessage;
 
   do_check_eq(postedMessage.errorMsg, undefined);
   do_check_true(postedMessage.success);
 
   run_next_test();
 });
 
 add_test(function test_setCLIR_generic_failure() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.RIL.setCLIR = function fakeSetCLIR(options) {
-    worker.RIL[REQUEST_SET_CLIR](0, {
+  context.RIL.setCLIR = function fakeSetCLIR(options) {
+    context.RIL[REQUEST_SET_CLIR](0, {
       rilMessageType: "setCLIR",
       rilRequestError: ERROR_GENERIC_FAILURE
     });
   };
 
-  worker.RIL.setCLIR({
+  context.RIL.setCLIR({
     clirMode: CLIR_DEFAULT
   });
 
   let postedMessage = workerHelper.postedMessage;
 
   do_check_eq(postedMessage.errorMsg, "GenericFailure");
   do_check_false(postedMessage.success);
 
   run_next_test();
 });
 
 add_test(function test_getCLIR_n0_m1() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.Buf.readInt32 = function fakeReadUint32() {
-    return worker.Buf.int32Array.pop();
+  context.Buf.readInt32 = function fakeReadUint32() {
+    return context.Buf.int32Array.pop();
   };
 
-  worker.RIL.getCLIR = function fakeGetCLIR(options) {
-    worker.Buf.int32Array = [
+  context.RIL.getCLIR = function fakeGetCLIR(options) {
+    context.Buf.int32Array = [
       1,  // Presentation indicator is used according to the subscription
           // of the CLIR service.
       0,  // CLIR provisioned in permanent mode.
       2   // Length.
     ];
-    worker.RIL[REQUEST_GET_CLIR](1, {
+    context.RIL[REQUEST_GET_CLIR](1, {
       rilMessageType: "setCLIR",
       rilRequestError: ERROR_SUCCESS
     });
   };
 
-  worker.RIL.getCLIR({});
+  context.RIL.getCLIR({});
 
   let postedMessage = workerHelper.postedMessage;
 
   do_check_eq(postedMessage.errorMsg, undefined);
   do_check_true(postedMessage.success);
   do_check_eq(postedMessage.n, 0);
   do_check_eq(postedMessage.m, 1);
   run_next_test();
 });
 
 add_test(function test_getCLIR_error_generic_failure_invalid_length() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.Buf.readInt32 = function fakeReadUint32() {
-    return worker.Buf.int32Array.pop();
+  context.Buf.readInt32 = function fakeReadUint32() {
+    return context.Buf.int32Array.pop();
   };
 
-  worker.RIL.getCLIR = function fakeGetCLIR(options) {
-    worker.Buf.int32Array = [
+  context.RIL.getCLIR = function fakeGetCLIR(options) {
+    context.Buf.int32Array = [
       1,  // Presentation indicator is used according to the subscription
           // of the CLIR service.
       0,  // CLIR provisioned in permanent mode.
       0   // Length (invalid one).
     ];
-    worker.RIL[REQUEST_GET_CLIR](1, {
+    context.RIL[REQUEST_GET_CLIR](1, {
       rilMessageType: "setCLIR",
       rilRequestError: ERROR_SUCCESS
     });
   };
 
-  worker.RIL.getCLIR({});
+  context.RIL.getCLIR({});
 
   let postedMessage = workerHelper.postedMessage;
 
   do_check_eq(postedMessage.errorMsg, "GenericFailure");
   do_check_false(postedMessage.success);
   run_next_test();
 });
--- a/dom/system/gonk/tests/test_ril_worker_cw.js
+++ b/dom/system/gonk/tests/test_ril_worker_cw.js
@@ -24,107 +24,111 @@ function _getWorker() {
       return _worker;
     }
   };
 }
 
 add_test(function test_setCallWaiting_success() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.RIL.setCallWaiting = function fakeSetCallWaiting(options) {
-    worker.RIL[REQUEST_SET_CALL_WAITING](0, {
+  context.RIL.setCallWaiting = function fakeSetCallWaiting(options) {
+    context.RIL[REQUEST_SET_CALL_WAITING](0, {
       rilRequestError: ERROR_SUCCESS
     });
   };
 
-  worker.RIL.setCallWaiting({
+  context.RIL.setCallWaiting({
     enabled: true
   });
 
   let postedMessage = workerHelper.postedMessage;
 
   do_check_eq(postedMessage.errorMsg, undefined);
   do_check_true(postedMessage.success);
 
   run_next_test();
 });
 
 add_test(function test_setCallWaiting_generic_failure() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.RIL.setCallWaiting = function fakeSetCallWaiting(options) {
-    worker.RIL[REQUEST_SET_CALL_WAITING](0, {
+  context.RIL.setCallWaiting = function fakeSetCallWaiting(options) {
+    context.RIL[REQUEST_SET_CALL_WAITING](0, {
       rilRequestError: ERROR_GENERIC_FAILURE
     });
   };
 
-  worker.RIL.setCallWaiting({
+  context.RIL.setCallWaiting({
     enabled: true
   });
 
   let postedMessage = workerHelper.postedMessage;
 
   do_check_eq(postedMessage.errorMsg, "GenericFailure");
   do_check_false(postedMessage.success);
 
   run_next_test();
 });
 
 add_test(function test_queryCallWaiting_success_enabled_true() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.Buf.readInt32 = function fakeReadUint32() {
-    return worker.Buf.int32Array.pop();
+  context.Buf.readInt32 = function fakeReadUint32() {
+    return context.Buf.int32Array.pop();
   };
 
-  worker.RIL.queryCallWaiting = function fakeQueryCallWaiting(options) {
-    worker.Buf.int32Array = [
+  context.RIL.queryCallWaiting = function fakeQueryCallWaiting(options) {
+    context.Buf.int32Array = [
       1,  // serviceClass
       1,  // enabled
       1   // length
     ];
-    worker.RIL[REQUEST_QUERY_CALL_WAITING](1, {
+    context.RIL[REQUEST_QUERY_CALL_WAITING](1, {
       rilRequestError: ERROR_SUCCESS
     });
   };
 
-  worker.RIL.queryCallWaiting({});
+  context.RIL.queryCallWaiting({});
 
   let postedMessage = workerHelper.postedMessage;
 
   do_check_eq(postedMessage.errorMsg, undefined);
   do_check_true(postedMessage.success);
   do_check_eq(postedMessage.length, 1);
   do_check_true(postedMessage.enabled);
   run_next_test();
 });
 
 add_test(function test_queryCallWaiting_success_enabled_false() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.Buf.readInt32 = function fakeReadUint32() {
-    return worker.Buf.int32Array.pop();
+  context.Buf.readInt32 = function fakeReadUint32() {
+    return context.Buf.int32Array.pop();
   };
 
-  worker.RIL.queryCallWaiting = function fakeQueryCallWaiting(options) {
-    worker.Buf.int32Array = [
+  context.RIL.queryCallWaiting = function fakeQueryCallWaiting(options) {
+    context.Buf.int32Array = [
       1,  // serviceClass
       0,  // enabled
       1   // length
     ];
-    worker.RIL[REQUEST_QUERY_CALL_WAITING](1, {
+    context.RIL[REQUEST_QUERY_CALL_WAITING](1, {
       rilRequestError: ERROR_SUCCESS
     });
   };
 
-  worker.RIL.queryCallWaiting({});
+  context.RIL.queryCallWaiting({});
 
   let postedMessage = workerHelper.postedMessage;
 
   do_check_eq(postedMessage.errorMsg, undefined);
   do_check_true(postedMessage.success);
   do_check_eq(postedMessage.length, 1);
   do_check_false(postedMessage.enabled);
   run_next_test();
--- a/dom/system/gonk/tests/test_ril_worker_ecm.js
+++ b/dom/system/gonk/tests/test_ril_worker_ecm.js
@@ -51,131 +51,136 @@ function fireTimeout() {
     timeoutCallback();
     timeoutCallback = null;
   }
 }
 
 add_test(function test_enter_emergencyCbMode() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
   // Do it twice. Should always send the event.
   for (let i = 0; i < 2; ++i) {
-    worker.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
+    context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
     let postedMessage = workerHelper.postedMessage;
 
     // Should store the mode.
-    do_check_eq(worker.RIL._isInEmergencyCbMode, true);
+    do_check_eq(context.RIL._isInEmergencyCbMode, true);
 
     // Should notify change.
     do_check_eq(postedMessage.rilMessageType, "emergencyCbModeChange");
     do_check_eq(postedMessage.active, true);
     do_check_eq(postedMessage.timeoutMs, TIMEOUT_VALUE);
 
     // Should start timer.
-    do_check_eq(worker.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
+    do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
   }
 
   run_next_test();
 });
 
 add_test(function test_exit_emergencyCbMode() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
-  worker.RIL[UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE]();
+  context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
+  context.RIL[UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE]();
   let postedMessage = workerHelper.postedMessage;
 
   // Should store the mode.
-  do_check_eq(worker.RIL._isInEmergencyCbMode, false);
+  do_check_eq(context.RIL._isInEmergencyCbMode, false);
 
   // Should notify change.
   do_check_eq(postedMessage.rilMessageType, "emergencyCbModeChange");
   do_check_eq(postedMessage.active, false);
 
   // Should clear timer.
-  do_check_eq(worker.RIL._exitEmergencyCbModeTimeoutID, null);
+  do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, null);
 
   run_next_test();
 });
 
 add_test(function test_request_exit_emergencyCbMode_when_timeout() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
-  do_check_eq(worker.RIL._isInEmergencyCbMode, true);
-  do_check_eq(worker.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
+  context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
+  do_check_eq(context.RIL._isInEmergencyCbMode, true);
+  do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
 
   let parcelTypes = [];
-  worker.Buf.newParcel = function(type, options) {
+  context.Buf.newParcel = function(type, options) {
     parcelTypes.push(type);
   };
 
   // Timeout.
   fireTimeout();
 
   // Should clear timeout event.
-  do_check_eq(worker.RIL._exitEmergencyCbModeTimeoutID, null);
+  do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, null);
 
   // Check indeed sent out REQUEST_EXIT_EMERGENCY_CALLBACK_MODE.
   do_check_neq(parcelTypes.indexOf(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE), -1);
 
   run_next_test();
 });
 
 add_test(function test_request_exit_emergencyCbMode_when_dial() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
-  do_check_eq(worker.RIL._isInEmergencyCbMode, true);
-  do_check_eq(worker.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
+  context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
+  do_check_eq(context.RIL._isInEmergencyCbMode, true);
+  do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
 
   let parcelTypes = [];
-  worker.Buf.newParcel = function(type, options) {
+  context.Buf.newParcel = function(type, options) {
     parcelTypes.push(type);
   };
 
   // Dial non-emergency call.
-  worker.RIL.dial({number: "0912345678",
+  context.RIL.dial({number: "0912345678",
                   isDialEmergency: false});
 
   // Should clear timeout event.
-  do_check_eq(worker.RIL._exitEmergencyCbModeTimeoutID, null);
+  do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, null);
 
   // Check indeed sent out REQUEST_EXIT_EMERGENCY_CALLBACK_MODE.
   do_check_neq(parcelTypes.indexOf(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE), -1);
 
   run_next_test();
 });
 
 add_test(function test_request_exit_emergencyCbMode_explicitly() {
   let workerHelper = _getWorker();
   let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
 
-  worker.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
-  do_check_eq(worker.RIL._isInEmergencyCbMode, true);
-  do_check_eq(worker.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
+  context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
+  do_check_eq(context.RIL._isInEmergencyCbMode, true);
+  do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
 
   let parcelTypes = [];
-  worker.Buf.newParcel = function(type, options) {
+  context.Buf.newParcel = function(type, options) {
     parcelTypes.push(type);
   };
 
-  worker.RIL.handleChromeMessage({rilMessageType: "exitEmergencyCbMode"});
-  worker.RIL[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE](1, {
+  context.RIL.handleChromeMessage({rilMessageType: "exitEmergencyCbMode"});
+  context.RIL[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE](1, {
     rilMessageType: "exitEmergencyCbMode",
     rilRequestError: ERROR_SUCCESS
   });
   let postedMessage = workerHelper.postedMessage;
 
   // Should clear timeout event.
-  do_check_eq(worker.RIL._exitEmergencyCbModeTimeoutID, null);
+  do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, null);
 
   // Check indeed sent out REQUEST_EXIT_EMERGENCY_CALLBACK_MODE.
   do_check_neq(parcelTypes.indexOf(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE), -1);
 
   // Send back the response.
   do_check_eq(postedMessage.rilMessageType, "exitEmergencyCbMode");
 
   run_next_test();
--- a/dom/system/gonk/tests/test_ril_worker_icc.js
+++ b/dom/system/gonk/tests/test_ril_worker_icc.js
@@ -10,40 +10,42 @@ function run_test() {
 /**
  * Helper function.
  */
 function newUint8Worker() {
   let worker = newWorker();
   let index = 0; // index for read
   let buf = [];
 
-  worker.Buf.writeUint8 = function(value) {
+  let context = worker.ContextPool._contexts[0];
+  context.Buf.writeUint8 = function(value) {
     buf.push(value);
   };
 
-  worker.Buf.readUint8 = function() {
+  context.Buf.readUint8 = function() {
     return buf[index++];
   };
 
-  worker.Buf.seekIncoming = function(offset) {
+  context.Buf.seekIncoming = function(offset) {
     index += offset;
   };
 
   worker.debug = do_print;
 
   return worker;
 }
 
 /**
  * Verify ICCPDUHelper#readICCUCS2String()
  */
 add_test(function test_read_icc_ucs2_string() {
   let worker = newUint8Worker();
-  let helper = worker.GsmPDUHelper;
-  let iccHelper = worker.ICCPDUHelper;
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
 
   // 0x80
   let text = "TEST";
   helper.writeUCS2String(text);
   // Also write two unused octets.
   let ffLen = 2;
   for (let i = 0; i < ffLen; i++) {
     helper.writeHexOctet(0xff);
@@ -71,18 +73,19 @@ add_test(function test_read_icc_ucs2_str
   run_next_test();
 });