[automerger] Check access to user and password fields in APN db am: 9a74213831 am: bee8ca8ca4 am: d1dd12f763 am: 32300ccada am: 3b5a28712a am: 0a5cc7f83b am: 0f8d9fb37d
am: 19e3398d3e

Change-Id: Ib355cb588cdbda3d5992c636e529064718f1e1ba
diff --git a/Android.mk b/Android.mk
index c824fff..3ff05c9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -8,6 +8,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 
 LOCAL_PACKAGE_NAME := TelephonyProvider
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 LOCAL_JAVA_LIBRARIES += telephony-common
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5ac7fab..31e5364 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -23,6 +23,7 @@
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+    <uses-permission android:name="android.permission.USE_RESERVED_DISK" />
 
     <protected-broadcast android:name="android.provider.action.EXTERNAL_PROVIDER_CHANGE" />
     <protected-broadcast android:name="android.intent.action.CONTENT_CHANGED" />
@@ -105,6 +106,12 @@
                   android:multiprocess="false"
                   android:writePermission="android.permission.MODIFY_PHONE_STATE" />
 
+        <provider android:name="CarrierIdProvider"
+                  android:authorities="carrier_id"
+                  android:exported="true"
+                  android:singleUser="true"
+                  android:multiprocess="false" />
+
         <service
             android:name=".TelephonyBackupAgent$DeferredSmsMmsRestoreService"
             android:exported="false" />
diff --git a/OWNERS b/OWNERS
index 691af77..0716d33 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,5 +1,9 @@
 amitmahajan@google.com
 fionaxu@google.com
-jminjie@google.com
+jackyu@google.com
 rgreenwalt@google.com
-tomtaylor@google.com
+refuhoo@google.com
+mpq@google.com
+jminjie@google.com
+shuoq@google.com
+
diff --git a/assets/carrier_list.pb b/assets/carrier_list.pb
new file mode 100644
index 0000000..856c5bc
--- /dev/null
+++ b/assets/carrier_list.pb
Binary files differ
diff --git a/assets/carrier_list.textpb b/assets/carrier_list.textpb
new file mode 100644
index 0000000..23196a5
--- /dev/null
+++ b/assets/carrier_list.textpb
@@ -0,0 +1,7806 @@
+carrier_id {
+  canonical_id: 1
+  carrier_name: "T-Mobile - US"
+  carrier_attribute {
+    mccmnc_tuple: "310026"
+    mccmnc_tuple: "310160"
+    mccmnc_tuple: "310200"
+    mccmnc_tuple: "310210"
+    mccmnc_tuple: "310220"
+    mccmnc_tuple: "310230"
+    mccmnc_tuple: "310240"
+    mccmnc_tuple: "310250"
+    mccmnc_tuple: "310260"
+    mccmnc_tuple: "31026"
+    mccmnc_tuple: "310270"
+    mccmnc_tuple: "310300"
+    mccmnc_tuple: "310310"
+    mccmnc_tuple: "310490"
+    mccmnc_tuple: "310530"
+    mccmnc_tuple: "310590"
+    mccmnc_tuple: "310640"
+    mccmnc_tuple: "310660"
+    mccmnc_tuple: "310800"
+  }
+}
+carrier_id {
+  canonical_id: 2
+  carrier_name: "EE"
+  carrier_attribute {
+    mccmnc_tuple: "23430"
+    imsi_prefix_xpattern: "2343041"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "23430"
+    gid1: "ee"
+    gid1: "eeff"
+  }
+}
+carrier_id {
+  canonical_id: 3
+  carrier_name: "Telekom"
+  carrier_attribute {
+    mccmnc_tuple: "26201"
+    mccmnc_tuple: "26206"
+    gid1: "01"
+    gid1: "02"
+    gid1: "03"
+    gid1: "04"
+    gid1: "99"
+    gid1: "4B"
+    gid1: "4b"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "26201"
+    mccmnc_tuple: "26206"
+    spn: "Telekom.de"
+    spn: "T-Mobile D"
+    spn: "Business"
+    spn: "Privat"
+  }
+}
+carrier_id {
+  canonical_id: 4
+  carrier_name: "T-Mobile/tele.ring"
+  carrier_attribute {
+    mccmnc_tuple: "23203"
+    gid1: "01"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "23207"
+    imsi_prefix_xpattern: "999999"
+  }
+}
+carrier_id {
+  canonical_id: 5
+  carrier_name: "T-Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "20416"
+    mccmnc_tuple: "20420"
+    gid1: "FF"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "20416"
+    mccmnc_tuple: "20420"
+    spn: "T-Mobile  NL"
+  }
+}
+carrier_id {
+  canonical_id: 6
+  carrier_name: "T-Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "23001"
+    spn: "T-Mobile CZ"
+    spn: "KAKTUS"
+    spn: "Mobil CZ"
+    spn: "RWE Mobil"
+    spn: "innogy"
+    spn: "PREmobil"
+  }
+}
+carrier_id {
+  canonical_id: 7
+  carrier_name: "T-Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "26002"
+    gid1: "11"
+    gid1: "12"
+    gid1: "16"
+    gid1: "17"
+    gid1: "21"
+    gid1: "22"
+    gid1: "24"
+    gid1: "26"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "26002"
+    spn: "T-Mobile.pl"
+    spn: "T-Mobile.pl Q"
+  }
+}
+carrier_id {
+  canonical_id: 8
+  carrier_name: "Magyar Telekom"
+  carrier_attribute {
+    mccmnc_tuple: "21630"
+    spn: "Telekom HU"
+    spn: "T-Mobile H"
+  }
+}
+carrier_id {
+  canonical_id: 9
+  carrier_name: "Hrvaski Telekom"
+  carrier_attribute {
+    mccmnc_tuple: "21901"
+    spn: "T-Mobile HR"
+    spn: "HT HR"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "21901"
+    gid1: "01"
+    gid1: "02"
+    gid1: "03"
+    gid1: "99"
+  }
+}
+carrier_id {
+  canonical_id: 10
+  carrier_name: "T-Mobile - ME"
+  carrier_attribute {
+    mccmnc_tuple: "22004"
+  }
+}
+carrier_id {
+  canonical_id: 11
+  carrier_name: "Slovak Telekom"
+  carrier_attribute {
+    mccmnc_tuple: "23102"
+    spn: "Telekom SK"
+    spn: "Juro.sk"
+  }
+}
+carrier_id {
+  canonical_id: 12
+  carrier_name: "T-Mobile - UA"
+  carrier_attribute {
+    mccmnc_tuple: "25502"
+  }
+}
+carrier_id {
+  canonical_id: 13
+  carrier_name: "Mkedonski Telecom AD Skopje"
+  carrier_attribute {
+    mccmnc_tuple: "29401"
+    spn: "Telekom.mk"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "29401"
+    gid1: "FF"
+  }
+}
+carrier_id {
+  canonical_id: 14
+  carrier_name: "A1"
+  carrier_attribute {
+    mccmnc_tuple: "23201"
+    mccmnc_tuple: "23211"
+    mccmnc_tuple: "23212"
+  }
+}
+carrier_id {
+  canonical_id: 15
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "50503"
+  }
+}
+carrier_id {
+  canonical_id: 16
+  carrier_name: "Swisscom"
+  carrier_attribute {
+    mccmnc_tuple: "22801"
+    spn: "Swisscom"
+  }
+}
+carrier_id {
+  canonical_id: 18
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "20205"
+    spn: "vodafone GR"
+    spn: "CU"
+    spn: "CU-X"
+  }
+}
+carrier_id {
+  canonical_id: 19
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "27201"
+    spn: "vodafone IE"
+    spn: "Vodafone IE"
+  }
+}
+carrier_id {
+  canonical_id: 20
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "20404"
+    imsi_prefix_xpattern: "204040"
+    imsi_prefix_xpattern: "204041"
+    imsi_prefix_xpattern: "204042"
+    imsi_prefix_xpattern: "204044"
+    imsi_prefix_xpattern: "204045"
+    imsi_prefix_xpattern: "204047"
+    imsi_prefix_xpattern: "204048"
+    imsi_prefix_xpattern: "204049"
+    spn: ""
+    spn: "vodafone NL"
+  }
+}
+carrier_id {
+  canonical_id: 21
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "53001"
+  }
+}
+carrier_id {
+  canonical_id: 22
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "26801"
+    spn: ""
+    spn: "vodafone P"
+    spn: "Vodafone"
+  }
+}
+carrier_id {
+  canonical_id: 23
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "22601"
+    spn: "Vodafone RO"
+  }
+}
+carrier_id {
+  canonical_id: 24
+  carrier_name: "Vodacom"
+  carrier_attribute {
+    mccmnc_tuple: "65501"
+  }
+}
+carrier_id {
+  canonical_id: 25
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "26202"
+    imsi_prefix_xpattern: "262020"
+    imsi_prefix_xpattern: "2620211"
+    imsi_prefix_xpattern: "2620212"
+    imsi_prefix_xpattern: "2620213"
+    imsi_prefix_xpattern: "2620214"
+    imsi_prefix_xpattern: "2620215"
+    imsi_prefix_xpattern: "2620216"
+    imsi_prefix_xpattern: "2620217"
+    imsi_prefix_xpattern: "2620218"
+    imsi_prefix_xpattern: "26202190"
+    imsi_prefix_xpattern: "262021910"
+    imsi_prefix_xpattern: "262021911"
+    imsi_prefix_xpattern: "262021912"
+    imsi_prefix_xpattern: "2620219130"
+    imsi_prefix_xpattern: "2620219131"
+    imsi_prefix_xpattern: "2620219132"
+    imsi_prefix_xpattern: "2620219133"
+    imsi_prefix_xpattern: "2620219134"
+    imsi_prefix_xpattern: "2620219141"
+    imsi_prefix_xpattern: "2620219142"
+    imsi_prefix_xpattern: "2620219143"
+    imsi_prefix_xpattern: "2620219144"
+    imsi_prefix_xpattern: "2620219149"
+    imsi_prefix_xpattern: "262021915"
+    imsi_prefix_xpattern: "262021916"
+    imsi_prefix_xpattern: "262021917"
+    imsi_prefix_xpattern: "262021918"
+    imsi_prefix_xpattern: "262021919"
+    imsi_prefix_xpattern: "26202192"
+    imsi_prefix_xpattern: "26202193"
+    imsi_prefix_xpattern: "26202194"
+    imsi_prefix_xpattern: "26202195"
+    imsi_prefix_xpattern: "26202196"
+    imsi_prefix_xpattern: "26202197"
+    imsi_prefix_xpattern: "26202198"
+    imsi_prefix_xpattern: "26202199"
+    imsi_prefix_xpattern: "262022"
+    imsi_prefix_xpattern: "262023"
+    imsi_prefix_xpattern: "262024"
+    imsi_prefix_xpattern: "262025"
+    imsi_prefix_xpattern: "262026"
+    imsi_prefix_xpattern: "262027"
+    imsi_prefix_xpattern: "262028"
+    imsi_prefix_xpattern: "262029"
+    spn: ""
+    spn: "Vodafone"
+    spn: "Vodafone.de"
+  }
+}
+carrier_id {
+  canonical_id: 26
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "21401"
+    spn: ""
+    spn: "vodafone"
+    spn: "vodafone ES"
+    spn: "Vodafone"
+  }
+}
+carrier_id {
+  canonical_id: 27
+  carrier_name: "SFR"
+  carrier_attribute {
+    mccmnc_tuple: "20810"
+  }
+}
+carrier_id {
+  canonical_id: 28
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "23415"
+    mccmnc_tuple: "23491"
+    spn: ""
+    spn: "vodafone UK"
+  }
+}
+carrier_id {
+  canonical_id: 29
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "22210"
+    spn: ""
+    spn: "vodafone IT"
+    spn: "Vodafone"
+  }
+}
+carrier_id {
+  canonical_id: 30
+  carrier_name: "Optus"
+  carrier_attribute {
+    mccmnc_tuple: "50502"
+    mccmnc_tuple: "50590"
+  }
+}
+carrier_id {
+  canonical_id: 31
+  carrier_name: "Singtel"
+  carrier_attribute {
+    mccmnc_tuple: "52501"
+    mccmnc_tuple: "52502"
+  }
+}
+carrier_id {
+  canonical_id: 32
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "20800"
+    mccmnc_tuple: "20801"
+    mccmnc_tuple: "20802"
+  }
+}
+carrier_id {
+  canonical_id: 33
+  carrier_name: "TIM"
+  carrier_attribute {
+    mccmnc_tuple: "22201"
+  }
+}
+carrier_id {
+  canonical_id: 34
+  carrier_name: "Movistar"
+  carrier_attribute {
+    mccmnc_tuple: "21405"
+    mccmnc_tuple: "21407"
+  }
+}
+carrier_id {
+  canonical_id: 450
+  carrier_name: "Mobiland"
+  carrier_attribute {
+    mccmnc_tuple: "21303"
+  }
+}
+carrier_id {
+  canonical_id: 451
+  carrier_name: "Etisalat"
+  carrier_attribute {
+    mccmnc_tuple: "42402"
+  }
+}
+carrier_id {
+  canonical_id: 452
+  carrier_name: "AWCC"
+  carrier_attribute {
+    mccmnc_tuple: "41201"
+  }
+}
+carrier_id {
+  canonical_id: 453
+  carrier_name: "Roshan"
+  carrier_attribute {
+    mccmnc_tuple: "41220"
+  }
+}
+carrier_id {
+  canonical_id: 454
+  carrier_name: "New1"
+  carrier_attribute {
+    mccmnc_tuple: "41230"
+  }
+}
+carrier_id {
+  canonical_id: 455
+  carrier_name: "Areeba Afghanistan"
+  carrier_attribute {
+    mccmnc_tuple: "41240"
+  }
+}
+carrier_id {
+  canonical_id: 456
+  carrier_name: "Afghan Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "41288"
+  }
+}
+carrier_id {
+  canonical_id: 457
+  carrier_name: "APUA PCS"
+  carrier_attribute {
+    mccmnc_tuple: "344030"
+  }
+}
+carrier_id {
+  canonical_id: 491
+  carrier_name: "Advanced Communications Technologies Pty. Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "50524"
+  }
+}
+carrier_id {
+  canonical_id: 492
+  carrier_name: "Localstar Holding Pty. Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "50588"
+  }
+}
+carrier_id {
+  canonical_id: 493
+  carrier_name: "Setar GSM"
+  carrier_attribute {
+    mccmnc_tuple: "36301"
+  }
+}
+carrier_id {
+  canonical_id: 495
+  carrier_name: "Bakcell Limited Liabil ity Company"
+  carrier_attribute {
+    mccmnc_tuple: "40002"
+  }
+}
+carrier_id {
+  canonical_id: 529
+  carrier_name: "Claro BR"
+  carrier_attribute {
+    mccmnc_tuple: "72405"
+    mccmnc_tuple: "72438"
+  }
+}
+carrier_id {
+  canonical_id: 530
+  carrier_name: "Vivo"
+  carrier_attribute {
+    mccmnc_tuple: "72406"
+    mccmnc_tuple: "72410"
+    mccmnc_tuple: "72411"
+    mccmnc_tuple: "72423"
+  }
+}
+carrier_id {
+  canonical_id: 532
+  carrier_name: "Maxitel MG"
+  carrier_attribute {
+    mccmnc_tuple: "72408"
+  }
+}
+carrier_id {
+  canonical_id: 533
+  carrier_name: "Telepar Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72409"
+  }
+}
+carrier_id {
+  canonical_id: 536
+  carrier_name: "Americel"
+  carrier_attribute {
+    mccmnc_tuple: "72412"
+  }
+}
+carrier_id {
+  canonical_id: 537
+  carrier_name: "Telesp Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72413"
+  }
+}
+carrier_id {
+  canonical_id: 538
+  carrier_name: "Maxitel BA"
+  carrier_attribute {
+    mccmnc_tuple: "72414"
+  }
+}
+carrier_id {
+  canonical_id: 539
+  carrier_name: "Sercomtel"
+  carrier_attribute {
+    mccmnc_tuple: "72415"
+  }
+}
+carrier_id {
+  canonical_id: 540
+  carrier_name: "Brasil Telecom GSM"
+  carrier_attribute {
+    mccmnc_tuple: "72416"
+  }
+}
+carrier_id {
+  canonical_id: 541
+  carrier_name: "Ceterp Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72417"
+  }
+}
+carrier_id {
+  canonical_id: 542
+  carrier_name: "Datora"
+  carrier_attribute {
+    mccmnc_tuple: "72418"
+  }
+}
+carrier_id {
+  canonical_id: 543
+  carrier_name: "Telemig Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72419"
+  }
+}
+carrier_id {
+  canonical_id: 544
+  carrier_name: "Telerj Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72421"
+  }
+}
+carrier_id {
+  canonical_id: 546
+  carrier_name: "Telebrasilia Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72425"
+  }
+}
+carrier_id {
+  canonical_id: 547
+  carrier_name: "Telegoias Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72427"
+  }
+}
+carrier_id {
+  canonical_id: 548
+  carrier_name: "Telemat Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72429"
+  }
+}
+carrier_id {
+  canonical_id: 562
+  carrier_name: "Teleamapa Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72457"
+  }
+}
+carrier_id {
+  canonical_id: 563
+  carrier_name: "Telaima Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72459"
+  }
+}
+carrier_id {
+  canonical_id: 564
+  carrier_name: "Bhutan Telecom Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "40211"
+  }
+}
+carrier_id {
+  canonical_id: 566
+  carrier_name: "Mascom Wireless (Pty) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "65201"
+  }
+}
+carrier_id {
+  canonical_id: 567
+  carrier_name: "Orange Botswana (Pty) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "65202"
+  }
+}
+carrier_id {
+  canonical_id: 568
+  carrier_name: "Velcom"
+  carrier_attribute {
+    mccmnc_tuple: "25701"
+  }
+}
+carrier_id {
+  canonical_id: 569
+  carrier_name: "MTS"
+  carrier_attribute {
+    mccmnc_tuple: "25702"
+  }
+}
+carrier_id {
+  canonical_id: 570
+  carrier_name: "Belize Telecommunications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "70267"
+  }
+}
+carrier_id {
+  canonical_id: 571
+  carrier_name: "International Telecommunications Ltd. (INTELCO)"
+  carrier_attribute {
+    mccmnc_tuple: "70268"
+  }
+}
+carrier_id {
+  canonical_id: 572
+  carrier_name: "Clearnet"
+  carrier_attribute {
+    mccmnc_tuple: "30236"
+  }
+}
+carrier_id {
+  canonical_id: 574
+  carrier_name: "Ice Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "30262"
+  }
+}
+carrier_id {
+  canonical_id: 575
+  carrier_name: "Aliant Mobility"
+  carrier_attribute {
+    mccmnc_tuple: "30263"
+  }
+}
+carrier_id {
+  canonical_id: 576
+  carrier_name: "Bell Mobility"
+  carrier_attribute {
+    mccmnc_tuple: "30264"
+    mccmnc_tuple: "302610"
+    mccmnc_tuple: "302630"
+    mccmnc_tuple: "302640"
+  }
+}
+carrier_id {
+  canonical_id: 577
+  carrier_name: "Tbay Mobility"
+  carrier_attribute {
+    mccmnc_tuple: "302656"
+  }
+}
+carrier_id {
+  canonical_id: 578
+  carrier_name: "MTS Mobility"
+  carrier_attribute {
+    mccmnc_tuple: "302660"
+    mccmnc_tuple: "302370"
+    gid1: "2c"
+    gid1: "4d"
+  }
+}
+carrier_id {
+  canonical_id: 579
+  carrier_name: "CityTel Mobility"
+  carrier_attribute {
+    mccmnc_tuple: "30267"
+  }
+}
+carrier_id {
+  canonical_id: 580
+  carrier_name: "Sask Tel Mobility"
+  carrier_attribute {
+    mccmnc_tuple: "30268"
+    mccmnc_tuple: "302654"
+    mccmnc_tuple: "302680"
+    mccmnc_tuple: "302780"
+  }
+}
+carrier_id {
+  canonical_id: 581
+  carrier_name: "Globalstar"
+  carrier_attribute {
+    mccmnc_tuple: "30271"
+  }
+}
+carrier_id {
+  canonical_id: 624
+  carrier_name: "Colombia Móvil S.A."
+  carrier_attribute {
+    mccmnc_tuple: "732103"
+    mccmnc_tuple: "732111"
+  }
+}
+carrier_id {
+  canonical_id: 625
+  carrier_name: "Telefónica Móviles Colombia S.A."
+  carrier_attribute {
+    mccmnc_tuple: "732123"
+  }
+}
+carrier_id {
+  canonical_id: 626
+  carrier_name: "Avantel"
+  carrier_attribute {
+    mccmnc_tuple: "732130"
+  }
+}
+carrier_id {
+  canonical_id: 627
+  carrier_name: "Instituto Costarricense de Electricidad - ICE"
+  carrier_attribute {
+    mccmnc_tuple: "71201"
+  }
+}
+carrier_id {
+  canonical_id: 655
+  carrier_name: "Barablu Mobile Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "23807"
+  }
+}
+carrier_id {
+  canonical_id: 656
+  carrier_name: "Telia"
+  carrier_attribute {
+    mccmnc_tuple: "23820"
+    mccmnc_tuple: "23830"
+  }
+}
+carrier_id {
+  canonical_id: 657
+  carrier_name: "Tele2"
+  carrier_attribute {
+    mccmnc_tuple: "23877"
+  }
+}
+carrier_id {
+  canonical_id: 658
+  carrier_name: "Orange Dominicana, S.A."
+  carrier_attribute {
+    mccmnc_tuple: "37001"
+  }
+}
+carrier_id {
+  canonical_id: 667
+  carrier_name: "Telia"
+  carrier_attribute {
+    mccmnc_tuple: "24801"
+  }
+}
+carrier_id {
+  canonical_id: 668
+  carrier_name: "Elisa"
+  carrier_attribute {
+    mccmnc_tuple: "24802"
+  }
+}
+carrier_id {
+  canonical_id: 669
+  carrier_name: "Tele2"
+  carrier_attribute {
+    mccmnc_tuple: "24803"
+  }
+}
+carrier_id {
+  canonical_id: 670
+  carrier_name: "OY Top Connect"
+  carrier_attribute {
+    mccmnc_tuple: "24804"
+  }
+}
+carrier_id {
+  canonical_id: 671
+  carrier_name: "AS Bravocom Mobiil"
+  carrier_attribute {
+    mccmnc_tuple: "24805"
+  }
+}
+carrier_id {
+  canonical_id: 672
+  carrier_name: "OY ViaTel"
+  carrier_attribute {
+    mccmnc_tuple: "24806"
+  }
+}
+carrier_id {
+  canonical_id: 673
+  carrier_name: "Televõrgu AS"
+  carrier_attribute {
+    mccmnc_tuple: "24807"
+  }
+}
+carrier_id {
+  canonical_id: 674
+  carrier_name: "Siseministeerium (Ministry of Interior)"
+  carrier_attribute {
+    mccmnc_tuple: "24871"
+  }
+}
+carrier_id {
+  canonical_id: 675
+  carrier_name: "Orange Egypt"
+  carrier_attribute {
+    mccmnc_tuple: "60201"
+  }
+}
+carrier_id {
+  canonical_id: 676
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "60202"
+  }
+}
+carrier_id {
+  canonical_id: 678
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "21403"
+  }
+}
+carrier_id {
+  canonical_id: 679
+  carrier_name: "Yoigo"
+  carrier_attribute {
+    mccmnc_tuple: "21404"
+  }
+}
+carrier_id {
+  canonical_id: 681
+  carrier_name: "ETH MTN"
+  carrier_attribute {
+    mccmnc_tuple: "63601"
+  }
+}
+carrier_id {
+  canonical_id: 682
+  carrier_name: "Finnet Networks Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "24404"
+  }
+}
+carrier_id {
+  canonical_id: 717
+  carrier_name: "Virgin"
+  carrier_attribute {
+    mccmnc_tuple: "23430"
+    mccmnc_tuple: "23438"
+    gid1: "2800000000000000"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "20601"
+    gid1: "28"
+  }
+}
+carrier_id {
+  canonical_id: 718
+  carrier_name: "EE"
+  carrier_attribute {
+    mccmnc_tuple: "23430"
+    imsi_prefix_xpattern: "234300"
+    imsi_prefix_xpattern: "234301"
+    imsi_prefix_xpattern: "234302"
+    imsi_prefix_xpattern: "234303"
+    imsi_prefix_xpattern: "2343040"
+    imsi_prefix_xpattern: "2343042"
+    imsi_prefix_xpattern: "2343043"
+    imsi_prefix_xpattern: "2343044"
+    imsi_prefix_xpattern: "2343045"
+    imsi_prefix_xpattern: "2343046"
+    imsi_prefix_xpattern: "2343047"
+    imsi_prefix_xpattern: "2343048"
+    imsi_prefix_xpattern: "2343049"
+    imsi_prefix_xpattern: "234305"
+    imsi_prefix_xpattern: "234306"
+    imsi_prefix_xpattern: "234307"
+    imsi_prefix_xpattern: "234308"
+    imsi_prefix_xpattern: "234309"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "23433"
+    imsi_prefix_xpattern: "x"
+  }
+}
+carrier_id {
+  canonical_id: 720
+  carrier_name: "Cable and Wireless Guensey Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "23455"
+  }
+}
+carrier_id {
+  canonical_id: 733
+  carrier_name: "Gibtelecom GSM"
+  carrier_attribute {
+    mccmnc_tuple: "26601"
+  }
+}
+carrier_id {
+  canonical_id: 734
+  carrier_name: "Cloud9 Mobile Communications"
+  carrier_attribute {
+    mccmnc_tuple: "26609"
+  }
+}
+carrier_id {
+  canonical_id: 735
+  carrier_name: "Tele Greenland"
+  carrier_attribute {
+    mccmnc_tuple: "29001"
+  }
+}
+carrier_id {
+  canonical_id: 736
+  carrier_name: "Gamcel"
+  carrier_attribute {
+    mccmnc_tuple: "60701"
+  }
+}
+carrier_id {
+  canonical_id: 737
+  carrier_name: "Africell"
+  carrier_attribute {
+    mccmnc_tuple: "60702"
+  }
+}
+carrier_id {
+  canonical_id: 738
+  carrier_name: "Comium Services Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "60703"
+  }
+}
+carrier_id {
+  canonical_id: 739
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "61101"
+  }
+}
+carrier_id {
+  canonical_id: 740
+  carrier_name: "Sotelgui"
+  carrier_attribute {
+    mccmnc_tuple: "61102"
+  }
+}
+carrier_id {
+  canonical_id: 741
+  carrier_name: "Cellcom Guinée SA"
+  carrier_attribute {
+    mccmnc_tuple: "61105"
+  }
+}
+carrier_id {
+  canonical_id: 742
+  carrier_name: "Orange Caraïbe Mobiles"
+  carrier_attribute {
+    mccmnc_tuple: "34001"
+  }
+}
+carrier_id {
+  canonical_id: 743
+  carrier_name: "Outremer Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "34002"
+  }
+}
+carrier_id {
+  canonical_id: 744
+  carrier_name: "Saint Martin et Saint Barthelemy Telcell Sarl"
+  carrier_attribute {
+    mccmnc_tuple: "34003"
+  }
+}
+carrier_id {
+  canonical_id: 745
+  carrier_name: "Bouygues Telecom Caraïbe"
+  carrier_attribute {
+    mccmnc_tuple: "34020"
+  }
+}
+carrier_id {
+  canonical_id: 746
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "62701"
+  }
+}
+carrier_id {
+  canonical_id: 747
+  carrier_name: "COSMOTE"
+  carrier_attribute {
+    mccmnc_tuple: "20201"
+  }
+}
+carrier_id {
+  canonical_id: 749
+  carrier_name: "Info Quest S.A."
+  carrier_attribute {
+    mccmnc_tuple: "20209"
+  }
+}
+carrier_id {
+  canonical_id: 759
+  carrier_name: "3G Radio System/HKCSL3G"
+  carrier_attribute {
+    mccmnc_tuple: "45402"
+  }
+}
+carrier_id {
+  canonical_id: 760
+  carrier_name: "3HK"
+  carrier_attribute {
+    mccmnc_tuple: "45403"
+  }
+}
+carrier_id {
+  canonical_id: 761
+  carrier_name: "SmarTone HK"
+  carrier_attribute {
+    mccmnc_tuple: "45406"
+  }
+}
+carrier_id {
+  canonical_id: 762
+  carrier_name: "MVNO/China Unicom International Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "45407"
+  }
+}
+carrier_id {
+  canonical_id: 763
+  carrier_name: "MVNO/Trident"
+  carrier_attribute {
+    mccmnc_tuple: "45408"
+  }
+}
+carrier_id {
+  canonical_id: 764
+  carrier_name: "MVNO/China Motion Telecom (HK) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "45409"
+  }
+}
+carrier_id {
+  canonical_id: 765
+  carrier_name: "GSM1800New World PCS Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "45410"
+  }
+}
+carrier_id {
+  canonical_id: 766
+  carrier_name: "MVNO/CHKTL"
+  carrier_attribute {
+    mccmnc_tuple: "45411"
+  }
+}
+carrier_id {
+  canonical_id: 767
+  carrier_name: "中國移動香港 China Mobile HK"
+  carrier_attribute {
+    mccmnc_tuple: "45412"
+    mccmnc_tuple: "45413"
+  }
+}
+carrier_id {
+  canonical_id: 768
+  carrier_name: "3G Radio System/SMT3G"
+  carrier_attribute {
+    mccmnc_tuple: "45415"
+  }
+}
+carrier_id {
+  canonical_id: 769
+  carrier_name: "PCCW"
+  carrier_attribute {
+    mccmnc_tuple: "45416"
+  }
+}
+carrier_id {
+  canonical_id: 770
+  carrier_name: "GSM7800/Hong Kong CSL Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "45418"
+  }
+}
+carrier_id {
+  canonical_id: 772
+  carrier_name: "Public Mobile Networks/Reserved"
+  carrier_attribute {
+    mccmnc_tuple: "45420"
+    mccmnc_tuple: "45421"
+    mccmnc_tuple: "45422"
+    mccmnc_tuple: "45423"
+    mccmnc_tuple: "45424"
+    mccmnc_tuple: "45425"
+    mccmnc_tuple: "45426"
+    mccmnc_tuple: "45427"
+    mccmnc_tuple: "45428"
+    mccmnc_tuple: "45429"
+    mccmnc_tuple: "45430"
+    mccmnc_tuple: "45431"
+    mccmnc_tuple: "45432"
+    mccmnc_tuple: "45433"
+    mccmnc_tuple: "45434"
+    mccmnc_tuple: "45435"
+    mccmnc_tuple: "45436"
+    mccmnc_tuple: "45437"
+    mccmnc_tuple: "45438"
+    mccmnc_tuple: "45439"
+  }
+}
+carrier_id {
+  canonical_id: 773
+  carrier_name: "Claro HN"
+  carrier_attribute {
+    mccmnc_tuple: "708001"
+    mccmnc_tuple: "70801"
+  }
+}
+carrier_id {
+  canonical_id: 787
+  carrier_name: "Telkomsel"
+  carrier_attribute {
+    mccmnc_tuple: "51010"
+  }
+}
+carrier_id {
+  canonical_id: 788
+  carrier_name: "XL/AXIS"
+  carrier_attribute {
+    mccmnc_tuple: "51008"
+    mccmnc_tuple: "51011"
+  }
+}
+carrier_id {
+  canonical_id: 789
+  carrier_name: "Indosat - M3"
+  carrier_attribute {
+    mccmnc_tuple: "51021"
+  }
+}
+carrier_id {
+  canonical_id: 792
+  carrier_name: "3"
+  carrier_attribute {
+    mccmnc_tuple: "27202"
+  }
+}
+carrier_id {
+  canonical_id: 793
+  carrier_name: "Meteor Mobile Communications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "27203"
+  }
+}
+carrier_id {
+  canonical_id: 794
+  carrier_name: "Eircom"
+  carrier_attribute {
+    mccmnc_tuple: "27207"
+  }
+}
+carrier_id {
+  canonical_id: 795
+  carrier_name: "Clever Communications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "27209"
+  }
+}
+carrier_id {
+  canonical_id: 796
+  carrier_name: "Partner Communications Co. Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "42501"
+  }
+}
+carrier_id {
+  canonical_id: 797
+  carrier_name: "Cellcom Israel Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "42502"
+  }
+}
+carrier_id {
+  canonical_id: 798
+  carrier_name: "Pelephone Communications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "42503"
+  }
+}
+carrier_id {
+  canonical_id: 802
+  carrier_name: "Idea"
+  carrier_attribute {
+    mccmnc_tuple: "40404"
+    mccmnc_tuple: "40407"
+    mccmnc_tuple: "40412"
+    mccmnc_tuple: "40414"
+    mccmnc_tuple: "40419"
+    mccmnc_tuple: "40422"
+    mccmnc_tuple: "40424"
+    mccmnc_tuple: "40444"
+    mccmnc_tuple: "40456"
+    mccmnc_tuple: "40478"
+    mccmnc_tuple: "40482"
+    mccmnc_tuple: "40487"
+    mccmnc_tuple: "40489"
+    mccmnc_tuple: "40570"
+    mccmnc_tuple: "40545"
+    mccmnc_tuple: "405799"
+    mccmnc_tuple: "405845"
+    mccmnc_tuple: "405846"
+    mccmnc_tuple: "405848"
+    mccmnc_tuple: "405849"
+    mccmnc_tuple: "405850"
+    mccmnc_tuple: "405852"
+    mccmnc_tuple: "405853"
+  }
+}
+carrier_id {
+  canonical_id: 849
+  carrier_name: "Orange Jordan"
+  carrier_attribute {
+    mccmnc_tuple: "41677"
+  }
+}
+carrier_id {
+  canonical_id: 850
+  carrier_name: "NTT DOCOMO"
+  carrier_attribute {
+    mccmnc_tuple: "44010"
+  }
+}
+carrier_id {
+  canonical_id: 865
+  carrier_name: "Safaricom"
+  carrier_attribute {
+    mccmnc_tuple: "63902"
+  }
+}
+carrier_id {
+  canonical_id: 866
+  carrier_name: "Kencell Communications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "63903"
+  }
+}
+carrier_id {
+  canonical_id: 867
+  carrier_name: "Bitel GSM"
+  carrier_attribute {
+    mccmnc_tuple: "43701"
+  }
+}
+carrier_id {
+  canonical_id: 868
+  carrier_name: "Mobitel (Cam GSM)"
+  carrier_attribute {
+    mccmnc_tuple: "45601"
+  }
+}
+carrier_id {
+  canonical_id: 869
+  carrier_name: "Smart"
+  carrier_attribute {
+    mccmnc_tuple: "45602"
+    mccmnc_tuple: "45605"
+    mccmnc_tuple: "45606"
+  }
+}
+carrier_id {
+  canonical_id: 870
+  carrier_name: "S Telecom (CDMA) (reserved)"
+  carrier_attribute {
+    mccmnc_tuple: "45603"
+  }
+}
+carrier_id {
+  canonical_id: 871
+  carrier_name: "Camshin (Shinawatra)"
+  carrier_attribute {
+    mccmnc_tuple: "45618"
+  }
+}
+carrier_id {
+  canonical_id: 872
+  carrier_name: "HURI - SNPT"
+  carrier_attribute {
+    mccmnc_tuple: "65401"
+  }
+}
+carrier_id {
+  canonical_id: 892
+  carrier_name: "Telia"
+  carrier_attribute {
+    mccmnc_tuple: "24601"
+  }
+}
+carrier_id {
+  canonical_id: 893
+  carrier_name: "BITĖ"
+  carrier_attribute {
+    mccmnc_tuple: "24602"
+  }
+}
+carrier_id {
+  canonical_id: 894
+  carrier_name: "Tele2"
+  carrier_attribute {
+    mccmnc_tuple: "24603"
+  }
+}
+carrier_id {
+  canonical_id: 895
+  carrier_name: "P&T Luxembourg"
+  carrier_attribute {
+    mccmnc_tuple: "27001"
+  }
+}
+carrier_id {
+  canonical_id: 896
+  carrier_name: "Tango"
+  carrier_attribute {
+    mccmnc_tuple: "27077"
+  }
+}
+carrier_id {
+  canonical_id: 897
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "27099"
+  }
+}
+carrier_id {
+  canonical_id: 898
+  carrier_name: "LMT/Amigo"
+  carrier_attribute {
+    mccmnc_tuple: "24701"
+  }
+}
+carrier_id {
+  canonical_id: 899
+  carrier_name: "Tele2/ZZ"
+  carrier_attribute {
+    mccmnc_tuple: "24702"
+  }
+}
+carrier_id {
+  canonical_id: 900
+  carrier_name: "Telekom Baltija"
+  carrier_attribute {
+    mccmnc_tuple: "24703"
+  }
+}
+carrier_id {
+  canonical_id: 901
+  carrier_name: "Beta Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "24704"
+  }
+}
+carrier_id {
+  canonical_id: 902
+  carrier_name: "Méditélécom"
+  carrier_attribute {
+    mccmnc_tuple: "60400"
+  }
+}
+carrier_id {
+  canonical_id: 903
+  carrier_name: "Ittissalat Al Maghrid"
+  carrier_attribute {
+    mccmnc_tuple: "60401"
+  }
+}
+carrier_id {
+  canonical_id: 904
+  carrier_name: "Orange Moldova GSM"
+  carrier_attribute {
+    mccmnc_tuple: "25901"
+  }
+}
+carrier_id {
+  canonical_id: 905
+  carrier_name: "Moldcell GSM"
+  carrier_attribute {
+    mccmnc_tuple: "25902"
+  }
+}
+carrier_id {
+  canonical_id: 906
+  carrier_name: "Eventis Mobile GSM"
+  carrier_attribute {
+    mccmnc_tuple: "25904"
+  }
+}
+carrier_id {
+  canonical_id: 941
+  carrier_name: "Mobile Telecommunications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "64901"
+  }
+}
+carrier_id {
+  canonical_id: 942
+  carrier_name: "Powercom Pty Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "64903"
+  }
+}
+carrier_id {
+  canonical_id: 943
+  carrier_name: "OPT Mobilis"
+  carrier_attribute {
+    mccmnc_tuple: "54601"
+  }
+}
+carrier_id {
+  canonical_id: 945
+  carrier_name: "Celtel"
+  carrier_attribute {
+    mccmnc_tuple: "61402"
+  }
+}
+carrier_id {
+  canonical_id: 958
+  carrier_name: "Telenor"
+  carrier_attribute {
+    mccmnc_tuple: "24201"
+  }
+}
+carrier_id {
+  canonical_id: 959
+  carrier_name: "Netcom GSM AS"
+  carrier_attribute {
+    mccmnc_tuple: "24202"
+  }
+}
+carrier_id {
+  canonical_id: 960
+  carrier_name: "Teletopia Mobile Communications AS"
+  carrier_attribute {
+    mccmnc_tuple: "24203"
+  }
+}
+carrier_id {
+  canonical_id: 961
+  carrier_name: "Tele2 Norge AS"
+  carrier_attribute {
+    mccmnc_tuple: "24204"
+  }
+}
+carrier_id {
+  canonical_id: 962
+  carrier_name: "Nepal Telecommunications"
+  carrier_attribute {
+    mccmnc_tuple: "42901"
+    mccmnc_tuple: "42903"
+  }
+}
+carrier_id {
+  canonical_id: 963
+  carrier_name: "Reserved for AMPS MIN based IMSI's"
+  carrier_attribute {
+    mccmnc_tuple: "53000"
+  }
+}
+carrier_id {
+  canonical_id: 965
+  carrier_name: "Teleom New Zealand CDMA Network"
+  carrier_attribute {
+    mccmnc_tuple: "53002"
+  }
+}
+carrier_id {
+  canonical_id: 966
+  carrier_name: "Woosh Wireless - CDMA Network"
+  carrier_attribute {
+    mccmnc_tuple: "53003"
+  }
+}
+carrier_id {
+  canonical_id: 967
+  carrier_name: "TelstraClear - GSM Network"
+  carrier_attribute {
+    mccmnc_tuple: "53004"
+  }
+}
+carrier_id {
+  canonical_id: 968
+  carrier_name: "Spark NZ"
+  carrier_attribute {
+    mccmnc_tuple: "53005"
+  }
+}
+carrier_id {
+  canonical_id: 969
+  carrier_name: "2degrees"
+  carrier_attribute {
+    mccmnc_tuple: "53024"
+  }
+}
+carrier_id {
+  canonical_id: 970
+  carrier_name: "Omantel"
+  carrier_attribute {
+    mccmnc_tuple: "42202"
+    mccmnc_tuple: "42204"
+  }
+}
+carrier_id {
+  canonical_id: 971
+  carrier_name: "Ooredoo"
+  carrier_attribute {
+    mccmnc_tuple: "42203"
+  }
+}
+carrier_id {
+  canonical_id: 973
+  carrier_name: "Cable & Wireless Panama S.A."
+  carrier_attribute {
+    mccmnc_tuple: "71401"
+  }
+}
+carrier_id {
+  canonical_id: 974
+  carrier_name: "movistar (Telefónica Moviles Panama S.A.)"
+  carrier_attribute {
+    mccmnc_tuple: "71402"
+    mccmnc_tuple: "714020"
+  }
+}
+carrier_id {
+  canonical_id: 1008
+  carrier_name: "Société Réunionnaise du Radiotéléphone"
+  carrier_attribute {
+    mccmnc_tuple: "64710"
+  }
+}
+carrier_id {
+  canonical_id: 1010
+  carrier_name: "Telekom Romania"
+  carrier_attribute {
+    mccmnc_tuple: "22603"
+    mccmnc_tuple: "22606"
+    spn: "TELEKOM.RO"
+    spn: "COSMOTE"
+    spn: "frog"
+    spn: "MTV Mobile"
+  }
+}
+carrier_id {
+  canonical_id: 1011
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "22610"
+  }
+}
+carrier_id {
+  canonical_id: 1012
+  carrier_name: "Telenor d.o.o."
+  carrier_attribute {
+    mccmnc_tuple: "22001"
+    mccmnc_tuple: "22002"
+  }
+}
+carrier_id {
+  canonical_id: 1013
+  carrier_name: "Telekom Srbija a.d."
+  carrier_attribute {
+    mccmnc_tuple: "22003"
+  }
+}
+carrier_id {
+  canonical_id: 1014
+  carrier_name: "Vip mobile d.o.o."
+  carrier_attribute {
+    mccmnc_tuple: "22005"
+  }
+}
+carrier_id {
+  canonical_id: 1016
+  carrier_name: "MegaFon"
+  carrier_attribute {
+    mccmnc_tuple: "25002"
+  }
+}
+carrier_id {
+  canonical_id: 1018
+  carrier_name: "Sibchallenge"
+  carrier_attribute {
+    mccmnc_tuple: "25004"
+  }
+}
+carrier_id {
+  canonical_id: 1020
+  carrier_name: "BM Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "25007"
+  }
+}
+carrier_id {
+  canonical_id: 1021
+  carrier_name: "Don Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "25010"
+  }
+}
+carrier_id {
+  canonical_id: 1022
+  carrier_name: "Orensot"
+  carrier_attribute {
+    mccmnc_tuple: "25011"
+  }
+}
+carrier_id {
+  canonical_id: 1024
+  carrier_name: "Kuban GSM"
+  carrier_attribute {
+    mccmnc_tuple: "25013"
+  }
+}
+carrier_id {
+  canonical_id: 1025
+  carrier_name: "New Telephone Company"
+  carrier_attribute {
+    mccmnc_tuple: "25016"
+  }
+}
+carrier_id {
+  canonical_id: 1027
+  carrier_name: "Volgograd Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "25019"
+  }
+}
+carrier_id {
+  canonical_id: 1028
+  carrier_name: "Tele2"
+  carrier_attribute {
+    mccmnc_tuple: "25003"
+    mccmnc_tuple: "25005"
+    mccmnc_tuple: "25012"
+    mccmnc_tuple: "25017"
+    mccmnc_tuple: "25020"
+    mccmnc_tuple: "25039"
+  }
+}
+carrier_id {
+  canonical_id: 1029
+  carrier_name: "Extel"
+  carrier_attribute {
+    mccmnc_tuple: "25028"
+  }
+}
+carrier_id {
+  canonical_id: 1031
+  carrier_name: "Stuvtelesot"
+  carrier_attribute {
+    mccmnc_tuple: "25044"
+  }
+}
+carrier_id {
+  canonical_id: 1074
+  carrier_name: "Comium (Sierra Leone) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "61904"
+  }
+}
+carrier_id {
+  canonical_id: 1075
+  carrier_name: "Lintel (Sierra Leone) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "61905"
+  }
+}
+carrier_id {
+  canonical_id: 1076
+  carrier_name: "Mobitel"
+  carrier_attribute {
+    mccmnc_tuple: "61925"
+  }
+}
+carrier_id {
+  canonical_id: 1077
+  carrier_name: "Datatel (SL) Ltd GSM"
+  carrier_attribute {
+    mccmnc_tuple: "61940"
+  }
+}
+carrier_id {
+  canonical_id: 1082
+  carrier_name: "Golis Telecommunications Company"
+  carrier_attribute {
+    mccmnc_tuple: "63730"
+  }
+}
+carrier_id {
+  canonical_id: 1083
+  carrier_name: "Telesur"
+  carrier_attribute {
+    mccmnc_tuple: "74602"
+  }
+}
+carrier_id {
+  canonical_id: 1084
+  carrier_name: "Digicel"
+  carrier_attribute {
+    mccmnc_tuple: "74603"
+  }
+}
+carrier_id {
+  canonical_id: 1085
+  carrier_name: "Intelsur"
+  carrier_attribute {
+    mccmnc_tuple: "74604"
+  }
+}
+carrier_id {
+  canonical_id: 1086
+  carrier_name: "Companhia Santomese de Telecomunicaçôes"
+  carrier_attribute {
+    mccmnc_tuple: "62601"
+  }
+}
+carrier_id {
+  canonical_id: 1087
+  carrier_name: "Digicel, S.A. de C.V."
+  carrier_attribute {
+    mccmnc_tuple: "70602"
+  }
+}
+carrier_id {
+  canonical_id: 1088
+  carrier_name: "Syriatel"
+  carrier_attribute {
+    mccmnc_tuple: "41701"
+  }
+}
+carrier_id {
+  canonical_id: 1089
+  carrier_name: "Spacetel Syria"
+  carrier_attribute {
+    mccmnc_tuple: "41702"
+  }
+}
+carrier_id {
+  canonical_id: 1090
+  carrier_name: "Syrian Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "41709"
+  }
+}
+carrier_id {
+  canonical_id: 1091
+  carrier_name: "Swazi MTN"
+  carrier_attribute {
+    mccmnc_tuple: "65310"
+  }
+}
+carrier_id {
+  canonical_id: 1092
+  carrier_name: "IslandCom Communications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "376352"
+  }
+}
+carrier_id {
+  canonical_id: 1093
+  carrier_name: "Celtel"
+  carrier_attribute {
+    mccmnc_tuple: "62201"
+  }
+}
+carrier_id {
+  canonical_id: 1094
+  carrier_name: "Tchad Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "62202"
+  }
+}
+carrier_id {
+  canonical_id: 1095
+  carrier_name: "Togo Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "61501"
+  }
+}
+carrier_id {
+  canonical_id: 1096
+  carrier_name: "CAT CDMA"
+  carrier_attribute {
+    mccmnc_tuple: "52000"
+  }
+}
+carrier_id {
+  canonical_id: 1097
+  carrier_name: "AIS GSM"
+  carrier_attribute {
+    mccmnc_tuple: "52001"
+  }
+}
+carrier_id {
+  canonical_id: 1098
+  carrier_name: "AIS"
+  carrier_attribute {
+    mccmnc_tuple: "52003"
+  }
+}
+carrier_id {
+  canonical_id: 1136
+  carrier_name: "Iridium Satellite, LLC (GMSS)"
+  carrier_attribute {
+    mccmnc_tuple: "90103"
+  }
+}
+carrier_id {
+  canonical_id: 1137
+  carrier_name: "Globalstar"
+  carrier_attribute {
+    mccmnc_tuple: "90104"
+  }
+}
+carrier_id {
+  canonical_id: 1138
+  carrier_name: "Thuraya RMSS Network"
+  carrier_attribute {
+    mccmnc_tuple: "90105"
+  }
+}
+carrier_id {
+  canonical_id: 1139
+  carrier_name: "Thuraya Satellite Telecommunications Company"
+  carrier_attribute {
+    mccmnc_tuple: "90106"
+  }
+}
+carrier_id {
+  canonical_id: 1166
+  carrier_name: "Consolidated Telcom"
+  carrier_attribute {
+    mccmnc_tuple: "310060"
+  }
+}
+carrier_id {
+  canonical_id: 1168
+  carrier_name: "Corr Wireless Communications LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310080"
+  }
+}
+carrier_id {
+  canonical_id: 1170
+  carrier_name: "New Mexico RSA 4 East Ltd. Partnership"
+  carrier_attribute {
+    mccmnc_tuple: "310100"
+  }
+}
+carrier_id {
+  canonical_id: 1183
+  carrier_name: "High Plains Midwest LLC, dba Wetlink Communications"
+  carrier_attribute {
+    mccmnc_tuple: "310340"
+  }
+}
+carrier_id {
+  canonical_id: 1184
+  carrier_name: "Mohave Cellular L.P."
+  carrier_attribute {
+    mccmnc_tuple: "310350"
+  }
+}
+carrier_id {
+  canonical_id: 1185
+  carrier_name: "Cellular Network Partnership dba Pioneer Cellular"
+  carrier_attribute {
+    mccmnc_tuple: "310360"
+  }
+}
+carrier_id {
+  canonical_id: 1186
+  carrier_name: "Guamcell Cellular and Paging"
+  carrier_attribute {
+    mccmnc_tuple: "310370"
+  }
+}
+carrier_id {
+  canonical_id: 1187
+  carrier_name: "AT&T"
+  carrier_attribute {
+    mccmnc_tuple: "310030"
+    mccmnc_tuple: "310070"
+    mccmnc_tuple: "310170"
+    mccmnc_tuple: "310280"
+    mccmnc_tuple: "310380"
+    mccmnc_tuple: "310410"
+    mccmnc_tuple: "310560"
+    mccmnc_tuple: "310680"
+    mccmnc_tuple: "310950"
+    mccmnc_tuple: "311180"
+  }
+}
+carrier_id {
+  canonical_id: 1188
+  carrier_name: "TX-11 Acquistion LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310390"
+  }
+}
+carrier_id {
+  canonical_id: 1189
+  carrier_name: "Wave Runner LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310400"
+    mccmnc_tuple: "311250"
+  }
+}
+carrier_id {
+  canonical_id: 1190
+  carrier_name: "Cincinnati Bell Wireless LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310420"
+  }
+}
+carrier_id {
+  canonical_id: 1191
+  carrier_name: "Alaska Digitel LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310430"
+  }
+}
+carrier_id {
+  canonical_id: 1192
+  carrier_name: "Numerex Corp."
+  carrier_attribute {
+    mccmnc_tuple: "310440"
+  }
+}
+carrier_id {
+  canonical_id: 1193
+  carrier_name: "North East Cellular Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310450"
+  }
+}
+carrier_id {
+  canonical_id: 1194
+  carrier_name: "TMP Corporation"
+  carrier_attribute {
+    mccmnc_tuple: "310460"
+  }
+}
+carrier_id {
+  canonical_id: 1195
+  carrier_name: "Choice Phone LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310480"
+    mccmnc_tuple: "311120"
+  }
+}
+carrier_id {
+  canonical_id: 1196
+  carrier_name: "Public Service Cellular, Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310500"
+  }
+}
+carrier_id {
+  canonical_id: 1197
+  carrier_name: "Airtel Wireless LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310510"
+  }
+}
+carrier_id {
+  canonical_id: 1198
+  carrier_name: "VeriSign"
+  carrier_attribute {
+    mccmnc_tuple: "310520"
+  }
+}
+carrier_id {
+  canonical_id: 1199
+  carrier_name: "Oklahoma Western Telephone Company"
+  carrier_attribute {
+    mccmnc_tuple: "310540"
+  }
+}
+carrier_id {
+  canonical_id: 1234
+  carrier_name: "UBET Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "310960"
+  }
+}
+carrier_id {
+  canonical_id: 1235
+  carrier_name: "Globalstar USA"
+  carrier_attribute {
+    mccmnc_tuple: "310970"
+  }
+}
+carrier_id {
+  canonical_id: 1236
+  carrier_name: "Mid-Tex Cellular Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "311000"
+  }
+}
+carrier_id {
+  canonical_id: 1237
+  carrier_name: "Chariton Valley Communications Corp., Inc."
+  carrier_attribute {
+    mccmnc_tuple: "311010"
+  }
+}
+carrier_id {
+  canonical_id: 1238
+  carrier_name: "Missouri RSA No. 5 Partnership"
+  carrier_attribute {
+    mccmnc_tuple: "311020"
+  }
+}
+carrier_id {
+  canonical_id: 1239
+  carrier_name: "Indigo Wireless, Inc."
+  carrier_attribute {
+    mccmnc_tuple: "311030"
+  }
+}
+carrier_id {
+  canonical_id: 1240
+  carrier_name: "Commet Wireless, LLC"
+  carrier_attribute {
+    mccmnc_tuple: "311040"
+  }
+}
+carrier_id {
+  canonical_id: 1241
+  carrier_name: "Thumb Cellular Limited Partnership"
+  carrier_attribute {
+    mccmnc_tuple: "311050"
+  }
+}
+carrier_id {
+  canonical_id: 1242
+  carrier_name: "Space Data Corporation"
+  carrier_attribute {
+    mccmnc_tuple: "311060"
+  }
+}
+carrier_id {
+  canonical_id: 1243
+  carrier_name: "Easterbrooke Cellular Corporation"
+  carrier_attribute {
+    mccmnc_tuple: "311070"
+  }
+}
+carrier_id {
+  canonical_id: 1244
+  carrier_name: "Pine Telephone Company dba Pine Cellular"
+  carrier_attribute {
+    mccmnc_tuple: "311080"
+  }
+}
+carrier_id {
+  canonical_id: 1245
+  carrier_name: "Siouxland PCS"
+  carrier_attribute {
+    mccmnc_tuple: "311090"
+  }
+}
+carrier_id {
+  canonical_id: 1246
+  carrier_name: "Alltel Communications Inc."
+  carrier_attribute {
+    mccmnc_tuple: "311110"
+    mccmnc_tuple: "311270"
+    mccmnc_tuple: "311271"
+    mccmnc_tuple: "311272"
+    mccmnc_tuple: "311273"
+    mccmnc_tuple: "311274"
+    mccmnc_tuple: "311275"
+    mccmnc_tuple: "311276"
+    mccmnc_tuple: "311277"
+    mccmnc_tuple: "311278"
+    mccmnc_tuple: "311279"
+  }
+}
+carrier_id {
+  canonical_id: 1247
+  carrier_name: "MBO Wireless Inc./Cross Telephone Company"
+  carrier_attribute {
+    mccmnc_tuple: "311140"
+  }
+}
+carrier_id {
+  canonical_id: 1248
+  carrier_name: "Wilkes Cellular Inc."
+  carrier_attribute {
+    mccmnc_tuple: "311150"
+  }
+}
+carrier_id {
+  canonical_id: 1261
+  carrier_name: "Commnet Wireless LLC"
+  carrier_attribute {
+    mccmnc_tuple: "311320"
+  }
+}
+carrier_id {
+  canonical_id: 1262
+  carrier_name: "Bag Tussel Wireless LLC"
+  carrier_attribute {
+    mccmnc_tuple: "311330"
+  }
+}
+carrier_id {
+  canonical_id: 1263
+  carrier_name: "Illinois Valley Cellular"
+  carrier_attribute {
+    mccmnc_tuple: "311340"
+  }
+}
+carrier_id {
+  canonical_id: 1264
+  carrier_name: "Torrestar Networks Inc"
+  carrier_attribute {
+    mccmnc_tuple: "311350"
+  }
+}
+carrier_id {
+  canonical_id: 1265
+  carrier_name: "Stelera Wireless LLC"
+  carrier_attribute {
+    mccmnc_tuple: "311360"
+  }
+}
+carrier_id {
+  canonical_id: 1299
+  carrier_name: "Mobifone"
+  carrier_attribute {
+    mccmnc_tuple: "45201"
+  }
+}
+carrier_id {
+  canonical_id: 1300
+  carrier_name: "Vinaphone"
+  carrier_attribute {
+    mccmnc_tuple: "45202"
+  }
+}
+carrier_id {
+  canonical_id: 1301
+  carrier_name: "SMILE"
+  carrier_attribute {
+    mccmnc_tuple: "54101"
+  }
+}
+carrier_id {
+  canonical_id: 1302
+  carrier_name: "Telecom Samoa Cellular Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "54901"
+  }
+}
+carrier_id {
+  canonical_id: 1307
+  carrier_name: "Sentech (Pty) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "65506"
+  }
+}
+carrier_id {
+  canonical_id: 1308
+  carrier_name: "Cell C (Pty) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "65507"
+  }
+}
+carrier_id {
+  canonical_id: 1309
+  carrier_name: "Mobile Telephone Networks"
+  carrier_attribute {
+    mccmnc_tuple: "65510"
+  }
+}
+carrier_id {
+  canonical_id: 1310
+  carrier_name: "SAPS Gauteng"
+  carrier_attribute {
+    mccmnc_tuple: "65511"
+  }
+}
+carrier_id {
+  canonical_id: 1311
+  carrier_name: "Cape Town Metropolitan Council"
+  carrier_attribute {
+    mccmnc_tuple: "65521"
+  }
+}
+carrier_id {
+  canonical_id: 1312
+  carrier_name: "Bokamoso Consortium"
+  carrier_attribute {
+    mccmnc_tuple: "65530"
+  }
+}
+carrier_id {
+  canonical_id: 1313
+  carrier_name: "Karabo Telecoms (Pty) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "65531"
+  }
+}
+carrier_id {
+  canonical_id: 1314
+  carrier_name: "Ilizwi Telecommunications"
+  carrier_attribute {
+    mccmnc_tuple: "65532"
+  }
+}
+carrier_id {
+  canonical_id: 1315
+  carrier_name: "Thinta Thinta Telecommunications"
+  carrier_attribute {
+    mccmnc_tuple: "65533"
+  }
+}
+carrier_id {
+  canonical_id: 1316
+  carrier_name: "Bokone Telecoms"
+  carrier_attribute {
+    mccmnc_tuple: "65534"
+  }
+}
+carrier_id {
+  canonical_id: 1317
+  carrier_name: "Kingdom Communications"
+  carrier_attribute {
+    mccmnc_tuple: "65535"
+  }
+}
+carrier_id {
+  canonical_id: 1318
+  carrier_name: "Amatole Telecommunication Services"
+  carrier_attribute {
+    mccmnc_tuple: "65536"
+  }
+}
+carrier_id {
+  canonical_id: 1319
+  carrier_name: "Celtel Zambia Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "64501"
+  }
+}
+carrier_id {
+  canonical_id: 1320
+  carrier_name: "Telecel Zambia Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "64502"
+  }
+}
+carrier_id {
+  canonical_id: 1321
+  carrier_name: "Zamtel"
+  carrier_attribute {
+    mccmnc_tuple: "64503"
+  }
+}
+carrier_id {
+  canonical_id: 1322
+  carrier_name: "Net One"
+  carrier_attribute {
+    mccmnc_tuple: "64801"
+  }
+}
+carrier_id {
+  canonical_id: 1325
+  carrier_name: "Cable & Wireless (Antigua)"
+  carrier_attribute {
+    mccmnc_tuple: "344920"
+  }
+}
+carrier_id {
+  canonical_id: 1326
+  carrier_name: "AT&T Wireless (Antigua)"
+  carrier_attribute {
+    mccmnc_tuple: "344930"
+  }
+}
+carrier_id {
+  canonical_id: 1327
+  carrier_name: "Weblinks Limited"
+  carrier_attribute {
+    mccmnc_tuple: "365010"
+  }
+}
+carrier_id {
+  canonical_id: 1328
+  carrier_name: "Telekom Albania"
+  carrier_attribute {
+    mccmnc_tuple: "27601"
+    gid1: "01"
+  }
+}
+carrier_id {
+  canonical_id: 1329
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "27602"
+    spn: "VODAFONE AL"
+  }
+}
+carrier_id {
+  canonical_id: 1330
+  carrier_name: "Eagle Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "27603"
+  }
+}
+carrier_id {
+  canonical_id: 1331
+  carrier_name: "TELCELL GSM"
+  carrier_attribute {
+    mccmnc_tuple: "36251"
+  }
+}
+carrier_id {
+  canonical_id: 1332
+  carrier_name: "CT GSM"
+  carrier_attribute {
+    mccmnc_tuple: "36269"
+  }
+}
+carrier_id {
+  canonical_id: 1333
+  carrier_name: "SETEL GSM"
+  carrier_attribute {
+    mccmnc_tuple: "36291"
+  }
+}
+carrier_id {
+  canonical_id: 1334
+  carrier_name: "Unitel"
+  carrier_attribute {
+    mccmnc_tuple: "63102"
+  }
+}
+carrier_id {
+  canonical_id: 1335
+  carrier_name: "Compañía de Radiocomunicaciones Moviles S.A."
+  carrier_attribute {
+    mccmnc_tuple: "722010"
+  }
+}
+carrier_id {
+  canonical_id: 1336
+  carrier_name: "Nextel Argentina srl"
+  carrier_attribute {
+    mccmnc_tuple: "722020"
+  }
+}
+carrier_id {
+  canonical_id: 1337
+  carrier_name: "Telefonica Comunicaciones Personales S.A."
+  carrier_attribute {
+    mccmnc_tuple: "722070"
+    mccmnc_tuple: "72207"
+  }
+}
+carrier_id {
+  canonical_id: 1338
+  carrier_name: "Claro AR"
+  carrier_attribute {
+    mccmnc_tuple: "722310"
+  }
+}
+carrier_id {
+  canonical_id: 1339
+  carrier_name: "Compañía de Telefonos del Interior Norte S.A."
+  carrier_attribute {
+    mccmnc_tuple: "722320"
+  }
+}
+carrier_id {
+  canonical_id: 1340
+  carrier_name: "Compañía de Telefonos del Interior S.A."
+  carrier_attribute {
+    mccmnc_tuple: "722330"
+  }
+}
+carrier_id {
+  canonical_id: 1341
+  carrier_name: "Telecom Personal S.A."
+  carrier_attribute {
+    mccmnc_tuple: "722340"
+    mccmnc_tuple: "72234"
+    mccmnc_tuple: "722341"
+  }
+}
+carrier_id {
+  canonical_id: 1343
+  carrier_name: "Telefonica Austria"
+  carrier_attribute {
+    mccmnc_tuple: "23208"
+  }
+}
+carrier_id {
+  canonical_id: 1344
+  carrier_name: "Drei"
+  carrier_attribute {
+    mccmnc_tuple: "23205"
+    mccmnc_tuple: "23210"
+  }
+}
+carrier_id {
+  canonical_id: 1345
+  carrier_name: "Telstra"
+  carrier_attribute {
+    mccmnc_tuple: "50501"
+    mccmnc_tuple: "50511"
+    mccmnc_tuple: "50571"
+    mccmnc_tuple: "50572"
+  }
+}
+carrier_id {
+  canonical_id: 1346
+  carrier_name: "Department of Defence"
+  carrier_attribute {
+    mccmnc_tuple: "50504"
+  }
+}
+carrier_id {
+  canonical_id: 1347
+  carrier_name: "The Ozitel Network Pty. Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "50505"
+  }
+}
+carrier_id {
+  canonical_id: 1348
+  carrier_name: "Hutchison 3G Australia Pty. Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "50506"
+  }
+}
+carrier_id {
+  canonical_id: 1349
+  carrier_name: "One.Tel GSM 1800 Pty. Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "50508"
+    mccmnc_tuple: "50599"
+  }
+}
+carrier_id {
+  canonical_id: 1350
+  carrier_name: "Airnet Commercial Australia Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "50509"
+  }
+}
+carrier_id {
+  canonical_id: 1351
+  carrier_name: "Hutchison Telecommunications (Australia) Pty. Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "50512"
+  }
+}
+carrier_id {
+  canonical_id: 1352
+  carrier_name: "AAPT Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "50514"
+  }
+}
+carrier_id {
+  canonical_id: 1353
+  carrier_name: "3GIS Pty Ltd. (Telstra & Hutchison 3G)"
+  carrier_attribute {
+    mccmnc_tuple: "50515"
+  }
+}
+carrier_id {
+  canonical_id: 1354
+  carrier_name: "Azercell Limited Liability Joint Venture"
+  carrier_attribute {
+    mccmnc_tuple: "40001"
+  }
+}
+carrier_id {
+  canonical_id: 1355
+  carrier_name: "Catel JV"
+  carrier_attribute {
+    mccmnc_tuple: "40003"
+  }
+}
+carrier_id {
+  canonical_id: 1356
+  carrier_name: "Azerphone LLC"
+  carrier_attribute {
+    mccmnc_tuple: "40004"
+  }
+}
+carrier_id {
+  canonical_id: 1357
+  carrier_name: "Eronet Mobile Communications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "21803"
+  }
+}
+carrier_id {
+  canonical_id: 1358
+  carrier_name: "MOBI'S (Mobilina Srpske)"
+  carrier_attribute {
+    mccmnc_tuple: "21805"
+  }
+}
+carrier_id {
+  canonical_id: 1359
+  carrier_name: "GSMBIH"
+  carrier_attribute {
+    mccmnc_tuple: "21890"
+  }
+}
+carrier_id {
+  canonical_id: 1360
+  carrier_name: "Cable & Wireless (Barbados) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "342600"
+  }
+}
+carrier_id {
+  canonical_id: 1361
+  carrier_name: "Sunbeach Communications"
+  carrier_attribute {
+    mccmnc_tuple: "342820"
+  }
+}
+carrier_id {
+  canonical_id: 1362
+  carrier_name: "GramenPhone"
+  carrier_attribute {
+    mccmnc_tuple: "47001"
+  }
+}
+carrier_id {
+  canonical_id: 1363
+  carrier_name: "Aktel"
+  carrier_attribute {
+    mccmnc_tuple: "47002"
+  }
+}
+carrier_id {
+  canonical_id: 1364
+  carrier_name: "Mobile 2000"
+  carrier_attribute {
+    mccmnc_tuple: "47003"
+  }
+}
+carrier_id {
+  canonical_id: 1365
+  carrier_name: "Proximus"
+  carrier_attribute {
+    mccmnc_tuple: "20601"
+  }
+}
+carrier_id {
+  canonical_id: 1366
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "20610"
+  }
+}
+carrier_id {
+  canonical_id: 1367
+  carrier_name: "BASE"
+  carrier_attribute {
+    mccmnc_tuple: "20620"
+  }
+}
+carrier_id {
+  canonical_id: 1368
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "61302"
+  }
+}
+carrier_id {
+  canonical_id: 1369
+  carrier_name: "Telecel"
+  carrier_attribute {
+    mccmnc_tuple: "61303"
+  }
+}
+carrier_id {
+  canonical_id: 1370
+  carrier_name: "Mtel"
+  carrier_attribute {
+    mccmnc_tuple: "28401"
+  }
+}
+carrier_id {
+  canonical_id: 1371
+  carrier_name: "Telenor"
+  carrier_attribute {
+    mccmnc_tuple: "28405"
+  }
+}
+carrier_id {
+  canonical_id: 1372
+  carrier_name: "Batelco"
+  carrier_attribute {
+    mccmnc_tuple: "42601"
+    mccmnc_tuple: "42605"
+  }
+}
+carrier_id {
+  canonical_id: 1373
+  carrier_name: "Spacetel Burundi"
+  carrier_attribute {
+    mccmnc_tuple: "64201"
+  }
+}
+carrier_id {
+  canonical_id: 1374
+  carrier_name: "Safaris"
+  carrier_attribute {
+    mccmnc_tuple: "64202"
+  }
+}
+carrier_id {
+  canonical_id: 1375
+  carrier_name: "Telecel Burundi Company"
+  carrier_attribute {
+    mccmnc_tuple: "64203"
+  }
+}
+carrier_id {
+  canonical_id: 1376
+  carrier_name: "Libercom"
+  carrier_attribute {
+    mccmnc_tuple: "61601"
+  }
+}
+carrier_id {
+  canonical_id: 1377
+  carrier_name: "Telecel"
+  carrier_attribute {
+    mccmnc_tuple: "61602"
+  }
+}
+carrier_id {
+  canonical_id: 1378
+  carrier_name: "Spacetel Benin"
+  carrier_attribute {
+    mccmnc_tuple: "61603"
+  }
+}
+carrier_id {
+  canonical_id: 1379
+  carrier_name: "DST Com"
+  carrier_attribute {
+    mccmnc_tuple: "52811"
+  }
+}
+carrier_id {
+  canonical_id: 1380
+  carrier_name: "Nuevatel S.A."
+  carrier_attribute {
+    mccmnc_tuple: "73601"
+  }
+}
+carrier_id {
+  canonical_id: 1381
+  carrier_name: "ENTEL S.A."
+  carrier_attribute {
+    mccmnc_tuple: "73602"
+  }
+}
+carrier_id {
+  canonical_id: 1382
+  carrier_name: "Telecel S.A."
+  carrier_attribute {
+    mccmnc_tuple: "73603"
+  }
+}
+carrier_id {
+  canonical_id: 1383
+  carrier_name: "Nextel"
+  carrier_attribute {
+    mccmnc_tuple: "72400"
+    mccmnc_tuple: "72439"
+  }
+}
+carrier_id {
+  canonical_id: 1384
+  carrier_name: "CRT Cellular"
+  carrier_attribute {
+    mccmnc_tuple: "72401"
+  }
+}
+carrier_id {
+  canonical_id: 1385
+  carrier_name: "TIM"
+  carrier_attribute {
+    mccmnc_tuple: "72402"
+    mccmnc_tuple: "72403"
+    mccmnc_tuple: "72404"
+  }
+}
+carrier_id {
+  canonical_id: 1388
+  carrier_name: "Sercontel Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72407"
+  }
+}
+carrier_id {
+  canonical_id: 1389
+  carrier_name: "Oi"
+  carrier_attribute {
+    mccmnc_tuple: "72430"
+    mccmnc_tuple: "72431"
+  }
+}
+carrier_id {
+  canonical_id: 1390
+  carrier_name: "CTBC Celular"
+  carrier_attribute {
+    mccmnc_tuple: "72432"
+    mccmnc_tuple: "72433"
+    mccmnc_tuple: "72434"
+  }
+}
+carrier_id {
+  canonical_id: 1391
+  carrier_name: "Telebahia Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72435"
+  }
+}
+carrier_id {
+  canonical_id: 1392
+  carrier_name: "Telergipe Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72437"
+  }
+}
+carrier_id {
+  canonical_id: 1394
+  carrier_name: "Telpe Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72441"
+  }
+}
+carrier_id {
+  canonical_id: 1395
+  carrier_name: "Telepisa Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72443"
+  }
+}
+carrier_id {
+  canonical_id: 1396
+  carrier_name: "Telpa Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72445"
+  }
+}
+carrier_id {
+  canonical_id: 1397
+  carrier_name: "Telern Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72447"
+  }
+}
+carrier_id {
+  canonical_id: 1398
+  carrier_name: "Teleceara Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72448"
+  }
+}
+carrier_id {
+  canonical_id: 1399
+  carrier_name: "Telma Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72451"
+  }
+}
+carrier_id {
+  canonical_id: 1400
+  carrier_name: "Telepara Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72453"
+  }
+}
+carrier_id {
+  canonical_id: 1401
+  carrier_name: "Teleamazon Cel"
+  carrier_attribute {
+    mccmnc_tuple: "72455"
+  }
+}
+carrier_id {
+  canonical_id: 1402
+  carrier_name: "B-Mobile of Bhutan Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "40217"
+  }
+}
+carrier_id {
+  canonical_id: 1403
+  carrier_name: "Rogers"
+  carrier_attribute {
+    mccmnc_tuple: "302720"
+    mccmnc_tuple: "30272"
+  }
+}
+carrier_id {
+  canonical_id: 1404
+  carrier_name: "TELUS Mobility"
+  carrier_attribute {
+    mccmnc_tuple: "302220"
+    mccmnc_tuple: "302221"
+    mccmnc_tuple: "30222"
+    mccmnc_tuple: "30286"
+  }
+}
+carrier_id {
+  canonical_id: 1405
+  carrier_name: "Vodacom Congo RDC sprl"
+  carrier_attribute {
+    mccmnc_tuple: "63001"
+  }
+}
+carrier_id {
+  canonical_id: 1406
+  carrier_name: "Supercell Sprl"
+  carrier_attribute {
+    mccmnc_tuple: "63005"
+  }
+}
+carrier_id {
+  canonical_id: 1407
+  carrier_name: "Orange RDC"
+  carrier_attribute {
+    mccmnc_tuple: "63086"
+  }
+}
+carrier_id {
+  canonical_id: 1408
+  carrier_name: "Centrafrique Telecom Plus (CTP)"
+  carrier_attribute {
+    mccmnc_tuple: "62301"
+  }
+}
+carrier_id {
+  canonical_id: 1409
+  carrier_name: "Telecel Centrafrique (TC)"
+  carrier_attribute {
+    mccmnc_tuple: "62302"
+  }
+}
+carrier_id {
+  canonical_id: 1410
+  carrier_name: "Orange Centrafricaine"
+  carrier_attribute {
+    mccmnc_tuple: "62303"
+  }
+}
+carrier_id {
+  canonical_id: 1411
+  carrier_name: "Celtel"
+  carrier_attribute {
+    mccmnc_tuple: "62901"
+  }
+}
+carrier_id {
+  canonical_id: 1412
+  carrier_name: "Libertis Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "62910"
+  }
+}
+carrier_id {
+  canonical_id: 1413
+  carrier_name: "Sunrise"
+  carrier_attribute {
+    mccmnc_tuple: "22802"
+    mccmnc_tuple: "22812"
+  }
+}
+carrier_id {
+  canonical_id: 1414
+  carrier_name: "Salt"
+  carrier_attribute {
+    mccmnc_tuple: "22803"
+  }
+}
+carrier_id {
+  canonical_id: 1415
+  carrier_name: "Comfone AG"
+  carrier_attribute {
+    mccmnc_tuple: "22805"
+  }
+}
+carrier_id {
+  canonical_id: 1416
+  carrier_name: "SBB AG"
+  carrier_attribute {
+    mccmnc_tuple: "22806"
+  }
+}
+carrier_id {
+  canonical_id: 1417
+  carrier_name: "IN&Phone SA"
+  carrier_attribute {
+    mccmnc_tuple: "22807"
+  }
+}
+carrier_id {
+  canonical_id: 1418
+  carrier_name: "Tele2 Telecommunications AG"
+  carrier_attribute {
+    mccmnc_tuple: "22808"
+  }
+}
+carrier_id {
+  canonical_id: 1419
+  carrier_name: "Bebbicell AG"
+  carrier_attribute {
+    mccmnc_tuple: "22851"
+  }
+}
+carrier_id {
+  canonical_id: 1420
+  carrier_name: "Atlantique Cellulaire"
+  carrier_attribute {
+    mccmnc_tuple: "61202"
+  }
+}
+carrier_id {
+  canonical_id: 1421
+  carrier_name: "Orange Côte d'Ivoire"
+  carrier_attribute {
+    mccmnc_tuple: "61203"
+  }
+}
+carrier_id {
+  canonical_id: 1422
+  carrier_name: "Comium Côte d'Ivoire"
+  carrier_attribute {
+    mccmnc_tuple: "61204"
+  }
+}
+carrier_id {
+  canonical_id: 1423
+  carrier_name: "Loteny Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "61205"
+  }
+}
+carrier_id {
+  canonical_id: 1424
+  carrier_name: "Oricel Côte d'Ivoire"
+  carrier_attribute {
+    mccmnc_tuple: "61206"
+  }
+}
+carrier_id {
+  canonical_id: 1425
+  carrier_name: "Aircomm Côte d'Ivoire"
+  carrier_attribute {
+    mccmnc_tuple: "61207"
+  }
+}
+carrier_id {
+  canonical_id: 1426
+  carrier_name: "Telecom Cook"
+  carrier_attribute {
+    mccmnc_tuple: "54801"
+  }
+}
+carrier_id {
+  canonical_id: 1427
+  carrier_name: "Entel"
+  carrier_attribute {
+    mccmnc_tuple: "73001"
+    mccmnc_tuple: "73010"
+  }
+}
+carrier_id {
+  canonical_id: 1428
+  carrier_name: "Telefónica Móvil"
+  carrier_attribute {
+    mccmnc_tuple: "73002"
+    mccmnc_tuple: "73007"
+  }
+}
+carrier_id {
+  canonical_id: 1429
+  carrier_name: "Claro CL"
+  carrier_attribute {
+    mccmnc_tuple: "73003"
+  }
+}
+carrier_id {
+  canonical_id: 1430
+  carrier_name: "Centennial Cayman Corp. Chile S.A."
+  carrier_attribute {
+    mccmnc_tuple: "73004"
+  }
+}
+carrier_id {
+  canonical_id: 1431
+  carrier_name: "Multikom S.A."
+  carrier_attribute {
+    mccmnc_tuple: "73005"
+  }
+}
+carrier_id {
+  canonical_id: 1433
+  carrier_name: "Mobile Telephone Networks Cameroon"
+  carrier_attribute {
+    mccmnc_tuple: "62401"
+  }
+}
+carrier_id {
+  canonical_id: 1434
+  carrier_name: "Orange Cameroun"
+  carrier_attribute {
+    mccmnc_tuple: "62402"
+  }
+}
+carrier_id {
+  canonical_id: 1435
+  carrier_name: "China Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "46000"
+    mccmnc_tuple: "46002"
+    mccmnc_tuple: "46007"
+  }
+}
+carrier_id {
+  canonical_id: 1436
+  carrier_name: "China Unicom"
+  carrier_attribute {
+    mccmnc_tuple: "46001"
+    mccmnc_tuple: "46003"
+  }
+}
+carrier_id {
+  canonical_id: 1437
+  carrier_name: "China Satellite Global Star Network"
+  carrier_attribute {
+    mccmnc_tuple: "46004"
+  }
+}
+carrier_id {
+  canonical_id: 1438
+  carrier_name: "Colombia Telecomunicaciones S.A. - Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "732001"
+  }
+}
+carrier_id {
+  canonical_id: 1439
+  carrier_name: "Edatel S.A."
+  carrier_attribute {
+    mccmnc_tuple: "732002"
+  }
+}
+carrier_id {
+  canonical_id: 1440
+  carrier_name: "Emtelsa"
+  carrier_attribute {
+    mccmnc_tuple: "732020"
+  }
+}
+carrier_id {
+  canonical_id: 1441
+  carrier_name: "Emcali"
+  carrier_attribute {
+    mccmnc_tuple: "732099"
+  }
+}
+carrier_id {
+  canonical_id: 1442
+  carrier_name: "Claro CO"
+  carrier_attribute {
+    mccmnc_tuple: "732101"
+  }
+}
+carrier_id {
+  canonical_id: 1443
+  carrier_name: "Bellsouth Colombia S.A."
+  carrier_attribute {
+    mccmnc_tuple: "732102"
+  }
+}
+carrier_id {
+  canonical_id: 1444
+  carrier_name: "ETECSA"
+  carrier_attribute {
+    mccmnc_tuple: "36801"
+  }
+}
+carrier_id {
+  canonical_id: 1445
+  carrier_name: "Cabo Verde Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "62501"
+  }
+}
+carrier_id {
+  canonical_id: 1446
+  carrier_name: "T+Telecomunicaçôes"
+  carrier_attribute {
+    mccmnc_tuple: "62502"
+  }
+}
+carrier_id {
+  canonical_id: 1447
+  carrier_name: "CYTA"
+  carrier_attribute {
+    mccmnc_tuple: "28001"
+  }
+}
+carrier_id {
+  canonical_id: 1448
+  carrier_name: "Scancom (Cyprus) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "28010"
+  }
+}
+carrier_id {
+  canonical_id: 1449
+  carrier_name: "O2"
+  carrier_attribute {
+    mccmnc_tuple: "23002"
+  }
+}
+carrier_id {
+  canonical_id: 1450
+  carrier_name: "Mobilkom a.s."
+  carrier_attribute {
+    mccmnc_tuple: "23004"
+  }
+}
+carrier_id {
+  canonical_id: 1451
+  carrier_name: "Sprava Zeleznicni Dopravni Cesty"
+  carrier_attribute {
+    mccmnc_tuple: "23098"
+  }
+}
+carrier_id {
+  canonical_id: 1452
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "23003"
+    spn: "Vodafone CZ"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "23099"
+    imsi_prefix_xpattern: "x"
+  }
+}
+carrier_id {
+  canonical_id: 1453
+  carrier_name: "Telefonica"
+  carrier_attribute {
+    mccmnc_tuple: "26203"
+    mccmnc_tuple: "26205"
+    mccmnc_tuple: "26277"
+  }
+}
+carrier_id {
+  canonical_id: 1454
+  carrier_name: "o2"
+  carrier_attribute {
+    mccmnc_tuple: "26207"
+    mccmnc_tuple: "26208"
+  }
+}
+carrier_id {
+  canonical_id: 1455
+  carrier_name: "Arcor AG & Co."
+  carrier_attribute {
+    mccmnc_tuple: "26210"
+  }
+}
+carrier_id {
+  canonical_id: 1456
+  carrier_name: "O2 (Germany) GmbH & Co. OHG"
+  carrier_attribute {
+    mccmnc_tuple: "26211"
+  }
+}
+carrier_id {
+  canonical_id: 1457
+  carrier_name: "Dolphin Telecom (Deutschland) GmbH"
+  carrier_attribute {
+    mccmnc_tuple: "26212"
+  }
+}
+carrier_id {
+  canonical_id: 1458
+  carrier_name: "Mobilcom Multimedia GmbH"
+  carrier_attribute {
+    mccmnc_tuple: "26213"
+  }
+}
+carrier_id {
+  canonical_id: 1459
+  carrier_name: "Group 3G UMTS GmbH (Quam)"
+  carrier_attribute {
+    mccmnc_tuple: "26214"
+  }
+}
+carrier_id {
+  canonical_id: 1460
+  carrier_name: "Airdata AG"
+  carrier_attribute {
+    mccmnc_tuple: "26215"
+  }
+}
+carrier_id {
+  canonical_id: 1461
+  carrier_name: "Siemens AG, ICMNPGUSTA"
+  carrier_attribute {
+    mccmnc_tuple: "26276"
+  }
+}
+carrier_id {
+  canonical_id: 1462
+  carrier_name: "Evatis"
+  carrier_attribute {
+    mccmnc_tuple: "63801"
+  }
+}
+carrier_id {
+  canonical_id: 1463
+  carrier_name: "TDC Mobil"
+  carrier_attribute {
+    mccmnc_tuple: "23801"
+    mccmnc_tuple: "23810"
+  }
+}
+carrier_id {
+  canonical_id: 1464
+  carrier_name: "Telenor"
+  carrier_attribute {
+    mccmnc_tuple: "23802"
+    mccmnc_tuple: "23866"
+  }
+}
+carrier_id {
+  canonical_id: 1465
+  carrier_name: "MIGway A/S"
+  carrier_attribute {
+    mccmnc_tuple: "23803"
+  }
+}
+carrier_id {
+  canonical_id: 1466
+  carrier_name: "3"
+  carrier_attribute {
+    mccmnc_tuple: "23806"
+  }
+}
+carrier_id {
+  canonical_id: 1467
+  carrier_name: "Claro RD"
+  carrier_attribute {
+    mccmnc_tuple: "37002"
+  }
+}
+carrier_id {
+  canonical_id: 1468
+  carrier_name: "Tricom S.A."
+  carrier_attribute {
+    mccmnc_tuple: "37003"
+  }
+}
+carrier_id {
+  canonical_id: 1469
+  carrier_name: "CentennialDominicana"
+  carrier_attribute {
+    mccmnc_tuple: "37004"
+  }
+}
+carrier_id {
+  canonical_id: 1470
+  carrier_name: "Algérie Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "60301"
+  }
+}
+carrier_id {
+  canonical_id: 1471
+  carrier_name: "Orascom Telecom Algérie"
+  carrier_attribute {
+    mccmnc_tuple: "60302"
+  }
+}
+carrier_id {
+  canonical_id: 1472
+  carrier_name: "Movistar (Otecel S.A.)"
+  carrier_attribute {
+    mccmnc_tuple: "74000"
+  }
+}
+carrier_id {
+  canonical_id: 1473
+  carrier_name: "Claro EC"
+  carrier_attribute {
+    mccmnc_tuple: "74001"
+  }
+}
+carrier_id {
+  canonical_id: 1474
+  carrier_name: "Telecsa S.A."
+  carrier_attribute {
+    mccmnc_tuple: "74002"
+  }
+}
+carrier_id {
+  canonical_id: 1475
+  carrier_name: "Elisa Matkapuhelinpalvelut Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "24405"
+  }
+}
+carrier_id {
+  canonical_id: 1476
+  carrier_name: "Finnet Group"
+  carrier_attribute {
+    mccmnc_tuple: "24409"
+  }
+}
+carrier_id {
+  canonical_id: 1477
+  carrier_name: "Alands Mobiltelefon AB"
+  carrier_attribute {
+    mccmnc_tuple: "24414"
+  }
+}
+carrier_id {
+  canonical_id: 1478
+  carrier_name: "Oy Finland Tele2 AB"
+  carrier_attribute {
+    mccmnc_tuple: "24416"
+  }
+}
+carrier_id {
+  canonical_id: 1479
+  carrier_name: "Saunalahti Group Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "24421"
+  }
+}
+carrier_id {
+  canonical_id: 1480
+  carrier_name: "Telia"
+  carrier_attribute {
+    mccmnc_tuple: "24491"
+  }
+}
+carrier_id {
+  canonical_id: 1481
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "54201"
+  }
+}
+carrier_id {
+  canonical_id: 1482
+  carrier_name: "FSM Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "55001"
+  }
+}
+carrier_id {
+  canonical_id: 1483
+  carrier_name: "Faroese Telecom - GSM"
+  carrier_attribute {
+    mccmnc_tuple: "28801"
+  }
+}
+carrier_id {
+  canonical_id: 1484
+  carrier_name: "Kall GSM"
+  carrier_attribute {
+    mccmnc_tuple: "28802"
+  }
+}
+carrier_id {
+  canonical_id: 1486
+  carrier_name: "Globalstar Europe"
+  carrier_attribute {
+    mccmnc_tuple: "20805"
+    mccmnc_tuple: "20806"
+    mccmnc_tuple: "20807"
+  }
+}
+carrier_id {
+  canonical_id: 1487
+  carrier_name: "Bouygues Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "20820"
+    mccmnc_tuple: "20821"
+    mccmnc_tuple: "20888"
+  }
+}
+carrier_id {
+  canonical_id: 1488
+  carrier_name: "Libertis S.A."
+  carrier_attribute {
+    mccmnc_tuple: "62801"
+  }
+}
+carrier_id {
+  canonical_id: 1489
+  carrier_name: "Telecel Gabon S.A."
+  carrier_attribute {
+    mccmnc_tuple: "62802"
+  }
+}
+carrier_id {
+  canonical_id: 1490
+  carrier_name: "Celtel Gabon S.A."
+  carrier_attribute {
+    mccmnc_tuple: "62803"
+  }
+}
+carrier_id {
+  canonical_id: 1491
+  carrier_name: "Mapesbury Communications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "23401"
+  }
+}
+carrier_id {
+  canonical_id: 1492
+  carrier_name: "O2"
+  carrier_attribute {
+    mccmnc_tuple: "23402"
+    mccmnc_tuple: "23410"
+    mccmnc_tuple: "23411"
+  }
+}
+carrier_id {
+  canonical_id: 1493
+  carrier_name: "Jersey Telenet Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "23403"
+  }
+}
+carrier_id {
+  canonical_id: 1494
+  carrier_name: "FMS Solutions Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "23404"
+  }
+}
+carrier_id {
+  canonical_id: 1495
+  carrier_name: "Colt Mobile Telecommunications Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "23405"
+  }
+}
+carrier_id {
+  canonical_id: 1496
+  carrier_name: "Internet One Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "23406"
+  }
+}
+carrier_id {
+  canonical_id: 1497
+  carrier_name: "Cable and Wireless plc"
+  carrier_attribute {
+    mccmnc_tuple: "23407"
+  }
+}
+carrier_id {
+  canonical_id: 1498
+  carrier_name: "Wire9 Telecom plc"
+  carrier_attribute {
+    mccmnc_tuple: "23409"
+    mccmnc_tuple: "23418"
+  }
+}
+carrier_id {
+  canonical_id: 1500
+  carrier_name: "Ntework Rail Infrastructure Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "23412"
+    mccmnc_tuple: "23413"
+  }
+}
+carrier_id {
+  canonical_id: 1501
+  carrier_name: "Hay Systems Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "23414"
+  }
+}
+carrier_id {
+  canonical_id: 1502
+  carrier_name: "Opal Telecom Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "23416"
+  }
+}
+carrier_id {
+  canonical_id: 1503
+  carrier_name: "Flextel Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "23417"
+  }
+}
+carrier_id {
+  canonical_id: 1504
+  carrier_name: "Teleware plc"
+  carrier_attribute {
+    mccmnc_tuple: "23419"
+  }
+}
+carrier_id {
+  canonical_id: 1505
+  carrier_name: "Three Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "23420"
+  }
+}
+carrier_id {
+  canonical_id: 1506
+  carrier_name: "Jersey Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "23450"
+  }
+}
+carrier_id {
+  canonical_id: 1507
+  carrier_name: "Manx Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "23458"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "23410"
+    gid1: "519"
+  }
+}
+carrier_id {
+  canonical_id: 1508
+  carrier_name: "Inquam Telecom (Holdings) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "23475"
+  }
+}
+carrier_id {
+  canonical_id: 1509
+  carrier_name: "British Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "23400"
+    mccmnc_tuple: "23476"
+  }
+}
+carrier_id {
+  canonical_id: 1510
+  carrier_name: "Airwave mmO2 Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "23478"
+  }
+}
+carrier_id {
+  canonical_id: 1511
+  carrier_name: "Geocell Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "28201"
+  }
+}
+carrier_id {
+  canonical_id: 1512
+  carrier_name: "Magti GSM Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "28202"
+  }
+}
+carrier_id {
+  canonical_id: 1513
+  carrier_name: "Iberiatel Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "28203"
+  }
+}
+carrier_id {
+  canonical_id: 1514
+  carrier_name: "Mobitel Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "28204"
+  }
+}
+carrier_id {
+  canonical_id: 1515
+  carrier_name: "MTN"
+  carrier_attribute {
+    mccmnc_tuple: "62001"
+  }
+}
+carrier_id {
+  canonical_id: 1516
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "62002"
+  }
+}
+carrier_id {
+  canonical_id: 1517
+  carrier_name: "Mobitel"
+  carrier_attribute {
+    mccmnc_tuple: "62003"
+  }
+}
+carrier_id {
+  canonical_id: 1518
+  carrier_name: "Kasapa Telecom Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "62004"
+  }
+}
+carrier_id {
+  canonical_id: 1519
+  carrier_name: "Telestet"
+  carrier_attribute {
+    mccmnc_tuple: "20210"
+  }
+}
+carrier_id {
+  canonical_id: 1520
+  carrier_name: "Claro GT"
+  carrier_attribute {
+    mccmnc_tuple: "70401"
+  }
+}
+carrier_id {
+  canonical_id: 1521
+  carrier_name: "Comunicaciones Celulares S.A."
+  carrier_attribute {
+    mccmnc_tuple: "70402"
+  }
+}
+carrier_id {
+  canonical_id: 1522
+  carrier_name: "Telefónica Centroamérica Guatemala S.A."
+  carrier_attribute {
+    mccmnc_tuple: "70403"
+    mccmnc_tuple: "704030"
+  }
+}
+carrier_id {
+  canonical_id: 1523
+  carrier_name: "Guinétel S.A."
+  carrier_attribute {
+    mccmnc_tuple: "63201"
+  }
+}
+carrier_id {
+  canonical_id: 1524
+  carrier_name: "Spacetel Guiné-Bissau S.A."
+  carrier_attribute {
+    mccmnc_tuple: "63202"
+  }
+}
+carrier_id {
+  canonical_id: 1525
+  carrier_name: "Cel*Star (Guyana) Inc."
+  carrier_attribute {
+    mccmnc_tuple: "73801"
+  }
+}
+carrier_id {
+  canonical_id: 1526
+  carrier_name: "1O1O / csl"
+  carrier_attribute {
+    mccmnc_tuple: "45400"
+    mccmnc_tuple: "45419"
+  }
+}
+carrier_id {
+  canonical_id: 1527
+  carrier_name: "MVNO/CITIC"
+  carrier_attribute {
+    mccmnc_tuple: "45401"
+  }
+}
+carrier_id {
+  canonical_id: 1528
+  carrier_name: "Celtel"
+  carrier_attribute {
+    mccmnc_tuple: "708002"
+    mccmnc_tuple: "70802"
+    mccmnc_tuple: "708020"
+  }
+}
+carrier_id {
+  canonical_id: 1529
+  carrier_name: "Tele2"
+  carrier_attribute {
+    mccmnc_tuple: "21902"
+  }
+}
+carrier_id {
+  canonical_id: 1530
+  carrier_name: "Vip/Tomato"
+  carrier_attribute {
+    mccmnc_tuple: "21910"
+  }
+}
+carrier_id {
+  canonical_id: 1531
+  carrier_name: "Comcel"
+  carrier_attribute {
+    mccmnc_tuple: "37201"
+  }
+}
+carrier_id {
+  canonical_id: 1532
+  carrier_name: "Digicel"
+  carrier_attribute {
+    mccmnc_tuple: "37202"
+  }
+}
+carrier_id {
+  canonical_id: 1533
+  carrier_name: "Rectel"
+  carrier_attribute {
+    mccmnc_tuple: "37203"
+  }
+}
+carrier_id {
+  canonical_id: 1534
+  carrier_name: "Telenor"
+  carrier_attribute {
+    mccmnc_tuple: "21601"
+  }
+}
+carrier_id {
+  canonical_id: 1535
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "21670"
+    spn: ""
+    spn: "vodafone HU"
+  }
+}
+carrier_id {
+  canonical_id: 1536
+  carrier_name: "PSN"
+  carrier_attribute {
+    mccmnc_tuple: "51000"
+  }
+}
+carrier_id {
+  canonical_id: 1537
+  carrier_name: "Indosat"
+  carrier_attribute {
+    mccmnc_tuple: "51001"
+  }
+}
+carrier_id {
+  canonical_id: 1543
+  carrier_name: "Reliance"
+  carrier_attribute {
+    mccmnc_tuple: "40409"
+    mccmnc_tuple: "40418"
+    mccmnc_tuple: "40436"
+    mccmnc_tuple: "40450"
+    mccmnc_tuple: "40452"
+    mccmnc_tuple: "40467"
+    mccmnc_tuple: "40485"
+  }
+}
+carrier_id {
+  canonical_id: 1545
+  carrier_name: "BPL Mobile Communications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "40421"
+  }
+}
+carrier_id {
+  canonical_id: 1549
+  carrier_name: "Bharat Sanchar Nigam Ltd. (BSNL)"
+  carrier_attribute {
+    mccmnc_tuple: "40434"
+    mccmnc_tuple: "40438"
+    mccmnc_tuple: "40451"
+    mccmnc_tuple: "40453"
+    mccmnc_tuple: "40454"
+    mccmnc_tuple: "40455"
+    mccmnc_tuple: "40457"
+    mccmnc_tuple: "40458"
+    mccmnc_tuple: "40459"
+    mccmnc_tuple: "40462"
+    mccmnc_tuple: "40464"
+    mccmnc_tuple: "40466"
+    mccmnc_tuple: "40471"
+    mccmnc_tuple: "40472"
+    mccmnc_tuple: "40473"
+    mccmnc_tuple: "40474"
+    mccmnc_tuple: "40475"
+    mccmnc_tuple: "40476"
+    mccmnc_tuple: "40477"
+    mccmnc_tuple: "40480"
+    mccmnc_tuple: "40481"
+  }
+}
+carrier_id {
+  canonical_id: 1550
+  carrier_name: "RPG Cellular"
+  carrier_attribute {
+    mccmnc_tuple: "40441"
+  }
+}
+carrier_id {
+  canonical_id: 1551
+  carrier_name: "Aircel Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "40442"
+  }
+}
+carrier_id {
+  canonical_id: 1556
+  carrier_name: "Mahanagar Telephone Nigam Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "40468"
+    mccmnc_tuple: "40469"
+  }
+}
+carrier_id {
+  canonical_id: 1559
+  carrier_name: "Reliable Internet Services Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "40483"
+  }
+}
+carrier_id {
+  canonical_id: 1562
+  carrier_name: "IR-MCI (Hamrahe Avval)"
+  carrier_attribute {
+    mccmnc_tuple: "43211"
+  }
+}
+carrier_id {
+  canonical_id: 1563
+  carrier_name: "Telecommunication Kish Co. (KIFZO)"
+  carrier_attribute {
+    mccmnc_tuple: "43214"
+  }
+}
+carrier_id {
+  canonical_id: 1564
+  carrier_name: "MTCE (Espadan)"
+  carrier_attribute {
+    mccmnc_tuple: "43219"
+  }
+}
+carrier_id {
+  canonical_id: 1565
+  carrier_name: "Iceland Telecom Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "27401"
+  }
+}
+carrier_id {
+  canonical_id: 1566
+  carrier_name: "Tal hf"
+  carrier_attribute {
+    mccmnc_tuple: "27402"
+  }
+}
+carrier_id {
+  canonical_id: 1567
+  carrier_name: "Islandssimi GSM ehf"
+  carrier_attribute {
+    mccmnc_tuple: "27403"
+  }
+}
+carrier_id {
+  canonical_id: 1568
+  carrier_name: "IMC Islande ehf"
+  carrier_attribute {
+    mccmnc_tuple: "27404"
+  }
+}
+carrier_id {
+  canonical_id: 1569
+  carrier_name: "IceCell ehf"
+  carrier_attribute {
+    mccmnc_tuple: "27407"
+  }
+}
+carrier_id {
+  canonical_id: 1571
+  carrier_name: "Elsacom"
+  carrier_attribute {
+    mccmnc_tuple: "22202"
+  }
+}
+carrier_id {
+  canonical_id: 1572
+  carrier_name: "IPSE 2000"
+  carrier_attribute {
+    mccmnc_tuple: "22277"
+  }
+}
+carrier_id {
+  canonical_id: 1573
+  carrier_name: "Wind"
+  carrier_attribute {
+    mccmnc_tuple: "22288"
+  }
+}
+carrier_id {
+  canonical_id: 1574
+  carrier_name: "Blu"
+  carrier_attribute {
+    mccmnc_tuple: "22298"
+  }
+}
+carrier_id {
+  canonical_id: 1575
+  carrier_name: "3"
+  carrier_attribute {
+    mccmnc_tuple: "22299"
+  }
+}
+carrier_id {
+  canonical_id: 1576
+  carrier_name: "Cable & Wireless Jamaica Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "338020"
+  }
+}
+carrier_id {
+  canonical_id: 1577
+  carrier_name: "Mossel (Jamaica) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "338050"
+  }
+}
+carrier_id {
+  canonical_id: 1578
+  carrier_name: "Fastlink"
+  carrier_attribute {
+    mccmnc_tuple: "41601"
+  }
+}
+carrier_id {
+  canonical_id: 1579
+  carrier_name: "Xpress"
+  carrier_attribute {
+    mccmnc_tuple: "41602"
+  }
+}
+carrier_id {
+  canonical_id: 1580
+  carrier_name: "Umniah"
+  carrier_attribute {
+    mccmnc_tuple: "41603"
+  }
+}
+carrier_id {
+  canonical_id: 1581
+  carrier_name: "au"
+  carrier_attribute {
+    mccmnc_tuple: "44050"
+    mccmnc_tuple: "44051"
+    mccmnc_tuple: "44052"
+  }
+}
+carrier_id {
+  canonical_id: 1585
+  carrier_name: "Zain"
+  carrier_attribute {
+    mccmnc_tuple: "41902"
+  }
+}
+carrier_id {
+  canonical_id: 1586
+  carrier_name: "Ooredoo"
+  carrier_attribute {
+    mccmnc_tuple: "41903"
+  }
+}
+carrier_id {
+  canonical_id: 1587
+  carrier_name: "Cable & Wireless (Cayman)"
+  carrier_attribute {
+    mccmnc_tuple: "346140"
+  }
+}
+carrier_id {
+  canonical_id: 1588
+  carrier_name: "Beeline"
+  carrier_attribute {
+    mccmnc_tuple: "40101"
+  }
+}
+carrier_id {
+  canonical_id: 1589
+  carrier_name: "TSC Kazak Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "40102"
+  }
+}
+carrier_id {
+  canonical_id: 1590
+  carrier_name: "Lao Telecommunications"
+  carrier_attribute {
+    mccmnc_tuple: "45701"
+  }
+}
+carrier_id {
+  canonical_id: 1591
+  carrier_name: "ETL Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "45702"
+  }
+}
+carrier_id {
+  canonical_id: 1592
+  carrier_name: "Millicom"
+  carrier_attribute {
+    mccmnc_tuple: "45708"
+  }
+}
+carrier_id {
+  canonical_id: 1593
+  carrier_name: "Cellis"
+  carrier_attribute {
+    mccmnc_tuple: "41532"
+    mccmnc_tuple: "41533"
+    mccmnc_tuple: "41534"
+    mccmnc_tuple: "41535"
+  }
+}
+carrier_id {
+  canonical_id: 1594
+  carrier_name: "Libancell"
+  carrier_attribute {
+    mccmnc_tuple: "41536"
+    mccmnc_tuple: "41537"
+    mccmnc_tuple: "41538"
+    mccmnc_tuple: "41539"
+  }
+}
+carrier_id {
+  canonical_id: 1595
+  carrier_name: "Telecom FL AG"
+  carrier_attribute {
+    mccmnc_tuple: "29501"
+  }
+}
+carrier_id {
+  canonical_id: 1596
+  carrier_name: "Viag Europlatform AG"
+  carrier_attribute {
+    mccmnc_tuple: "29502"
+  }
+}
+carrier_id {
+  canonical_id: 1597
+  carrier_name: "Mobilkom (Liechstein) AG"
+  carrier_attribute {
+    mccmnc_tuple: "29505"
+  }
+}
+carrier_id {
+  canonical_id: 1598
+  carrier_name: "Tele2 AG"
+  carrier_attribute {
+    mccmnc_tuple: "29577"
+  }
+}
+carrier_id {
+  canonical_id: 1599
+  carrier_name: "MTN Network Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "41302"
+  }
+}
+carrier_id {
+  canonical_id: 1600
+  carrier_name: "Celtel Lanka Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "41303"
+  }
+}
+carrier_id {
+  canonical_id: 1601
+  carrier_name: "Comium Liberia"
+  carrier_attribute {
+    mccmnc_tuple: "61804"
+  }
+}
+carrier_id {
+  canonical_id: 1602
+  carrier_name: "Vodacom Lesotho (pty) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "65101"
+  }
+}
+carrier_id {
+  canonical_id: 1603
+  carrier_name: "Econet Ezin-cel"
+  carrier_attribute {
+    mccmnc_tuple: "65102"
+  }
+}
+carrier_id {
+  canonical_id: 1604
+  carrier_name: "MTEL d.o.o. Podgorica"
+  carrier_attribute {
+    mccmnc_tuple: "29703"
+  }
+}
+carrier_id {
+  canonical_id: 1605
+  carrier_name: "MADACOM"
+  carrier_attribute {
+    mccmnc_tuple: "64601"
+  }
+}
+carrier_id {
+  canonical_id: 1606
+  carrier_name: "Orange Madagascar"
+  carrier_attribute {
+    mccmnc_tuple: "64602"
+  }
+}
+carrier_id {
+  canonical_id: 1607
+  carrier_name: "Telecom Malagasy Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "64604"
+  }
+}
+carrier_id {
+  canonical_id: 1608
+  carrier_name: "Cosmofon"
+  carrier_attribute {
+    mccmnc_tuple: "29402"
+  }
+}
+carrier_id {
+  canonical_id: 1609
+  carrier_name: "Nov Operator"
+  carrier_attribute {
+    mccmnc_tuple: "29403"
+  }
+}
+carrier_id {
+  canonical_id: 1610
+  carrier_name: "Malitel"
+  carrier_attribute {
+    mccmnc_tuple: "61001"
+  }
+}
+carrier_id {
+  canonical_id: 1611
+  carrier_name: "Myanmar Post and Telecommunication"
+  carrier_attribute {
+    mccmnc_tuple: "41401"
+  }
+}
+carrier_id {
+  canonical_id: 1612
+  carrier_name: "Mobicom"
+  carrier_attribute {
+    mccmnc_tuple: "42899"
+  }
+}
+carrier_id {
+  canonical_id: 1613
+  carrier_name: "Smartone Mobile Communications (Macao) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "45500"
+  }
+}
+carrier_id {
+  canonical_id: 1614
+  carrier_name: "CTM GSM"
+  carrier_attribute {
+    mccmnc_tuple: "45501"
+  }
+}
+carrier_id {
+  canonical_id: 1615
+  carrier_name: "Hutchison Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "45503"
+  }
+}
+carrier_id {
+  canonical_id: 1616
+  carrier_name: "Mattel S.A."
+  carrier_attribute {
+    mccmnc_tuple: "60901"
+  }
+}
+carrier_id {
+  canonical_id: 1617
+  carrier_name: "Chinguitel S.A."
+  carrier_attribute {
+    mccmnc_tuple: "60902"
+  }
+}
+carrier_id {
+  canonical_id: 1618
+  carrier_name: "Mauritel Mobiles"
+  carrier_attribute {
+    mccmnc_tuple: "60910"
+  }
+}
+carrier_id {
+  canonical_id: 1619
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "27801"
+  }
+}
+carrier_id {
+  canonical_id: 1620
+  carrier_name: "go mobile"
+  carrier_attribute {
+    mccmnc_tuple: "27821"
+  }
+}
+carrier_id {
+  canonical_id: 1621
+  carrier_name: "Orange Mauritius"
+  carrier_attribute {
+    mccmnc_tuple: "61701"
+  }
+}
+carrier_id {
+  canonical_id: 1622
+  carrier_name: "Mahanagar Telephone (Mauritius) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "61702"
+  }
+}
+carrier_id {
+  canonical_id: 1623
+  carrier_name: "Emtel"
+  carrier_attribute {
+    mccmnc_tuple: "61710"
+  }
+}
+carrier_id {
+  canonical_id: 1624
+  carrier_name: "DhiMobile"
+  carrier_attribute {
+    mccmnc_tuple: "47201"
+  }
+}
+carrier_id {
+  canonical_id: 1625
+  carrier_name: "Telekom Network Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "65001"
+  }
+}
+carrier_id {
+  canonical_id: 1626
+  carrier_name: "Celtel ltd."
+  carrier_attribute {
+    mccmnc_tuple: "65010"
+  }
+}
+carrier_id {
+  canonical_id: 1627
+  carrier_name: "Art900"
+  carrier_attribute {
+    mccmnc_tuple: "50200"
+  }
+}
+carrier_id {
+  canonical_id: 1628
+  carrier_name: "Maxis/Hotlink/Ookyo"
+  carrier_attribute {
+    mccmnc_tuple: "50212"
+  }
+}
+carrier_id {
+  canonical_id: 1630
+  carrier_name: "Digi"
+  carrier_attribute {
+    mccmnc_tuple: "50210"
+    mccmnc_tuple: "50216"
+  }
+}
+carrier_id {
+  canonical_id: 1631
+  carrier_name: "TimeCel"
+  carrier_attribute {
+    mccmnc_tuple: "50217"
+  }
+}
+carrier_id {
+  canonical_id: 1632
+  carrier_name: "U Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "50218"
+  }
+}
+carrier_id {
+  canonical_id: 1633
+  carrier_name: "Celcom"
+  carrier_attribute {
+    mccmnc_tuple: "50213"
+    mccmnc_tuple: "50219"
+  }
+}
+carrier_id {
+  canonical_id: 1634
+  carrier_name: "T.D.M. GSM"
+  carrier_attribute {
+    mccmnc_tuple: "64301"
+  }
+}
+carrier_id {
+  canonical_id: 1635
+  carrier_name: "Vodacom"
+  carrier_attribute {
+    mccmnc_tuple: "64304"
+  }
+}
+carrier_id {
+  canonical_id: 1636
+  carrier_name: "Sahel.Com"
+  carrier_attribute {
+    mccmnc_tuple: "61401"
+  }
+}
+carrier_id {
+  canonical_id: 1637
+  carrier_name: "Telecel"
+  carrier_attribute {
+    mccmnc_tuple: "61403"
+  }
+}
+carrier_id {
+  canonical_id: 1638
+  carrier_name: "Econet Wireless Nigeria Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "62120"
+  }
+}
+carrier_id {
+  canonical_id: 1639
+  carrier_name: "MTN Nigeria Communications"
+  carrier_attribute {
+    mccmnc_tuple: "62130"
+  }
+}
+carrier_id {
+  canonical_id: 1640
+  carrier_name: "Nigeria Telecommunications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "62140"
+  }
+}
+carrier_id {
+  canonical_id: 1641
+  carrier_name: "Claro NI"
+  carrier_attribute {
+    mccmnc_tuple: "71021"
+  }
+}
+carrier_id {
+  canonical_id: 1642
+  carrier_name: "Servicios de Comunicaciones, S.A. (SERCOM)"
+  carrier_attribute {
+    mccmnc_tuple: "71073"
+  }
+}
+carrier_id {
+  canonical_id: 1643
+  carrier_name: "Tele2"
+  carrier_attribute {
+    mccmnc_tuple: "20402"
+  }
+}
+carrier_id {
+  canonical_id: 1644
+  carrier_name: "KPN/Telfort"
+  carrier_attribute {
+    mccmnc_tuple: "20408"
+    mccmnc_tuple: "20412"
+  }
+}
+carrier_id {
+  canonical_id: 1646
+  carrier_name: "NS Railinfrabeheer B.V."
+  carrier_attribute {
+    mccmnc_tuple: "20421"
+  }
+}
+carrier_id {
+  canonical_id: 1647
+  carrier_name: "Claro PE"
+  carrier_attribute {
+    mccmnc_tuple: "71610"
+  }
+}
+carrier_id {
+  canonical_id: 1648
+  carrier_name: "Tikiphone"
+  carrier_attribute {
+    mccmnc_tuple: "54720"
+  }
+}
+carrier_id {
+  canonical_id: 1649
+  carrier_name: "Bmobile"
+  carrier_attribute {
+    mccmnc_tuple: "53701"
+  }
+}
+carrier_id {
+  canonical_id: 1650
+  carrier_name: "Greencom"
+  carrier_attribute {
+    mccmnc_tuple: "53702"
+  }
+}
+carrier_id {
+  canonical_id: 1651
+  carrier_name: "Digicel Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "53703"
+  }
+}
+carrier_id {
+  canonical_id: 1652
+  carrier_name: "Islacom"
+  carrier_attribute {
+    mccmnc_tuple: "51501"
+  }
+}
+carrier_id {
+  canonical_id: 1653
+  carrier_name: "Globe Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "51502"
+  }
+}
+carrier_id {
+  canonical_id: 1654
+  carrier_name: "Smart Communications"
+  carrier_attribute {
+    mccmnc_tuple: "51503"
+  }
+}
+carrier_id {
+  canonical_id: 1655
+  carrier_name: "Sun"
+  carrier_attribute {
+    mccmnc_tuple: "51505"
+  }
+}
+carrier_id {
+  canonical_id: 1656
+  carrier_name: "Jazz"
+  carrier_attribute {
+    mccmnc_tuple: "41001"
+  }
+}
+carrier_id {
+  canonical_id: 1657
+  carrier_name: "PAK Telecom Mobile Ltd. (UFONE)"
+  carrier_attribute {
+    mccmnc_tuple: "41003"
+  }
+}
+carrier_id {
+  canonical_id: 1658
+  carrier_name: "Plus"
+  carrier_attribute {
+    mccmnc_tuple: "26001"
+  }
+}
+carrier_id {
+  canonical_id: 1659
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "26003"
+  }
+}
+carrier_id {
+  canonical_id: 1660
+  carrier_name: "Tele2 Polska (Tele2 Polska Sp. Z.o.o.)"
+  carrier_attribute {
+    mccmnc_tuple: "26004"
+  }
+}
+carrier_id {
+  canonical_id: 1661
+  carrier_name: "IDEA (UMTS)/PTK Centertel sp. Z.o.o."
+  carrier_attribute {
+    mccmnc_tuple: "26005"
+  }
+}
+carrier_id {
+  canonical_id: 1662
+  carrier_name: "PLAY"
+  carrier_attribute {
+    mccmnc_tuple: "26006"
+  }
+}
+carrier_id {
+  canonical_id: 1663
+  carrier_name: "Premium internet"
+  carrier_attribute {
+    mccmnc_tuple: "26007"
+  }
+}
+carrier_id {
+  canonical_id: 1664
+  carrier_name: "E-Telko"
+  carrier_attribute {
+    mccmnc_tuple: "26008"
+  }
+}
+carrier_id {
+  canonical_id: 1665
+  carrier_name: "Telekomunikacja Kolejowa (GSM-R)"
+  carrier_attribute {
+    mccmnc_tuple: "26009"
+  }
+}
+carrier_id {
+  canonical_id: 1666
+  carrier_name: "Telefony Opalenickie"
+  carrier_attribute {
+    mccmnc_tuple: "26010"
+  }
+}
+carrier_id {
+  canonical_id: 1667
+  carrier_name: "St. Pierre-et-Miquelon Télécom"
+  carrier_attribute {
+    mccmnc_tuple: "30801"
+  }
+}
+carrier_id {
+  canonical_id: 1668
+  carrier_name: "Optimus - Telecomunicações, S.A."
+  carrier_attribute {
+    mccmnc_tuple: "26803"
+  }
+}
+carrier_id {
+  canonical_id: 1669
+  carrier_name: "Oniway - Inforcomunicaçôes, S.A."
+  carrier_attribute {
+    mccmnc_tuple: "26805"
+  }
+}
+carrier_id {
+  canonical_id: 1670
+  carrier_name: "TMN - Telecomunicações Móveis Nacionais, S.A."
+  carrier_attribute {
+    mccmnc_tuple: "26806"
+  }
+}
+carrier_id {
+  canonical_id: 1671
+  carrier_name: "Palau National Communications Corp. (a.k.a. PNCC)"
+  carrier_attribute {
+    mccmnc_tuple: "55201"
+  }
+}
+carrier_id {
+  canonical_id: 1672
+  carrier_name: "Hola Paraguay S.A."
+  carrier_attribute {
+    mccmnc_tuple: "74401"
+    mccmnc_tuple: "74406"
+  }
+}
+carrier_id {
+  canonical_id: 1673
+  carrier_name: "Claro PY"
+  carrier_attribute {
+    mccmnc_tuple: "74402"
+  }
+}
+carrier_id {
+  canonical_id: 1674
+  carrier_name: "Compañia Privada de Comunicaciones S.A."
+  carrier_attribute {
+    mccmnc_tuple: "74403"
+  }
+}
+carrier_id {
+  canonical_id: 1675
+  carrier_name: "Ooredoo"
+  carrier_attribute {
+    mccmnc_tuple: "42701"
+  }
+}
+carrier_id {
+  canonical_id: 1676
+  carrier_name: "Orange La Réunion"
+  carrier_attribute {
+    mccmnc_tuple: "64700"
+  }
+}
+carrier_id {
+  canonical_id: 1677
+  carrier_name: "Outremer Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "64702"
+  }
+}
+carrier_id {
+  canonical_id: 1678
+  carrier_name: "МТС"
+  carrier_attribute {
+    mccmnc_tuple: "25001"
+  }
+}
+carrier_id {
+  canonical_id: 1679
+  carrier_name: "Printelefone"
+  carrier_attribute {
+    mccmnc_tuple: "25092"
+  }
+}
+carrier_id {
+  canonical_id: 1680
+  carrier_name: "Telecom XXI"
+  carrier_attribute {
+    mccmnc_tuple: "25093"
+  }
+}
+carrier_id {
+  canonical_id: 1681
+  carrier_name: "Билайн"
+  carrier_attribute {
+    mccmnc_tuple: "25099"
+  }
+}
+carrier_id {
+  canonical_id: 1682
+  carrier_name: "MTN Rwandacell"
+  carrier_attribute {
+    mccmnc_tuple: "63510"
+  }
+}
+carrier_id {
+  canonical_id: 1683
+  carrier_name: "STC"
+  carrier_attribute {
+    mccmnc_tuple: "42001"
+  }
+}
+carrier_id {
+  canonical_id: 1684
+  carrier_name: "Mobily"
+  carrier_attribute {
+    mccmnc_tuple: "42003"
+  }
+}
+carrier_id {
+  canonical_id: 1685
+  carrier_name: "Cable & Wireless (Seychelles) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "63301"
+  }
+}
+carrier_id {
+  canonical_id: 1686
+  carrier_name: "Mediatech International Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "63302"
+  }
+}
+carrier_id {
+  canonical_id: 1687
+  carrier_name: "Telecom (Seychelles) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "63310"
+  }
+}
+carrier_id {
+  canonical_id: 1688
+  carrier_name: "SD Mobitel"
+  carrier_attribute {
+    mccmnc_tuple: "63401"
+  }
+}
+carrier_id {
+  canonical_id: 1689
+  carrier_name: "Areeba-Sudan"
+  carrier_attribute {
+    mccmnc_tuple: "63402"
+  }
+}
+carrier_id {
+  canonical_id: 1690
+  carrier_name: "Telia Sonera AB"
+  carrier_attribute {
+    mccmnc_tuple: "24001"
+  }
+}
+carrier_id {
+  canonical_id: 1691
+  carrier_name: "3 (Hi3G Access AB)"
+  carrier_attribute {
+    mccmnc_tuple: "24002"
+  }
+}
+carrier_id {
+  canonical_id: 1692
+  carrier_name: "Nordisk Mobiltelefon AS"
+  carrier_attribute {
+    mccmnc_tuple: "24003"
+  }
+}
+carrier_id {
+  canonical_id: 1693
+  carrier_name: "3G Infrastructure Services AB"
+  carrier_attribute {
+    mccmnc_tuple: "24004"
+  }
+}
+carrier_id {
+  canonical_id: 1694
+  carrier_name: "Svenska UMTS-Nät AB"
+  carrier_attribute {
+    mccmnc_tuple: "24005"
+  }
+}
+carrier_id {
+  canonical_id: 1695
+  carrier_name: "Telenor Sverige AB"
+  carrier_attribute {
+    mccmnc_tuple: "24006"
+    mccmnc_tuple: "24008"
+  }
+}
+carrier_id {
+  canonical_id: 1696
+  carrier_name: "Tele2/Comviq Sverige"
+  carrier_attribute {
+    mccmnc_tuple: "24007"
+  }
+}
+carrier_id {
+  canonical_id: 1697
+  carrier_name: "Spring Mobil AB"
+  carrier_attribute {
+    mccmnc_tuple: "24010"
+  }
+}
+carrier_id {
+  canonical_id: 1698
+  carrier_name: "Linholmen Science Park AB"
+  carrier_attribute {
+    mccmnc_tuple: "24011"
+  }
+}
+carrier_id {
+  canonical_id: 1699
+  carrier_name: "Barablu Mobile Scandinavia Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "24012"
+  }
+}
+carrier_id {
+  canonical_id: 1700
+  carrier_name: "Ventelo Sverige AB"
+  carrier_attribute {
+    mccmnc_tuple: "24013"
+  }
+}
+carrier_id {
+  canonical_id: 1701
+  carrier_name: "TDC Mobil A/S"
+  carrier_attribute {
+    mccmnc_tuple: "24014"
+  }
+}
+carrier_id {
+  canonical_id: 1702
+  carrier_name: "Wireless Maingate Nordic AB"
+  carrier_attribute {
+    mccmnc_tuple: "24015"
+  }
+}
+carrier_id {
+  canonical_id: 1703
+  carrier_name: "42IT AB"
+  carrier_attribute {
+    mccmnc_tuple: "24016"
+  }
+}
+carrier_id {
+  canonical_id: 1704
+  carrier_name: "Wireless Maingate Message Services AB"
+  carrier_attribute {
+    mccmnc_tuple: "24020"
+  }
+}
+carrier_id {
+  canonical_id: 1705
+  carrier_name: "Banverket"
+  carrier_attribute {
+    mccmnc_tuple: "24021"
+  }
+}
+carrier_id {
+  canonical_id: 1706
+  carrier_name: "M1"
+  carrier_attribute {
+    mccmnc_tuple: "52503"
+  }
+}
+carrier_id {
+  canonical_id: 1707
+  carrier_name: "StarHub"
+  carrier_attribute {
+    mccmnc_tuple: "52505"
+  }
+}
+carrier_id {
+  canonical_id: 1708
+  carrier_name: "Digital Trunked Radio Network"
+  carrier_attribute {
+    mccmnc_tuple: "52512"
+  }
+}
+carrier_id {
+  canonical_id: 1709
+  carrier_name: "SI Mobil"
+  carrier_attribute {
+    mccmnc_tuple: "29340"
+  }
+}
+carrier_id {
+  canonical_id: 1710
+  carrier_name: "Telekom Slovenije"
+  carrier_attribute {
+    mccmnc_tuple: "29341"
+  }
+}
+carrier_id {
+  canonical_id: 1711
+  carrier_name: "T-2 d.o.o."
+  carrier_attribute {
+    mccmnc_tuple: "29364"
+  }
+}
+carrier_id {
+  canonical_id: 1712
+  carrier_name: "Tusmobil d.o.o."
+  carrier_attribute {
+    mccmnc_tuple: "29370"
+  }
+}
+carrier_id {
+  canonical_id: 1713
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "23101"
+  }
+}
+carrier_id {
+  canonical_id: 1714
+  carrier_name: "Eurotel, UMTS"
+  carrier_attribute {
+    mccmnc_tuple: "23104"
+  }
+}
+carrier_id {
+  canonical_id: 1715
+  carrier_name: "Orange, UMTS"
+  carrier_attribute {
+    mccmnc_tuple: "23105"
+  }
+}
+carrier_id {
+  canonical_id: 1716
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "61901"
+  }
+}
+carrier_id {
+  canonical_id: 1717
+  carrier_name: "Millicom"
+  carrier_attribute {
+    mccmnc_tuple: "61902"
+  }
+}
+carrier_id {
+  canonical_id: 1718
+  carrier_name: "Africell"
+  carrier_attribute {
+    mccmnc_tuple: "61903"
+  }
+}
+carrier_id {
+  canonical_id: 1719
+  carrier_name: "Dtatel (SL) Ltd CDMA"
+  carrier_attribute {
+    mccmnc_tuple: "61950"
+  }
+}
+carrier_id {
+  canonical_id: 1720
+  carrier_name: "SMT - San  Marino Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "29201"
+  }
+}
+carrier_id {
+  canonical_id: 1721
+  carrier_name: "Orange Senegal"
+  carrier_attribute {
+    mccmnc_tuple: "60801"
+  }
+}
+carrier_id {
+  canonical_id: 1722
+  carrier_name: "Sentel GSM"
+  carrier_attribute {
+    mccmnc_tuple: "60802"
+  }
+}
+carrier_id {
+  canonical_id: 1723
+  carrier_name: "ACT Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "52015"
+  }
+}
+carrier_id {
+  canonical_id: 1724
+  carrier_name: "JC Somoncom"
+  carrier_attribute {
+    mccmnc_tuple: "43601"
+  }
+}
+carrier_id {
+  canonical_id: 1725
+  carrier_name: "CJSC Indigo Tajikistan"
+  carrier_attribute {
+    mccmnc_tuple: "43602"
+  }
+}
+carrier_id {
+  canonical_id: 1726
+  carrier_name: "TT mobile"
+  carrier_attribute {
+    mccmnc_tuple: "43603"
+  }
+}
+carrier_id {
+  canonical_id: 1727
+  carrier_name: "Josa Babilon-T"
+  carrier_attribute {
+    mccmnc_tuple: "43604"
+  }
+}
+carrier_id {
+  canonical_id: 1728
+  carrier_name: "CTJTHSC Tajik-tel"
+  carrier_attribute {
+    mccmnc_tuple: "43605"
+  }
+}
+carrier_id {
+  canonical_id: 1729
+  carrier_name: "Barash Communication Technologies (BCTI)"
+  carrier_attribute {
+    mccmnc_tuple: "43801"
+  }
+}
+carrier_id {
+  canonical_id: 1730
+  carrier_name: "TM-Cell"
+  carrier_attribute {
+    mccmnc_tuple: "43802"
+  }
+}
+carrier_id {
+  canonical_id: 1731
+  carrier_name: "Tunisie Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "60502"
+  }
+}
+carrier_id {
+  canonical_id: 1732
+  carrier_name: "Ooredoo Tunisia"
+  carrier_attribute {
+    mccmnc_tuple: "60503"
+  }
+}
+carrier_id {
+  canonical_id: 1733
+  carrier_name: "Tonga Communications Corporation"
+  carrier_attribute {
+    mccmnc_tuple: "53901"
+  }
+}
+carrier_id {
+  canonical_id: 1734
+  carrier_name: "Shoreline Communication"
+  carrier_attribute {
+    mccmnc_tuple: "53943"
+  }
+}
+carrier_id {
+  canonical_id: 1735
+  carrier_name: "Paycell | Turkcell"
+  carrier_attribute {
+    mccmnc_tuple: "28601"
+  }
+}
+carrier_id {
+  canonical_id: 1736
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "28602"
+  }
+}
+carrier_id {
+  canonical_id: 1737
+  carrier_name: "Türk Telekom"
+  carrier_attribute {
+    mccmnc_tuple: "28603"
+    mccmnc_tuple: "28604"
+  }
+}
+carrier_id {
+  canonical_id: 1739
+  carrier_name: "TSTT Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "37412"
+  }
+}
+carrier_id {
+  canonical_id: 1740
+  carrier_name: "Digicel Trinidad and Tobago Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "374130"
+  }
+}
+carrier_id {
+  canonical_id: 1741
+  carrier_name: "LaqTel Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "374140"
+  }
+}
+carrier_id {
+  canonical_id: 1742
+  carrier_name: "TIGO"
+  carrier_attribute {
+    mccmnc_tuple: "64002"
+  }
+}
+carrier_id {
+  canonical_id: 1743
+  carrier_name: "Zantel"
+  carrier_attribute {
+    mccmnc_tuple: "64003"
+  }
+}
+carrier_id {
+  canonical_id: 1744
+  carrier_name: "Vodacom (T) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "64004"
+  }
+}
+carrier_id {
+  canonical_id: 1745
+  carrier_name: "Celtel (T) Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "64005"
+  }
+}
+carrier_id {
+  canonical_id: 1746
+  carrier_name: "Ukrainian Mobile Communication, UMC"
+  carrier_attribute {
+    mccmnc_tuple: "25501"
+  }
+}
+carrier_id {
+  canonical_id: 1747
+  carrier_name: "Kyivstar GSM"
+  carrier_attribute {
+    mccmnc_tuple: "25503"
+  }
+}
+carrier_id {
+  canonical_id: 1748
+  carrier_name: "International Telecommunications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "25504"
+  }
+}
+carrier_id {
+  canonical_id: 1749
+  carrier_name: "Golden Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "25505"
+  }
+}
+carrier_id {
+  canonical_id: 1750
+  carrier_name: "Astelit"
+  carrier_attribute {
+    mccmnc_tuple: "25506"
+  }
+}
+carrier_id {
+  canonical_id: 1751
+  carrier_name: "Ukrtelecom"
+  carrier_attribute {
+    mccmnc_tuple: "25507"
+  }
+}
+carrier_id {
+  canonical_id: 1752
+  carrier_name: "CJSC - Telesystems of Ukraine"
+  carrier_attribute {
+    mccmnc_tuple: "25521"
+  }
+}
+carrier_id {
+  canonical_id: 1753
+  carrier_name: "Celtel Uganda"
+  carrier_attribute {
+    mccmnc_tuple: "64101"
+  }
+}
+carrier_id {
+  canonical_id: 1754
+  carrier_name: "MTN Uganda Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "64110"
+  }
+}
+carrier_id {
+  canonical_id: 1755
+  carrier_name: "Uganda Telecom Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "64111"
+  }
+}
+carrier_id {
+  canonical_id: 1756
+  carrier_name: "House of Integrated Technology and Systems Uganda Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "64114"
+  }
+}
+carrier_id {
+  canonical_id: 1757
+  carrier_name: "Warid Telecom Uganda Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "64122"
+  }
+}
+carrier_id {
+  canonical_id: 1758
+  carrier_name: "ICO Global Communications"
+  carrier_attribute {
+    mccmnc_tuple: "90101"
+  }
+}
+carrier_id {
+  canonical_id: 1759
+  carrier_name: "Sense Communications International AS"
+  carrier_attribute {
+    mccmnc_tuple: "90102"
+  }
+}
+carrier_id {
+  canonical_id: 1760
+  carrier_name: "Ellipso"
+  carrier_attribute {
+    mccmnc_tuple: "90107"
+  }
+}
+carrier_id {
+  canonical_id: 1761
+  carrier_name: "Tele1 Europe"
+  carrier_attribute {
+    mccmnc_tuple: "90109"
+  }
+}
+carrier_id {
+  canonical_id: 1762
+  carrier_name: "Asia Cellular Satellite (AceS)"
+  carrier_attribute {
+    mccmnc_tuple: "90110"
+  }
+}
+carrier_id {
+  canonical_id: 1763
+  carrier_name: "Inmarsat Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "90111"
+  }
+}
+carrier_id {
+  canonical_id: 1764
+  carrier_name: "Maritime Communications Partner AS (MCP network)"
+  carrier_attribute {
+    mccmnc_tuple: "90112"
+  }
+}
+carrier_id {
+  canonical_id: 1765
+  carrier_name: "Global Networks, Inc."
+  carrier_attribute {
+    mccmnc_tuple: "90113"
+  }
+}
+carrier_id {
+  canonical_id: 1766
+  carrier_name: "Telenor GSM - services in aircraft"
+  carrier_attribute {
+    mccmnc_tuple: "90114"
+  }
+}
+carrier_id {
+  canonical_id: 1767
+  carrier_name: "SITA GSM services in aircraft (On Air)"
+  carrier_attribute {
+    mccmnc_tuple: "90115"
+  }
+}
+carrier_id {
+  canonical_id: 1768
+  carrier_name: "Jasper Systems, Inc."
+  carrier_attribute {
+    mccmnc_tuple: "90116"
+  }
+}
+carrier_id {
+  canonical_id: 1769
+  carrier_name: "Jersey Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "90117"
+  }
+}
+carrier_id {
+  canonical_id: 1770
+  carrier_name: "AT&T Mobility (Wireless Maritime Services)"
+  carrier_attribute {
+    mccmnc_tuple: "90118"
+  }
+}
+carrier_id {
+  canonical_id: 1771
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "90119"
+  }
+}
+carrier_id {
+  canonical_id: 1772
+  carrier_name: "Intermatica"
+  carrier_attribute {
+    mccmnc_tuple: "90120"
+  }
+}
+carrier_id {
+  canonical_id: 1773
+  carrier_name: "Seanet Maritime Communications"
+  carrier_attribute {
+    mccmnc_tuple: "90121"
+  }
+}
+carrier_id {
+  canonical_id: 1774
+  carrier_name: "Denver Consultants Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "90122"
+  }
+}
+carrier_id {
+  canonical_id: 1775
+  carrier_name: "Telecommunications for Disaster Relief (TDR) (OCHA)"
+  carrier_attribute {
+    mccmnc_tuple: "90188"
+  }
+}
+carrier_id {
+  canonical_id: 1776
+  carrier_name: "MCI"
+  carrier_attribute {
+    mccmnc_tuple: "310010"
+  }
+}
+carrier_id {
+  canonical_id: 1778
+  carrier_name: "Mobile Tel Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310013"
+  }
+}
+carrier_id {
+  canonical_id: 1779
+  carrier_name: "Cricket Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "310016"
+    mccmnc_tuple: "310090"
+  }
+}
+carrier_id {
+  canonical_id: 1780
+  carrier_name: "North Sight Communications Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310017"
+  }
+}
+carrier_id {
+  canonical_id: 1781
+  carrier_name: "Union Telephone Company"
+  carrier_attribute {
+    mccmnc_tuple: "310020"
+  }
+}
+carrier_id {
+  canonical_id: 1783
+  carrier_name: "Nevada Wireless LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310034"
+  }
+}
+carrier_id {
+  canonical_id: 1784
+  carrier_name: "MTA Communications dba MTA Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "310040"
+  }
+}
+carrier_id {
+  canonical_id: 1785
+  carrier_name: "ACS Wireless Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310050"
+  }
+}
+carrier_id {
+  canonical_id: 1787
+  carrier_name: "Pacific Telecom Inc"
+  carrier_attribute {
+    mccmnc_tuple: "310110"
+  }
+}
+carrier_id {
+  canonical_id: 1788
+  carrier_name: "Sprint"
+  carrier_attribute {
+    mccmnc_tuple: "310120"
+    mccmnc_tuple: "312530"
+  }
+}
+carrier_id {
+  canonical_id: 1789
+  carrier_name: "Carolina West Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "310130"
+  }
+}
+carrier_id {
+  canonical_id: 1790
+  carrier_name: "GTA Wireless LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310140"
+  }
+}
+carrier_id {
+  canonical_id: 1792
+  carrier_name: "West Central Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "310180"
+  }
+}
+carrier_id {
+  canonical_id: 1793
+  carrier_name: "Alaska Wireless Communications LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310190"
+  }
+}
+carrier_id {
+  canonical_id: 1795
+  carrier_name: "Nep Cellcorp Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310290"
+  }
+}
+carrier_id {
+  canonical_id: 1796
+  carrier_name: "Smith Bagley Inc, dba Cellular One"
+  carrier_attribute {
+    mccmnc_tuple: "310320"
+  }
+}
+carrier_id {
+  canonical_id: 1797
+  carrier_name: "AN Subsidiary LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310330"
+  }
+}
+carrier_id {
+  canonical_id: 1798
+  carrier_name: "Wireless Solutions International"
+  carrier_attribute {
+    mccmnc_tuple: "310550"
+  }
+}
+carrier_id {
+  canonical_id: 1800
+  carrier_name: "MTPCS LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310570"
+  }
+}
+carrier_id {
+  canonical_id: 1802
+  carrier_name: "New Cell Inc. dba Cellcom"
+  carrier_attribute {
+    mccmnc_tuple: "310600"
+    mccmnc_tuple: "31060"
+  }
+}
+carrier_id {
+  canonical_id: 1803
+  carrier_name: "Elkhart Telephone Co. Inc. dba Epic Touch Co."
+  carrier_attribute {
+    mccmnc_tuple: "310610"
+  }
+}
+carrier_id {
+  canonical_id: 1804
+  carrier_name: "Coleman County Telecommunications Inc. (Trans Texas PCS)"
+  carrier_attribute {
+    mccmnc_tuple: "310620"
+  }
+}
+carrier_id {
+  canonical_id: 1806
+  carrier_name: "Jasper Wireless Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310650"
+  }
+}
+carrier_id {
+  canonical_id: 1807
+  carrier_name: "AT&T Mobility Vanguard Services"
+  carrier_attribute {
+    mccmnc_tuple: "310670"
+  }
+}
+carrier_id {
+  canonical_id: 1808
+  carrier_name: "Conestoga Wireless Company"
+  carrier_attribute {
+    mccmnc_tuple: "310690"
+  }
+}
+carrier_id {
+  canonical_id: 1809
+  carrier_name: "Cross Valiant Cellular Partnership"
+  carrier_attribute {
+    mccmnc_tuple: "310700"
+  }
+}
+carrier_id {
+  canonical_id: 1810
+  carrier_name: "Arctic Slopo Telephone Association Cooperative"
+  carrier_attribute {
+    mccmnc_tuple: "310710"
+  }
+}
+carrier_id {
+  canonical_id: 1811
+  carrier_name: "Wireless Solutions International Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310720"
+  }
+}
+carrier_id {
+  canonical_id: 1812
+  carrier_name: "Sea Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "310730"
+  }
+}
+carrier_id {
+  canonical_id: 1813
+  carrier_name: "East Kentucky Network LLC dba Appalachian Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "310750"
+  }
+}
+carrier_id {
+  canonical_id: 1814
+  carrier_name: "Panhandle Telecommunications Systems Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310760"
+  }
+}
+carrier_id {
+  canonical_id: 1815
+  carrier_name: "Iowa Wireless Services LLC dba I Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "310770"
+  }
+}
+carrier_id {
+  canonical_id: 1816
+  carrier_name: "Connect Net Inc"
+  carrier_attribute {
+    mccmnc_tuple: "310780"
+  }
+}
+carrier_id {
+  canonical_id: 1817
+  carrier_name: "PinPoint Communications Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310790"
+  }
+}
+carrier_id {
+  canonical_id: 1818
+  carrier_name: "Brazos Cellular Communications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "310810"
+  }
+}
+carrier_id {
+  canonical_id: 1819
+  carrier_name: "South Canaan Cellular Communications Co. LP"
+  carrier_attribute {
+    mccmnc_tuple: "310820"
+  }
+}
+carrier_id {
+  canonical_id: 1820
+  carrier_name: "Caprock Cellular Ltd. Partnership"
+  carrier_attribute {
+    mccmnc_tuple: "310830"
+  }
+}
+carrier_id {
+  canonical_id: 1821
+  carrier_name: "Edge Mobile LLC"
+  carrier_attribute {
+    mccmnc_tuple: "310840"
+  }
+}
+carrier_id {
+  canonical_id: 1822
+  carrier_name: "Aeris Communications, Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310850"
+  }
+}
+carrier_id {
+  canonical_id: 1823
+  carrier_name: "TX RSA 15B2, LP dba Five Star Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "310860"
+  }
+}
+carrier_id {
+  canonical_id: 1824
+  carrier_name: "Kaplan Telephone Company Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310870"
+  }
+}
+carrier_id {
+  canonical_id: 1825
+  carrier_name: "Advantage Cellular Systems, Inc."
+  carrier_attribute {
+    mccmnc_tuple: "310880"
+  }
+}
+carrier_id {
+  canonical_id: 1826
+  carrier_name: "Rural Cellular Corporation"
+  carrier_attribute {
+    mccmnc_tuple: "310890"
+  }
+}
+carrier_id {
+  canonical_id: 1827
+  carrier_name: "Taylor Telecommunications Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "310900"
+  }
+}
+carrier_id {
+  canonical_id: 1828
+  carrier_name: "Southern IL RSA Partnership dba First Cellular of Southern Illinois"
+  carrier_attribute {
+    mccmnc_tuple: "310910"
+  }
+}
+carrier_id {
+  canonical_id: 1829
+  carrier_name: "Get Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "310920"
+  }
+}
+carrier_id {
+  canonical_id: 1830
+  carrier_name: "Copper Valley Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "310930"
+  }
+}
+carrier_id {
+  canonical_id: 1831
+  carrier_name: "PetroCom LLC"
+  carrier_attribute {
+    mccmnc_tuple: "311170"
+  }
+}
+carrier_id {
+  canonical_id: 1833
+  carrier_name: "Cellular Properties Inc."
+  carrier_attribute {
+    mccmnc_tuple: "311190"
+  }
+}
+carrier_id {
+  canonical_id: 1834
+  carrier_name: "ARINC"
+  carrier_attribute {
+    mccmnc_tuple: "311200"
+  }
+}
+carrier_id {
+  canonical_id: 1835
+  carrier_name: "Farmers Cellular Telephone"
+  carrier_attribute {
+    mccmnc_tuple: "311210"
+  }
+}
+carrier_id {
+  canonical_id: 1836
+  carrier_name: "Cellular South Inc."
+  carrier_attribute {
+    mccmnc_tuple: "311230"
+    mccmnc_tuple: "310023"
+  }
+}
+carrier_id {
+  canonical_id: 1837
+  carrier_name: "Cordova Wireless Communications Inc"
+  carrier_attribute {
+    mccmnc_tuple: "311240"
+  }
+}
+carrier_id {
+  canonical_id: 1838
+  carrier_name: "SLO Cellular Inc. dba CellularOne of San Luis Obispo"
+  carrier_attribute {
+    mccmnc_tuple: "311260"
+  }
+}
+carrier_id {
+  canonical_id: 1839
+  carrier_name: "Verizon Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "20404"
+    gid1: "BAE0000000000000"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "310004"
+    mccmnc_tuple: "310012"
+    mccmnc_tuple: "311280"
+    mccmnc_tuple: "311281"
+    mccmnc_tuple: "311282"
+    mccmnc_tuple: "311283"
+    mccmnc_tuple: "311284"
+    mccmnc_tuple: "311285"
+    mccmnc_tuple: "311286"
+    mccmnc_tuple: "311287"
+    mccmnc_tuple: "311288"
+    mccmnc_tuple: "311289"
+    mccmnc_tuple: "311480"
+    mccmnc_tuple: "311481"
+    mccmnc_tuple: "311482"
+    mccmnc_tuple: "311483"
+    mccmnc_tuple: "311484"
+    mccmnc_tuple: "311485"
+    mccmnc_tuple: "311486"
+    mccmnc_tuple: "311487"
+    mccmnc_tuple: "311488"
+    mccmnc_tuple: "311489"
+  }
+}
+carrier_id {
+  canonical_id: 1840
+  carrier_name: "Pinpoint Wireless Inc."
+  carrier_attribute {
+    mccmnc_tuple: "311290"
+  }
+}
+carrier_id {
+  canonical_id: 1841
+  carrier_name: "Rutal Cellular Corporation"
+  carrier_attribute {
+    mccmnc_tuple: "311300"
+  }
+}
+carrier_id {
+  canonical_id: 1842
+  carrier_name: "Leaco Rural Telephone Company Inc"
+  carrier_attribute {
+    mccmnc_tuple: "311310"
+  }
+}
+carrier_id {
+  canonical_id: 1843
+  carrier_name: "GCI Communications Corp."
+  carrier_attribute {
+    mccmnc_tuple: "311370"
+  }
+}
+carrier_id {
+  canonical_id: 1844
+  carrier_name: "GreenFly LLC"
+  carrier_attribute {
+    mccmnc_tuple: "311380"
+  }
+}
+carrier_id {
+  canonical_id: 1845
+  carrier_name: "Midwest Wireless Holdings LLC"
+  carrier_attribute {
+    mccmnc_tuple: "311390"
+  }
+}
+carrier_id {
+  canonical_id: 1846
+  carrier_name: "Iowa RSA No.2 Ltd Partnership"
+  carrier_attribute {
+    mccmnc_tuple: "311410"
+  }
+}
+carrier_id {
+  canonical_id: 1847
+  carrier_name: "Northwest Missouri Cellular Limited Partnership"
+  carrier_attribute {
+    mccmnc_tuple: "311420"
+  }
+}
+carrier_id {
+  canonical_id: 1848
+  carrier_name: "RSA 1 Limited Partnership dba Cellular 29 Plus"
+  carrier_attribute {
+    mccmnc_tuple: "311430"
+  }
+}
+carrier_id {
+  canonical_id: 1849
+  carrier_name: "Bluegrass Cellular LLC"
+  carrier_attribute {
+    mccmnc_tuple: "311440"
+  }
+}
+carrier_id {
+  canonical_id: 1850
+  carrier_name: "Panhandle Telecommunication Systems Inc."
+  carrier_attribute {
+    mccmnc_tuple: "311450"
+  }
+}
+carrier_id {
+  canonical_id: 1851
+  carrier_name: "Fisher Wireless Services Inc"
+  carrier_attribute {
+    mccmnc_tuple: "311460"
+  }
+}
+carrier_id {
+  canonical_id: 1852
+  carrier_name: "Vitelcom Cellular Inc dba Innovative Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "311470"
+  }
+}
+carrier_id {
+  canonical_id: 1853
+  carrier_name: "Virgin Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "311490"
+  }
+}
+carrier_id {
+  canonical_id: 1854
+  carrier_name: "CTC Telecom Inc"
+  carrier_attribute {
+    mccmnc_tuple: "311500"
+  }
+}
+carrier_id {
+  canonical_id: 1855
+  carrier_name: "Benton-Lian Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "311510"
+  }
+}
+carrier_id {
+  canonical_id: 1856
+  carrier_name: "Crossroads Wireless Inc"
+  carrier_attribute {
+    mccmnc_tuple: "311520"
+  }
+}
+carrier_id {
+  canonical_id: 1857
+  carrier_name: "Wireless Communications Venture"
+  carrier_attribute {
+    mccmnc_tuple: "311530"
+  }
+}
+carrier_id {
+  canonical_id: 1858
+  carrier_name: "Keystone Wireless Inc"
+  carrier_attribute {
+    mccmnc_tuple: "311540"
+  }
+}
+carrier_id {
+  canonical_id: 1859
+  carrier_name: "Commnet Midwest LLC"
+  carrier_attribute {
+    mccmnc_tuple: "311550"
+  }
+}
+carrier_id {
+  canonical_id: 1860
+  carrier_name: "Nextel Communications Inc."
+  carrier_attribute {
+    mccmnc_tuple: "316010"
+  }
+}
+carrier_id {
+  canonical_id: 1861
+  carrier_name: "Southern Communications Services Inc."
+  carrier_attribute {
+    mccmnc_tuple: "316011"
+  }
+}
+carrier_id {
+  canonical_id: 1862
+  carrier_name: "Ancel"
+  carrier_attribute {
+    mccmnc_tuple: "74800"
+    mccmnc_tuple: "74801"
+    mccmnc_tuple: "74803"
+  }
+}
+carrier_id {
+  canonical_id: 1863
+  carrier_name: "Movistar"
+  carrier_attribute {
+    mccmnc_tuple: "74807"
+  }
+}
+carrier_id {
+  canonical_id: 1864
+  carrier_name: "Claro UY"
+  carrier_attribute {
+    mccmnc_tuple: "74810"
+  }
+}
+carrier_id {
+  canonical_id: 1865
+  carrier_name: "Buztel"
+  carrier_attribute {
+    mccmnc_tuple: "43401"
+  }
+}
+carrier_id {
+  canonical_id: 1866
+  carrier_name: "Uzmacom"
+  carrier_attribute {
+    mccmnc_tuple: "43402"
+  }
+}
+carrier_id {
+  canonical_id: 1867
+  carrier_name: "Daewoo Unitel"
+  carrier_attribute {
+    mccmnc_tuple: "43404"
+  }
+}
+carrier_id {
+  canonical_id: 1868
+  carrier_name: "Coscom"
+  carrier_attribute {
+    mccmnc_tuple: "43405"
+  }
+}
+carrier_id {
+  canonical_id: 1869
+  carrier_name: "Uzdunrobita"
+  carrier_attribute {
+    mccmnc_tuple: "43407"
+  }
+}
+carrier_id {
+  canonical_id: 1870
+  carrier_name: "Infonet"
+  carrier_attribute {
+    mccmnc_tuple: "73401"
+  }
+}
+carrier_id {
+  canonical_id: 1871
+  carrier_name: "Corporación Digitel"
+  carrier_attribute {
+    mccmnc_tuple: "73402"
+  }
+}
+carrier_id {
+  canonical_id: 1872
+  carrier_name: "Digicel"
+  carrier_attribute {
+    mccmnc_tuple: "73403"
+  }
+}
+carrier_id {
+  canonical_id: 1873
+  carrier_name: "Movistar"
+  carrier_attribute {
+    mccmnc_tuple: "73404"
+  }
+}
+carrier_id {
+  canonical_id: 1874
+  carrier_name: "Telecomunicaciones Movilnet, C.A."
+  carrier_attribute {
+    mccmnc_tuple: "73406"
+  }
+}
+carrier_id {
+  canonical_id: 1875
+  carrier_name: "Caribbean Cellular Telephone, Boatphone Ltd."
+  carrier_attribute {
+    mccmnc_tuple: "348570"
+  }
+}
+carrier_id {
+  canonical_id: 1876
+  carrier_name: "GoMobile SamoaTel Ltd"
+  carrier_attribute {
+    mccmnc_tuple: "54927"
+  }
+}
+carrier_id {
+  canonical_id: 1877
+  carrier_name: "Yemen Mobile Phone Company"
+  carrier_attribute {
+    mccmnc_tuple: "42101"
+  }
+}
+carrier_id {
+  canonical_id: 1878
+  carrier_name: "Spacetel Yemen"
+  carrier_attribute {
+    mccmnc_tuple: "42102"
+  }
+}
+carrier_id {
+  canonical_id: 1879
+  carrier_name: "Telecel"
+  carrier_attribute {
+    mccmnc_tuple: "64803"
+  }
+}
+carrier_id {
+  canonical_id: 1880
+  carrier_name: "Econet"
+  carrier_attribute {
+    mccmnc_tuple: "64804"
+  }
+}
+carrier_id {
+  canonical_id: 1881
+  carrier_name: "遠傳電信 Far EasTone Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "46601"
+    mccmnc_tuple: "46688"
+  }
+}
+carrier_id {
+  canonical_id: 1882
+  carrier_name: "亞太電信 Asia Pacific Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "46602"
+    mccmnc_tuple: "46605"
+  }
+}
+carrier_id {
+  canonical_id: 1883
+  carrier_name: "Tuntex Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "46606"
+  }
+}
+carrier_id {
+  canonical_id: 1884
+  carrier_name: "中華電信_Chunghwa Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "46611"
+    mccmnc_tuple: "46692"
+  }
+}
+carrier_id {
+  canonical_id: 1886
+  carrier_name: "台灣之星 T Star"
+  carrier_attribute {
+    mccmnc_tuple: "46689"
+  }
+}
+carrier_id {
+  canonical_id: 1887
+  carrier_name: "MobiTai Communications"
+  carrier_attribute {
+    mccmnc_tuple: "46693"
+  }
+}
+carrier_id {
+  canonical_id: 1888
+  carrier_name: "台灣大哥大 Taiwan Mobile Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "46697"
+  }
+}
+carrier_id {
+  canonical_id: 1889
+  carrier_name: "TransAsia Telecoms"
+  carrier_attribute {
+    mccmnc_tuple: "46699"
+  }
+}
+carrier_id {
+  canonical_id: 1890
+  carrier_name: "KT"
+  carrier_attribute {
+    mccmnc_tuple: "45002"
+    mccmnc_tuple: "45004"
+    mccmnc_tuple: "45008"
+  }
+}
+carrier_id {
+  canonical_id: 1891
+  carrier_name: "SK Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "45005"
+  }
+}
+carrier_id {
+  canonical_id: 1892
+  carrier_name: "LG U+"
+  carrier_attribute {
+    mccmnc_tuple: "45006"
+    mccmnc_tuple: "450006"
+  }
+}
+carrier_id {
+  canonical_id: 1893
+  carrier_name: "nTelos"
+  carrier_attribute {
+    mccmnc_tuple: "310470"
+  }
+}
+carrier_id {
+  canonical_id: 1894
+  carrier_name: "SoftBank・Y!mobile"
+  carrier_attribute {
+    mccmnc_tuple: "44020"
+  }
+}
+carrier_id {
+  canonical_id: 1895
+  carrier_name: "Freedom Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "302490"
+  }
+}
+carrier_id {
+  canonical_id: 1896
+  carrier_name: "dtac"
+  carrier_attribute {
+    mccmnc_tuple: "52018"
+  }
+}
+carrier_id {
+  canonical_id: 1897
+  carrier_name: "dtac "
+  carrier_attribute {
+    mccmnc_tuple: "52005"
+  }
+}
+carrier_id {
+  canonical_id: 1898
+  carrier_name: "True Move"
+  carrier_attribute {
+    mccmnc_tuple: "52099"
+  }
+}
+carrier_id {
+  canonical_id: 1899
+  carrier_name: "Viettel Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "45204"
+  }
+}
+carrier_id {
+  canonical_id: 1900
+  carrier_name: "OneCall"
+  carrier_attribute {
+    mccmnc_tuple: "24205"
+  }
+}
+carrier_id {
+  canonical_id: 1901
+  carrier_name: "Android Emulator"
+  carrier_attribute {
+    mccmnc_tuple: "310995"
+  }
+}
+carrier_id {
+  canonical_id: 1902
+  carrier_name: "Access Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "27204"
+  }
+}
+carrier_id {
+  canonical_id: 1903
+  carrier_name: "3"
+  carrier_attribute {
+    mccmnc_tuple: "27205"
+  }
+}
+carrier_id {
+  canonical_id: 1904
+  carrier_name: "DNA"
+  carrier_attribute {
+    mccmnc_tuple: "24403"
+    mccmnc_tuple: "24412"
+    mccmnc_tuple: "24413"
+  }
+}
+carrier_id {
+  canonical_id: 1905
+  carrier_name: "Nokia Test Network"
+  carrier_attribute {
+    mccmnc_tuple: "24407"
+  }
+}
+carrier_id {
+  canonical_id: 1906
+  carrier_name: "Unknown"
+  carrier_attribute {
+    mccmnc_tuple: "24408"
+  }
+}
+carrier_id {
+  canonical_id: 1907
+  carrier_name: "TDC"
+  carrier_attribute {
+    mccmnc_tuple: "24410"
+  }
+}
+carrier_id {
+  canonical_id: 1908
+  carrier_name: "Scnl Truphone"
+  carrier_attribute {
+    mccmnc_tuple: "24429"
+  }
+}
+carrier_id {
+  canonical_id: 1909
+  carrier_name: "Euskaltel"
+  carrier_attribute {
+    mccmnc_tuple: "21406"
+    mccmnc_tuple: "21408"
+  }
+}
+carrier_id {
+  canonical_id: 1910
+  carrier_name: "COX"
+  carrier_attribute {
+    mccmnc_tuple: "311600"
+  }
+}
+carrier_id {
+  canonical_id: 1911
+  carrier_name: "Test Network, Used by GSM test equipment"
+  carrier_attribute {
+    mccmnc_tuple: "00101"
+  }
+}
+carrier_id {
+  canonical_id: 1912
+  carrier_name: "AT&T MX"
+  carrier_attribute {
+    mccmnc_tuple: "33401"
+    mccmnc_tuple: "334090"
+    mccmnc_tuple: "33409"
+  }
+}
+carrier_id {
+  canonical_id: 1913
+  carrier_name: "Telcel"
+  carrier_attribute {
+    mccmnc_tuple: "334020"
+    mccmnc_tuple: "33402"
+  }
+}
+carrier_id {
+  canonical_id: 1914
+  carrier_name: "Movistar"
+  carrier_attribute {
+    mccmnc_tuple: "334030"
+    mccmnc_tuple: "33403"
+  }
+}
+carrier_id {
+  canonical_id: 1915
+  carrier_name: "AT&T MX"
+  carrier_attribute {
+    mccmnc_tuple: "334050"
+  }
+}
+carrier_id {
+  canonical_id: 1916
+  carrier_name: "Dauphin Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "34080"
+  }
+}
+carrier_id {
+  canonical_id: 1917
+  carrier_name: "eMobile"
+  carrier_attribute {
+    mccmnc_tuple: "44000"
+  }
+}
+carrier_id {
+  canonical_id: 1918
+  carrier_name: "Hondutel"
+  carrier_attribute {
+    mccmnc_tuple: "70830"
+  }
+}
+carrier_id {
+  canonical_id: 1919
+  carrier_name: "Digicel"
+  carrier_attribute {
+    mccmnc_tuple: "70840"
+  }
+}
+carrier_id {
+  canonical_id: 1920
+  carrier_name: "Alfa"
+  carrier_attribute {
+    mccmnc_tuple: "41501"
+  }
+}
+carrier_id {
+  canonical_id: 1921
+  carrier_name: "MTC Touch"
+  carrier_attribute {
+    mccmnc_tuple: "41503"
+  }
+}
+carrier_id {
+  canonical_id: 1922
+  carrier_name: "Ogero Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "41505"
+  }
+}
+carrier_id {
+  canonical_id: 1923
+  carrier_name: "Ncell"
+  carrier_attribute {
+    mccmnc_tuple: "42902"
+  }
+}
+carrier_id {
+  canonical_id: 1924
+  carrier_name: "Smart Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "42904"
+  }
+}
+carrier_id {
+  canonical_id: 1925
+  carrier_name: "Claro PA"
+  carrier_attribute {
+    mccmnc_tuple: "71403"
+  }
+}
+carrier_id {
+  canonical_id: 1926
+  carrier_name: "Digicel"
+  carrier_attribute {
+    mccmnc_tuple: "71404"
+  }
+}
+carrier_id {
+  canonical_id: 1927
+  carrier_name: "Telecel"
+  carrier_attribute {
+    mccmnc_tuple: "74404"
+  }
+}
+carrier_id {
+  canonical_id: 1928
+  carrier_name: "Personal"
+  carrier_attribute {
+    mccmnc_tuple: "74405"
+  }
+}
+carrier_id {
+  canonical_id: 1929
+  carrier_name: "Telefonica Moviles Peru"
+  carrier_attribute {
+    mccmnc_tuple: "71606"
+  }
+}
+carrier_id {
+  canonical_id: 1930
+  carrier_name: "Nextel"
+  carrier_attribute {
+    mccmnc_tuple: "71617"
+  }
+}
+carrier_id {
+  canonical_id: 1931
+  carrier_name: "Sri Lanka Telecom Mobitel"
+  carrier_attribute {
+    mccmnc_tuple: "41301"
+  }
+}
+carrier_id {
+  canonical_id: 1932
+  carrier_name: "Airtel Lanka"
+  carrier_attribute {
+    mccmnc_tuple: "41305"
+  }
+}
+carrier_id {
+  canonical_id: 1933
+  carrier_name: "Hutchison Telecommunications Lanka"
+  carrier_attribute {
+    mccmnc_tuple: "41308"
+  }
+}
+carrier_id {
+  canonical_id: 1934
+  carrier_name: "Sasatel Tanzania"
+  carrier_attribute {
+    mccmnc_tuple: "64006"
+  }
+}
+carrier_id {
+  canonical_id: 1935
+  carrier_name: "Life Tanzania"
+  carrier_attribute {
+    mccmnc_tuple: "64007"
+  }
+}
+carrier_id {
+  canonical_id: 1936
+  carrier_name: "Orange Tunisie"
+  carrier_attribute {
+    mccmnc_tuple: "60501"
+  }
+}
+carrier_id {
+  canonical_id: 1937
+  carrier_name: "ArmenTel"
+  carrier_attribute {
+    mccmnc_tuple: "28301"
+  }
+}
+carrier_id {
+  canonical_id: 1938
+  carrier_name: "Karabakh Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "28304"
+  }
+}
+carrier_id {
+  canonical_id: 1939
+  carrier_name: "K Telecom CJSC"
+  carrier_attribute {
+    mccmnc_tuple: "28305"
+  }
+}
+carrier_id {
+  canonical_id: 1940
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "28310"
+  }
+}
+carrier_id {
+  canonical_id: 1941
+  carrier_name: "Bahamas Telecommunications"
+  carrier_attribute {
+    mccmnc_tuple: "364390"
+  }
+}
+carrier_id {
+  canonical_id: 1942
+  carrier_name: "Open Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "33000"
+  }
+}
+carrier_id {
+  canonical_id: 1943
+  carrier_name: "Orange Niger"
+  carrier_attribute {
+    mccmnc_tuple: "61404"
+  }
+}
+carrier_id {
+  canonical_id: 1944
+  carrier_name: "Bell Benin Communications"
+  carrier_attribute {
+    mccmnc_tuple: "61604"
+  }
+}
+carrier_id {
+  canonical_id: 1945
+  carrier_name: "Glo Communications Benin"
+  carrier_attribute {
+    mccmnc_tuple: "61605"
+  }
+}
+carrier_id {
+  canonical_id: 1946
+  carrier_name: "Onatal (Telmob)"
+  carrier_attribute {
+    mccmnc_tuple: "61301"
+  }
+}
+carrier_id {
+  canonical_id: 1947
+  carrier_name: "Moov Togo"
+  carrier_attribute {
+    mccmnc_tuple: "61503"
+  }
+}
+carrier_id {
+  canonical_id: 1948
+  carrier_name: "Orange"
+  carrier_attribute {
+    mccmnc_tuple: "63203"
+  }
+}
+carrier_id {
+  canonical_id: 1949
+  carrier_name: "MetroPCS"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "6D38"
+  }
+}
+carrier_id {
+  canonical_id: 1950
+  carrier_name: "life:)"
+  carrier_attribute {
+    mccmnc_tuple: "25704"
+  }
+}
+carrier_id {
+  canonical_id: 1951
+  carrier_name: "Boost Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "311870"
+  }
+}
+carrier_id {
+  canonical_id: 1952
+  carrier_name: "U.S. Cellular"
+  carrier_attribute {
+    mccmnc_tuple: "311580"
+    mccmnc_tuple: "311220"
+  }
+}
+carrier_id {
+  canonical_id: 1953
+  carrier_name: "Claro CR"
+  carrier_attribute {
+    mccmnc_tuple: "71203"
+  }
+}
+carrier_id {
+  canonical_id: 1954
+  carrier_name: "Claro SV"
+  carrier_attribute {
+    mccmnc_tuple: "70601"
+  }
+}
+carrier_id {
+  canonical_id: 1955
+  carrier_name: "Claro PR"
+  carrier_attribute {
+    mccmnc_tuple: "330110"
+    mccmnc_tuple: "33011"
+  }
+}
+carrier_id {
+  canonical_id: 1956
+  carrier_name: "Telenor Sweden (not used)"
+  carrier_attribute {
+    mccmnc_tuple: "24009"
+  }
+}
+carrier_id {
+  canonical_id: 1957
+  carrier_name: "Bluesky"
+  carrier_attribute {
+    mccmnc_tuple: "54411"
+  }
+}
+carrier_id {
+  canonical_id: 1958
+  carrier_name: "Free"
+  carrier_attribute {
+    mccmnc_tuple: "20815"
+  }
+}
+carrier_id {
+  canonical_id: 1959
+  carrier_name: "Digi.Mobil"
+  carrier_attribute {
+    mccmnc_tuple: "22605"
+  }
+}
+carrier_id {
+  canonical_id: 1960
+  carrier_name: "Hutchison 2G"
+  carrier_attribute {
+    mccmnc_tuple: "45404"
+    mccmnc_tuple: "45405"
+  }
+}
+carrier_id {
+  canonical_id: 1961
+  carrier_name: "Airtel"
+  carrier_attribute {
+    mccmnc_tuple: "40402"
+    mccmnc_tuple: "40403"
+    mccmnc_tuple: "40410"
+    mccmnc_tuple: "40416"
+    mccmnc_tuple: "40431"
+    mccmnc_tuple: "40440"
+    mccmnc_tuple: "40445"
+    mccmnc_tuple: "40449"
+    mccmnc_tuple: "40470"
+    mccmnc_tuple: "40490"
+    mccmnc_tuple: "40492"
+    mccmnc_tuple: "40493"
+    mccmnc_tuple: "40494"
+    mccmnc_tuple: "40495"
+    mccmnc_tuple: "40496"
+    mccmnc_tuple: "40497"
+    mccmnc_tuple: "40498"
+    mccmnc_tuple: "40551"
+    mccmnc_tuple: "40552"
+    mccmnc_tuple: "40553"
+    mccmnc_tuple: "40554"
+    mccmnc_tuple: "40555"
+    mccmnc_tuple: "40556"
+  }
+}
+carrier_id {
+  canonical_id: 1962
+  carrier_name: "Fido"
+  carrier_attribute {
+    mccmnc_tuple: "302370"
+    gid1: "DD"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "302370"
+    mccmnc_tuple: "30237"
+  }
+}
+carrier_id {
+  canonical_id: 1963
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "40401"
+    mccmnc_tuple: "40405"
+    mccmnc_tuple: "40411"
+    mccmnc_tuple: "40413"
+    mccmnc_tuple: "40415"
+    mccmnc_tuple: "40420"
+    mccmnc_tuple: "40427"
+    mccmnc_tuple: "40430"
+    mccmnc_tuple: "40443"
+    mccmnc_tuple: "40446"
+    mccmnc_tuple: "40460"
+    mccmnc_tuple: "40484"
+    mccmnc_tuple: "40486"
+    mccmnc_tuple: "40488"
+    mccmnc_tuple: "40566"
+    mccmnc_tuple: "40567"
+    mccmnc_tuple: "405750"
+    mccmnc_tuple: "405751"
+    mccmnc_tuple: "405752"
+    mccmnc_tuple: "405753"
+    mccmnc_tuple: "405754"
+    mccmnc_tuple: "405755"
+    mccmnc_tuple: "405756"
+  }
+}
+carrier_id {
+  canonical_id: 1964
+  carrier_name: "Aio"
+  carrier_attribute {
+    mccmnc_tuple: "310150"
+  }
+}
+carrier_id {
+  canonical_id: 1965
+  carrier_name: "Telkom"
+  carrier_attribute {
+    mccmnc_tuple: "65502"
+  }
+}
+carrier_id {
+  canonical_id: 1966
+  carrier_name: "3"
+  carrier_attribute {
+    mccmnc_tuple: "51089"
+  }
+}
+carrier_id {
+  canonical_id: 1967
+  carrier_name: "Irancell"
+  carrier_attribute {
+    mccmnc_tuple: "43235"
+  }
+}
+carrier_id {
+  canonical_id: 1968
+  carrier_name: "Etisalat"
+  carrier_attribute {
+    mccmnc_tuple: "60203"
+  }
+}
+carrier_id {
+  canonical_id: 1969
+  carrier_name: "Asia Cell"
+  carrier_attribute {
+    mccmnc_tuple: "41805"
+  }
+}
+carrier_id {
+  canonical_id: 1970
+  carrier_name: "du"
+  carrier_attribute {
+    mccmnc_tuple: "42403"
+  }
+}
+carrier_id {
+  canonical_id: 1971
+  carrier_name: "Zain Iraq"
+  carrier_attribute {
+    mccmnc_tuple: "41820"
+    mccmnc_tuple: "41830"
+  }
+}
+carrier_id {
+  canonical_id: 1972
+  carrier_name: "Zain Saudi Arabia"
+  carrier_attribute {
+    mccmnc_tuple: "42004"
+  }
+}
+carrier_id {
+  canonical_id: 1973
+  carrier_name: "Libyana"
+  carrier_attribute {
+    mccmnc_tuple: "60600"
+  }
+}
+carrier_id {
+  canonical_id: 1974
+  carrier_name: "Jazztel"
+  carrier_attribute {
+    mccmnc_tuple: "21421"
+  }
+}
+carrier_id {
+  canonical_id: 1975
+  carrier_name: "Telenor"
+  carrier_attribute {
+    mccmnc_tuple: "41006"
+  }
+}
+carrier_id {
+  canonical_id: 1976
+  carrier_name: "ONO"
+  carrier_attribute {
+    mccmnc_tuple: "21418"
+  }
+}
+carrier_id {
+  canonical_id: 1977
+  carrier_name: "Ooredoo"
+  carrier_attribute {
+    mccmnc_tuple: "60303"
+  }
+}
+carrier_id {
+  canonical_id: 1978
+  carrier_name: "Smartfren"
+  carrier_attribute {
+    mccmnc_tuple: "51009"
+    mccmnc_tuple: "51028"
+  }
+}
+carrier_id {
+  canonical_id: 1979
+  carrier_name: "9Pay"
+  carrier_attribute {
+    mccmnc_tuple: "62160"
+  }
+}
+carrier_id {
+  canonical_id: 1980
+  carrier_name: "Zong"
+  carrier_attribute {
+    mccmnc_tuple: "41004"
+  }
+}
+carrier_id {
+  canonical_id: 1981
+  carrier_name: "WaridTel"
+  carrier_attribute {
+    mccmnc_tuple: "41007"
+  }
+}
+carrier_id {
+  canonical_id: 1982
+  carrier_name: "TATA DOCOMO"
+  carrier_attribute {
+    mccmnc_tuple: "405025"
+    mccmnc_tuple: "405026"
+    mccmnc_tuple: "405027"
+    mccmnc_tuple: "405028"
+    mccmnc_tuple: "405029"
+    mccmnc_tuple: "405030"
+    mccmnc_tuple: "405031"
+    mccmnc_tuple: "405032"
+    mccmnc_tuple: "405033"
+    mccmnc_tuple: "405034"
+    mccmnc_tuple: "405035"
+    mccmnc_tuple: "405036"
+    mccmnc_tuple: "405037"
+    mccmnc_tuple: "405038"
+    mccmnc_tuple: "405039"
+    mccmnc_tuple: "405041"
+    mccmnc_tuple: "405042"
+    mccmnc_tuple: "405043"
+    mccmnc_tuple: "405044"
+    mccmnc_tuple: "405045"
+    mccmnc_tuple: "405046"
+    mccmnc_tuple: "405047"
+  }
+}
+carrier_id {
+  canonical_id: 1983
+  carrier_name: "Korek"
+  carrier_attribute {
+    mccmnc_tuple: "41840"
+  }
+}
+carrier_id {
+  canonical_id: 1984
+  carrier_name: "Virgin"
+  carrier_attribute {
+    mccmnc_tuple: "20823"
+  }
+}
+carrier_id {
+  canonical_id: 1985
+  carrier_name: "Wana"
+  carrier_attribute {
+    mccmnc_tuple: "60402"
+  }
+}
+carrier_id {
+  canonical_id: 1986
+  carrier_name: "Tele2"
+  carrier_attribute {
+    mccmnc_tuple: "40177"
+  }
+}
+carrier_id {
+  canonical_id: 1987
+  carrier_name: "Rightel"
+  carrier_attribute {
+    mccmnc_tuple: "43220"
+  }
+}
+carrier_id {
+  canonical_id: 1988
+  carrier_name: "O2"
+  carrier_attribute {
+    mccmnc_tuple: "23106"
+  }
+}
+carrier_id {
+  canonical_id: 1989
+  carrier_name: "Project Fi"
+  carrier_attribute {
+    mccmnc_tuple: "23420"
+    gid1: "0306"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "45403"
+    gid1: "0206"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "310120"
+    spn: "Fi Network"
+    spn: "nova"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    imsi_prefix_xpattern: "31026097"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "311580"
+    imsi_prefix_xpattern: "3115801"
+  }
+}
+carrier_id {
+  canonical_id: 1990
+  carrier_name: "Golan Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "42508"
+  }
+}
+carrier_id {
+  canonical_id: 1991
+  carrier_name: "Hot Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "42507"
+    mccmnc_tuple: "42577"
+  }
+}
+carrier_id {
+  canonical_id: 1992
+  carrier_name: "Viva"
+  carrier_attribute {
+    mccmnc_tuple: "41904"
+  }
+}
+carrier_id {
+  canonical_id: 1994
+  carrier_name: "Vietnamobile"
+  carrier_attribute {
+    mccmnc_tuple: "45205"
+  }
+}
+carrier_id {
+  canonical_id: 1996
+  carrier_name: "Ooredoo Myanmar"
+  carrier_attribute {
+    mccmnc_tuple: "41405"
+  }
+}
+carrier_id {
+  canonical_id: 1997
+  carrier_name: "TrueMove H 4G LTE"
+  carrier_attribute {
+    mccmnc_tuple: "52004"
+  }
+}
+carrier_id {
+  canonical_id: 1998
+  carrier_name: "Tigo"
+  carrier_attribute {
+    mccmnc_tuple: "70603"
+  }
+}
+carrier_id {
+  canonical_id: 1999
+  carrier_name: "VIVACOM"
+  carrier_attribute {
+    mccmnc_tuple: "28403"
+  }
+}
+carrier_id {
+  canonical_id: 2001
+  carrier_name: "Vodafone"
+  carrier_attribute {
+    mccmnc_tuple: "42702"
+  }
+}
+carrier_id {
+  canonical_id: 2002
+  carrier_name: "Uninor"
+  carrier_attribute {
+    mccmnc_tuple: "405813"
+    mccmnc_tuple: "405814"
+    mccmnc_tuple: "405815"
+    mccmnc_tuple: "405816"
+    mccmnc_tuple: "405817"
+    mccmnc_tuple: "405818"
+    mccmnc_tuple: "405819"
+    mccmnc_tuple: "405820"
+    mccmnc_tuple: "405821"
+    mccmnc_tuple: "405822"
+    mccmnc_tuple: "405844"
+    mccmnc_tuple: "405875"
+    mccmnc_tuple: "405876"
+    mccmnc_tuple: "405877"
+    mccmnc_tuple: "405878"
+    mccmnc_tuple: "405879"
+    mccmnc_tuple: "405880"
+    mccmnc_tuple: "405925"
+    mccmnc_tuple: "405926"
+    mccmnc_tuple: "405927"
+    mccmnc_tuple: "405928"
+    mccmnc_tuple: "405929"
+  }
+}
+carrier_id {
+  canonical_id: 2003
+  carrier_name: "movistar"
+  carrier_attribute {
+    mccmnc_tuple: "71204"
+  }
+}
+carrier_id {
+  canonical_id: 2004
+  carrier_name: "Airtel BD"
+  carrier_attribute {
+    mccmnc_tuple: "47007"
+  }
+}
+carrier_id {
+  canonical_id: 2005
+  carrier_name: "NRJ Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "20826"
+  }
+}
+carrier_id {
+  canonical_id: 2006
+  carrier_name: "Madar"
+  carrier_attribute {
+    mccmnc_tuple: "60601"
+  }
+}
+carrier_id {
+  canonical_id: 2007
+  carrier_name: "Telenor Myanmar"
+  carrier_attribute {
+    mccmnc_tuple: "41406"
+  }
+}
+carrier_id {
+  canonical_id: 2008
+  carrier_name: "Videotron"
+  carrier_attribute {
+    mccmnc_tuple: "302500"
+    mccmnc_tuple: "302510"
+    mccmnc_tuple: "302520"
+  }
+}
+carrier_id {
+  canonical_id: 2009
+  carrier_name: "Movistar (Telefonica Moviles El Salvador)"
+  carrier_attribute {
+    mccmnc_tuple: "70604"
+    mccmnc_tuple: "706040"
+  }
+}
+carrier_id {
+  canonical_id: 2010
+  carrier_name: "Movistar (Telefonía Celular de Nicaragua)"
+  carrier_attribute {
+    mccmnc_tuple: "71030"
+    mccmnc_tuple: "710300"
+  }
+}
+carrier_id {
+  canonical_id: 2011
+  carrier_name: "Inland Cellular"
+  carrier_attribute {
+    mccmnc_tuple: "310580"
+  }
+}
+carrier_id {
+  canonical_id: 2014
+  carrier_name: "Zain Bahrain"
+  carrier_attribute {
+    mccmnc_tuple: "42602"
+  }
+}
+carrier_id {
+  canonical_id: 2015
+  carrier_name: "VIVA"
+  carrier_attribute {
+    mccmnc_tuple: "42604"
+  }
+}
+carrier_id {
+  canonical_id: 2017
+  carrier_name: "Yes 4G"
+  carrier_attribute {
+    mccmnc_tuple: "502152"
+  }
+}
+carrier_id {
+  canonical_id: 2018
+  carrier_name: "Reliance Jio"
+  carrier_attribute {
+    mccmnc_tuple: "405840"
+    mccmnc_tuple: "405854"
+    mccmnc_tuple: "405855"
+    mccmnc_tuple: "405856"
+    mccmnc_tuple: "405857"
+    mccmnc_tuple: "405858"
+    mccmnc_tuple: "405859"
+    mccmnc_tuple: "405860"
+    mccmnc_tuple: "405861"
+    mccmnc_tuple: "405862"
+    mccmnc_tuple: "405863"
+    mccmnc_tuple: "405864"
+    mccmnc_tuple: "405865"
+    mccmnc_tuple: "405866"
+    mccmnc_tuple: "405867"
+    mccmnc_tuple: "405868"
+    mccmnc_tuple: "405869"
+    mccmnc_tuple: "405870"
+    mccmnc_tuple: "405871"
+    mccmnc_tuple: "405872"
+    mccmnc_tuple: "405873"
+    mccmnc_tuple: "405874"
+  }
+}
+carrier_id {
+  canonical_id: 2020
+  carrier_name: "Koodo Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "302220"
+    mccmnc_tuple: "302221"
+    mccmnc_tuple: "30222"
+    mccmnc_tuple: "30286"
+    gid1: "4b4f"
+  }
+}
+carrier_id {
+  canonical_id: 2021
+  carrier_name: "Virgin Mobile Canada"
+  carrier_attribute {
+    mccmnc_tuple: "30264"
+    mccmnc_tuple: "302610"
+    mccmnc_tuple: "302630"
+    mccmnc_tuple: "302640"
+    gid1: "3e"
+  }
+}
+carrier_id {
+  canonical_id: 2022
+  carrier_name: "TracFone"
+  carrier_attribute {
+    mccmnc_tuple: "310410"
+    mccmnc_tuple: "310260"
+    gid1: "DDFF"
+    gid1: "DEFF"
+  }
+}
+carrier_id {
+  canonical_id: 2023
+  carrier_name: "Consumer Cellular"
+  carrier_attribute {
+    mccmnc_tuple: "310410"
+    mccmnc_tuple: "310260"
+    gid1: "2AC9"
+  }
+}
+carrier_id {
+  canonical_id: 2024
+  carrier_name: "Locus Telecom"
+  carrier_attribute {
+    mccmnc_tuple: "310410"
+    gid1: "49FF"
+  }
+}
+carrier_id {
+  canonical_id: 2025
+  carrier_name: "Telrite/Pure Talk"
+  carrier_attribute {
+    mccmnc_tuple: "310410"
+    gid1: "62FF"
+  }
+}
+carrier_id {
+  canonical_id: 2026
+  carrier_name: "Red Pocket"
+  carrier_attribute {
+    mccmnc_tuple: "310410"
+    mccmnc_tuple: "310260"
+    gid1: "4201"
+  }
+}
+carrier_id {
+  canonical_id: 2027
+  carrier_name: "Airvoice"
+  carrier_attribute {
+    mccmnc_tuple: "310410"
+    gid1: "44FF"
+  }
+}
+carrier_id {
+  canonical_id: 2028
+  carrier_name: "Ztar"
+  carrier_attribute {
+    mccmnc_tuple: "310410"
+    gid1: "4102"
+  }
+}
+carrier_id {
+  canonical_id: 2029
+  carrier_name: "Defense Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "310410"
+    gid1: "60FF"
+  }
+}
+carrier_id {
+  canonical_id: 2030
+  carrier_name: "AGMS"
+  carrier_attribute {
+    mccmnc_tuple: "310380"
+    gid1: "50FF"
+  }
+}
+carrier_id {
+  canonical_id: 2031
+  carrier_name: "Kore"
+  carrier_attribute {
+    mccmnc_tuple: "310410"
+    gid1: "69FF"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "4B4F"
+  }
+}
+carrier_id {
+  canonical_id: 2032
+  carrier_name: "XFINITY Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "311480"
+    gid1: "BA01450000000000"
+  }
+}
+carrier_id {
+  canonical_id: 2033
+  carrier_name: "Ooredoo"
+  carrier_attribute {
+    mccmnc_tuple: "47202"
+  }
+}
+carrier_id {
+  canonical_id: 2034
+  carrier_name: "Orange Mali"
+  carrier_attribute {
+    mccmnc_tuple: "61002"
+  }
+}
+carrier_id {
+  canonical_id: 2035
+  carrier_name: "Celcom"
+  carrier_attribute {
+    mccmnc_tuple: "61807"
+  }
+}
+carrier_id {
+  canonical_id: 2036
+  carrier_name: "Tigo"
+  carrier_attribute {
+    mccmnc_tuple: "63089"
+  }
+}
+carrier_id {
+  canonical_id: 2037
+  carrier_name: "Bite"
+  carrier_attribute {
+    mccmnc_tuple: "24705"
+  }
+}
+carrier_id {
+  canonical_id: 2038
+  carrier_name: "unifi mobile"
+  carrier_attribute {
+    mccmnc_tuple: "50211"
+    mccmnc_tuple: "502153"
+  }
+}
+carrier_id {
+  canonical_id: 2052
+  carrier_name: "Virgin"
+  carrier_attribute {
+    mccmnc_tuple: "42005"
+  }
+}
+carrier_id {
+  canonical_id: 2053
+  carrier_name: "PC mobile"
+  carrier_attribute {
+    mccmnc_tuple: "30264"
+    mccmnc_tuple: "302610"
+    mccmnc_tuple: "302630"
+    mccmnc_tuple: "302640"
+    gid1: "40"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "302220"
+    gid1: "5043"
+  }
+}
+carrier_id {
+  canonical_id: 2054
+  carrier_name: "Solo Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "30264"
+    mccmnc_tuple: "302610"
+    mccmnc_tuple: "302630"
+    mccmnc_tuple: "302640"
+    gid1: "3f"
+  }
+}
+carrier_id {
+  canonical_id: 2055
+  carrier_name: "Chatr Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "302720"
+    imsi_prefix_xpattern: "302720x94"
+    gid1: "ff"
+  }
+}
+carrier_id {
+  canonical_id: 2056
+  carrier_name: "Ztar Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "302720"
+    imsi_prefix_xpattern: "302720x98"
+    gid1: "ff"
+  }
+}
+carrier_id {
+  canonical_id: 2057
+  carrier_name: "Cityfone"
+  carrier_attribute {
+    mccmnc_tuple: "302720"
+    imsi_prefix_xpattern: "302720x97"
+    gid1: "cc"
+  }
+}
+carrier_id {
+  canonical_id: 2060
+  carrier_name: "Amaysim (MVNE2)"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "6133"
+  }
+}
+carrier_id {
+  canonical_id: 2062
+  carrier_name: "Bright Spot (Leto)"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "4C45"
+  }
+}
+carrier_id {
+  canonical_id: 2063
+  carrier_name: "Family Mobile (Walmart)"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "4D4B"
+  }
+}
+carrier_id {
+  canonical_id: 2064
+  carrier_name: "GoSmart"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "4753"
+  }
+}
+carrier_id {
+  canonical_id: 2065
+  carrier_name: "IDT"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "AB"
+  }
+}
+carrier_id {
+  canonical_id: 2066
+  carrier_name: "Kajeet (Arterra)"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "6136"
+  }
+}
+carrier_id {
+  canonical_id: 2067
+  carrier_name: "Lyca Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "6C79"
+  }
+}
+carrier_id {
+  canonical_id: 2068
+  carrier_name: "M2M"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "3201"
+  }
+}
+carrier_id {
+  canonical_id: 2069
+  carrier_name: "MVNE2/AMDOCS"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "6132"
+  }
+}
+carrier_id {
+  canonical_id: 2070
+  carrier_name: "Nest"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "4E45"
+  }
+}
+carrier_id {
+  canonical_id: 2071
+  carrier_name: "Plintron"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "7031"
+  }
+}
+carrier_id {
+  canonical_id: 2073
+  carrier_name: "PWG/Cintex"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "4358"
+  }
+}
+carrier_id {
+  canonical_id: 2074
+  carrier_name: "Ready Wireless"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "8234"
+  }
+}
+carrier_id {
+  canonical_id: 2075
+  carrier_name: "Republic Wireless (MVNE2)"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "6134"
+  }
+}
+carrier_id {
+  canonical_id: 2076
+  carrier_name: "Roam Mobility"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "726D"
+    gid1: "524D"
+  }
+}
+carrier_id {
+  canonical_id: 2077
+  carrier_name: "Rock Island"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "6137"
+  }
+}
+carrier_id {
+  canonical_id: 2078
+  carrier_name: "Simple Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "534D"
+  }
+}
+carrier_id {
+  canonical_id: 2079
+  carrier_name: "Solavei"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "7376"
+  }
+}
+carrier_id {
+  canonical_id: 2080
+  carrier_name: "Ting"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "6135"
+  }
+}
+carrier_id {
+  canonical_id: 2081
+  carrier_name: "Twilio M2M"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "7477"
+  }
+}
+carrier_id {
+  canonical_id: 2083
+  carrier_name: "Ultra/Univision"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "354D"
+    gid1: "364D"
+    gid1: "4153"
+    gid1: "554D"
+  }
+}
+carrier_id {
+  canonical_id: 2086
+  carrier_name: "Vodafone US"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "2801"
+  }
+}
+carrier_id {
+  canonical_id: 2087
+  carrier_name: "Wyless"
+  carrier_attribute {
+    mccmnc_tuple: "310260"
+    gid1: "574D"
+  }
+}
+carrier_id {
+  canonical_id: 2088
+  carrier_name: "Crnogorski Telekom"
+  carrier_attribute {
+    mccmnc_tuple: "29702"
+    spn: "Telekom.me"
+  }
+}
+carrier_id {
+  canonical_id: 2089
+  carrier_name: "Public Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "302220"
+    gid1: "4d4f"
+  }
+}
+carrier_id {
+  canonical_id: 2090
+  carrier_name: "Tbaytel"
+  carrier_attribute {
+    mccmnc_tuple: "302720"
+    imsi_prefix_xpattern: "302720x92"
+    gid1: "ba"
+  }
+}
+carrier_id {
+  canonical_id: 2091
+  carrier_name: "Bonbon"
+  carrier_attribute {
+    mccmnc_tuple: "21901"
+    spn: "bonbon"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "21901"
+    gid1: "10"
+    gid1: "11"
+    gid1: "12"
+  }
+}
+carrier_id {
+  canonical_id: 2092
+  carrier_name: "Congstar"
+  carrier_attribute {
+    mccmnc_tuple: "26201"
+    gid1: "44"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "26201"
+    spn: "congstar"
+    spn: "congstar.de"
+  }
+}
+carrier_id {
+  canonical_id: 2093
+  carrier_name: "Tesco"
+  carrier_attribute {
+    mccmnc_tuple: "23410"
+    gid1: "0A"
+    gid1: "0AFFFF"
+    gid1: "0AFFFFFFFFFF544553434F202020202020202020"
+  }
+}
+carrier_id {
+  canonical_id: 2094
+  carrier_name: "tele.ring"
+  carrier_attribute {
+    mccmnc_tuple: "23207"
+    gid1: ""
+    gid1: "07"
+    gid1: "FF"
+  }
+}
+carrier_id {
+  canonical_id: 2095
+  carrier_name: "Ben"
+  carrier_attribute {
+    mccmnc_tuple: "20416"
+    gid1: "5F"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "20416"
+    spn: "Ben NL"
+  }
+}
+carrier_id {
+  canonical_id: 2096
+  carrier_name: "Heyah"
+  carrier_attribute {
+    mccmnc_tuple: "26002"
+    gid1: "23"
+  }
+  carrier_attribute {
+    mccmnc_tuple: "26002"
+    spn: "heyah"
+  }
+}
+carrier_id {
+  canonical_id: 2100
+  carrier_name: "Y!mobile"
+  carrier_attribute {
+    mccmnc_tuple: "44020"
+    imsi_prefix_xpattern: "4402091"
+    gid1: "16ffff"
+  }
+}
+carrier_id {
+  canonical_id: 2101
+  carrier_name: "BT"
+  carrier_attribute {
+    mccmnc_tuple: "23430"
+    gid1: "c3"
+    gid1: "c3ff"
+  }
+}
+carrier_id {
+  canonical_id: 2102
+  carrier_name: "BT Business"
+  carrier_attribute {
+    mccmnc_tuple: "23430"
+    gid1: "b3"
+    gid1: "b3ff"
+  }
+}
+carrier_id {
+  canonical_id: 2103
+  carrier_name: "BT One Phone"
+  carrier_attribute {
+    mccmnc_tuple: "23430"
+    mccmnc_tuple: "23408"
+    gid1: "b2"
+    gid1: "b2ff"
+  }
+}
+carrier_id {
+  canonical_id: 2105
+  carrier_name: "Skinny"
+  carrier_attribute {
+    mccmnc_tuple: "53005"
+    spn: "Skinny"
+  }
+}
+carrier_id {
+  canonical_id: 2106
+  carrier_name: "IIJmio"
+  carrier_attribute {
+    mccmnc_tuple: "44010"
+    preferred_apn: "iijmio.jp"
+  }
+}
+carrier_id {
+  canonical_id: 2107
+  carrier_name: "Telenor"
+  carrier_attribute {
+    mccmnc_tuple: "29701"
+  }
+}
+carrier_id {
+  canonical_id: 2108
+  carrier_name: "Airtel"
+  carrier_attribute {
+    mccmnc_tuple: "62006"
+  }
+}
+carrier_id {
+  canonical_id: 2109
+  carrier_name: "Rakuten Mobile"
+  carrier_attribute {
+    mccmnc_tuple: "44010"
+    preferred_apn: "rmobile.co"
+    preferred_apn: "rmobile.jp"
+  }
+}
+carrier_id {
+  canonical_id: 2110
+  carrier_name: "UQ mobile"
+  carrier_attribute {
+    mccmnc_tuple: "44051"
+    preferred_apn: "uqmobile.jp"
+  }
+}
+carrier_id {
+  canonical_id: 2111
+  carrier_name: "Euskaltel"
+  carrier_attribute {
+    mccmnc_tuple: "21403"
+    mccmnc_tuple: "21408"
+    spn: "EUSKALTEL"
+  }
+}
+carrier_id {
+  canonical_id: 2112
+  carrier_name: "Telecable"
+  carrier_attribute {
+    mccmnc_tuple: "21405"
+    mccmnc_tuple: "21416"
+    spn: "telecable"
+    spn: "Telecable"
+    spn: "TeleCable"
+  }
+}
+carrier_id {
+  canonical_id: 2113
+  carrier_name: "mobilR"
+  carrier_attribute {
+    mccmnc_tuple: "21403"
+    mccmnc_tuple: "21408"
+    mccmnc_tuple: "21417"
+    spn: "mobilR"
+    spn: "mobil R"
+    spn: "Mobil R"
+  }
+}
+carrier_id {
+  canonical_id: 2114
+  carrier_name: "EWE"
+  carrier_attribute {
+    mccmnc_tuple: "26202"
+    spn: "ewe.de"
+  }
+}
+carrier_id {
+  canonical_id: 2115
+  carrier_name: "Glo"
+  carrier_attribute {
+    mccmnc_tuple: "62150"
+  }
+}
+carrier_id {
+  canonical_id: 2116
+  carrier_name: "Ratel"
+  carrier_attribute {
+    mccmnc_tuple: "44010"
+    preferred_apn: "ratel.com"
+  }
+}
+carrier_id {
+  canonical_id: 2117
+  carrier_name: "TalkTalk"
+  carrier_attribute {
+    mccmnc_tuple: "23410"
+    gid1: "537"
+  }
+}
+carrier_id {
+  canonical_id: 2118
+  carrier_name: "giffgaff"
+  carrier_attribute {
+    mccmnc_tuple: "23410"
+    gid1: "508"
+  }
+}
+version: 4
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 1c53b15..309a57b 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -17,5 +17,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" product="tablet" msgid="9194799012395299737">"تهيئة شبكة الجوال"</string>
-    <string name="app_label" product="default" msgid="8338087656149558019">"سعة تخزينية للهاتف والرسائل"</string>
+    <string name="app_label" product="default" msgid="8338087656149558019">"مساحة تخزين للهاتف والرسائل"</string>
 </resources>
diff --git a/res/values-as/config.xml b/res/values-as/config.xml
new file mode 100644
index 0000000..99877a6
--- /dev/null
+++ b/res/values-as/config.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="persist_apns_for_plmn">
+    <item msgid="6413072509259000954">"20404"</item>
+    <item msgid="5639159280778239123">"310004"</item>
+    <item msgid="3860605521380788028">"310120"</item>
+    <item msgid="537693705785480198">"311480"</item>
+  </string-array>
+</resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
new file mode 100644
index 0000000..6994d18
--- /dev/null
+++ b/res/values-as/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" product="tablet" msgid="9194799012395299737">"ম’বাইল নেটৱৰ্ক কনফিগাৰেশ্বন"</string>
+    <string name="app_label" product="default" msgid="8338087656149558019">"ফ\'ন আৰু বাৰ্তাৰ সঞ্চয়াগাৰ"</string>
+</resources>
diff --git a/res/values-en-rXC/config.xml b/res/values-en-rXC/config.xml
index 274d8aa..5fadb9d 100644
--- a/res/values-en-rXC/config.xml
+++ b/res/values-en-rXC/config.xml
@@ -2,9 +2,9 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
   <string-array name="persist_apns_for_plmn">
-    <item msgid="6413072509259000954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎20404‎‏‎‎‏‎"</item>
-    <item msgid="5639159280778239123">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎310004‎‏‎‎‏‎"</item>
-    <item msgid="3860605521380788028">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎310120‎‏‎‎‏‎"</item>
-    <item msgid="537693705785480198">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‎‎311480‎‏‎‎‏‎"</item>
+    <item msgid="6413072509259000954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎20404‎‏‎‎‏‎"</item>
+    <item msgid="5639159280778239123">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎310004‎‏‎‎‏‎"</item>
+    <item msgid="3860605521380788028">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎‎310120‎‏‎‎‏‎"</item>
+    <item msgid="537693705785480198">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‎‎311480‎‏‎‎‏‎"</item>
   </string-array>
 </resources>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index 22950f7..e40d9ab 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -16,6 +16,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" product="tablet" msgid="9194799012395299737">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‏‎‎‏‎Mobile Network Configuration‎‏‎‎‏‎"</string>
-    <string name="app_label" product="default" msgid="8338087656149558019">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‎Phone and Messaging Storage‎‏‎‎‏‎"</string>
+    <string name="app_label" product="tablet" msgid="9194799012395299737">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‏‎‎‏‎Mobile Network Configuration‎‏‎‎‏‎"</string>
+    <string name="app_label" product="default" msgid="8338087656149558019">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‎Phone and Messaging Storage‎‏‎‎‏‎"</string>
 </resources>
diff --git a/res/values-or/config.xml b/res/values-or/config.xml
new file mode 100644
index 0000000..99877a6
--- /dev/null
+++ b/res/values-or/config.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string-array name="persist_apns_for_plmn">
+    <item msgid="6413072509259000954">"20404"</item>
+    <item msgid="5639159280778239123">"310004"</item>
+    <item msgid="3860605521380788028">"310120"</item>
+    <item msgid="537693705785480198">"311480"</item>
+  </string-array>
+</resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
new file mode 100644
index 0000000..b004c4f
--- /dev/null
+++ b/res/values-or/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2008 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_label" product="tablet" msgid="9194799012395299737">"ମୋବାଇଲ୍ ନେଟ୍‌ୱର୍କ କନଫିଗରେଶନ୍"</string>
+    <string name="app_label" product="default" msgid="8338087656149558019">"ଫୋନ୍ ଓ ମେସେଜିଙ୍ଗ ଷ୍ଟୋରେଜ୍"</string>
+</resources>
diff --git a/src/com/android/providers/telephony/CarrierIdProvider.java b/src/com/android/providers/telephony/CarrierIdProvider.java
new file mode 100644
index 0000000..1c2e5e5
--- /dev/null
+++ b/src/com/android/providers/telephony/CarrierIdProvider.java
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.providers.telephony;
+
+import android.content.ContentProvider;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.UriMatcher;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.Telephony.CarrierId;
+import android.telephony.SubscriptionManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.SubscriptionController;
+import com.android.internal.telephony.nano.CarrierIdProto;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import libcore.io.IoUtils;
+
+/**
+ * This class provides the ability to query the Carrier Identification databases
+ * (A.K.A. cid) which is stored in a SQLite database.
+ *
+ * Each row in carrier identification db consists of matching rule (e.g., MCCMNC, GID1, GID2, PLMN)
+ * and its matched carrier id & carrier name. Each carrier either MNO or MVNO could be
+ * identified by multiple matching rules but is assigned with a unique ID (cid).
+ *
+ *
+ * This class provides the ability to retrieve the cid of the current subscription.
+ * This is done atomically through a query.
+ *
+ * This class also provides a way to update carrier identifying attributes of an existing entry.
+ * Insert entries for new carriers or an existing carrier.
+ */
+public class CarrierIdProvider extends ContentProvider {
+
+    private static final boolean VDBG = false; // STOPSHIP if true
+    private static final String TAG = CarrierIdProvider.class.getSimpleName();
+
+    private static final String DATABASE_NAME = "carrierIdentification.db";
+    private static final int DATABASE_VERSION = 3;
+
+    private static final String ASSETS_PB_FILE = "carrier_list.pb";
+    private static final String VERSION_KEY = "version";
+    private static final String OTA_UPDATED_PB_PATH = "misc/carrierid/" + ASSETS_PB_FILE;
+    private static final String PREF_FILE = CarrierIdProvider.class.getSimpleName();
+
+    private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+    private static final int URL_ALL                = 1;
+    private static final int URL_ALL_UPDATE_FROM_PB = 2;
+    private static final int URL_ALL_GET_VERSION    = 3;
+
+    /**
+     * index 0: {@link CarrierId.All#MCCMNC}
+     */
+    private static final int MCCMNC_INDEX                = 0;
+    /**
+     * index 1: {@link CarrierId.All#IMSI_PREFIX_XPATTERN}
+     */
+    private static final int IMSI_PREFIX_INDEX           = 1;
+    /**
+     * index 2: {@link CarrierId.All#GID1}
+     */
+    private static final int GID1_INDEX                  = 2;
+    /**
+     * index 3: {@link CarrierId.All#GID2}
+     */
+    private static final int GID2_INDEX                  = 3;
+    /**
+     * index 4: {@link CarrierId.All#PLMN}
+     */
+    private static final int PLMN_INDEX                  = 4;
+    /**
+     * index 5: {@link CarrierId.All#SPN}
+     */
+    private static final int SPN_INDEX                   = 5;
+    /**
+     * index 6: {@link CarrierId.All#APN}
+     */
+    private static final int APN_INDEX                   = 6;
+    /**
+    * index 7: {@link CarrierId.All#ICCID_PREFIX}
+    */
+    private static final int ICCID_PREFIX_INDEX          = 7;
+    /**
+     * ending index of carrier attribute list.
+     */
+    private static final int CARRIER_ATTR_END_IDX        = ICCID_PREFIX_INDEX;
+    /**
+     * The authority string for the CarrierIdProvider
+     */
+    @VisibleForTesting
+    public static final String AUTHORITY = "carrier_id";
+
+    public static final String CARRIER_ID_TABLE = "carrier_id";
+
+    private static final List<String> CARRIERS_ID_UNIQUE_FIELDS = new ArrayList<>(Arrays.asList(
+            CarrierId.All.MCCMNC,
+            CarrierId.All.GID1,
+            CarrierId.All.GID2,
+            CarrierId.All.PLMN,
+            CarrierId.All.IMSI_PREFIX_XPATTERN,
+            CarrierId.All.SPN,
+            CarrierId.All.APN,
+            CarrierId.All.ICCID_PREFIX));
+
+    private CarrierIdDatabaseHelper mDbHelper;
+
+    /**
+     * Stores carrier id information for the current active subscriptions.
+     * Key is the active subId and entryValue is a pair of carrier id(int) and Carrier Name(String).
+     */
+    private final Map<Integer, Pair<Integer, String>> mCurrentSubscriptionMap =
+            new ConcurrentHashMap<>();
+
+    @VisibleForTesting
+    public static String getStringForCarrierIdTableCreation(String tableName) {
+        return "CREATE TABLE " + tableName
+                + "(_id INTEGER PRIMARY KEY,"
+                + CarrierId.All.MCCMNC + " TEXT NOT NULL,"
+                + CarrierId.All.GID1 + " TEXT,"
+                + CarrierId.All.GID2 + " TEXT,"
+                + CarrierId.All.PLMN + " TEXT,"
+                + CarrierId.All.IMSI_PREFIX_XPATTERN + " TEXT,"
+                + CarrierId.All.SPN + " TEXT,"
+                + CarrierId.All.APN + " TEXT,"
+                + CarrierId.All.ICCID_PREFIX + " TEXT,"
+                + CarrierId.CARRIER_NAME + " TEXT,"
+                + CarrierId.CARRIER_ID + " INTEGER DEFAULT -1,"
+                + "UNIQUE (" + TextUtils.join(", ", CARRIERS_ID_UNIQUE_FIELDS) + "));";
+    }
+
+    @VisibleForTesting
+    public static String getStringForIndexCreation(String tableName) {
+        return "CREATE INDEX IF NOT EXISTS mccmncIndex ON " + tableName + " ("
+                + CarrierId.All.MCCMNC + ");";
+    }
+
+    @Override
+    public boolean onCreate() {
+        Log.d(TAG, "onCreate");
+        mDbHelper = new CarrierIdDatabaseHelper(getContext());
+        mDbHelper.getReadableDatabase();
+        s_urlMatcher.addURI(AUTHORITY, "all", URL_ALL);
+        s_urlMatcher.addURI(AUTHORITY, "all/update_db", URL_ALL_UPDATE_FROM_PB);
+        s_urlMatcher.addURI(AUTHORITY, "all/get_version", URL_ALL_GET_VERSION);
+        updateDatabaseFromPb(mDbHelper.getWritableDatabase());
+        return true;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        Log.d(TAG, "getType");
+        return null;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projectionIn, String selection,
+                        String[] selectionArgs, String sortOrder) {
+        if (VDBG) {
+            Log.d(TAG, "query:"
+                    + " uri=" + uri
+                    + " values=" + Arrays.toString(projectionIn)
+                    + " selection=" + selection
+                    + " selectionArgs=" + Arrays.toString(selectionArgs));
+        }
+
+        final int match = s_urlMatcher.match(uri);
+        switch (match) {
+            case URL_ALL_GET_VERSION:
+                checkReadPermission();
+                final MatrixCursor cursor = new MatrixCursor(new String[] {VERSION_KEY});
+                cursor.addRow(new Object[] {getAppliedVersion()});
+                return cursor;
+            case URL_ALL:
+                checkReadPermission();
+                SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+                qb.setTables(CARRIER_ID_TABLE);
+
+                SQLiteDatabase db = getReadableDatabase();
+                return qb.query(db, projectionIn, selection, selectionArgs, null, null, sortOrder);
+            default:
+                return queryCarrierIdForCurrentSubscription(uri, projectionIn);
+        }
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        checkWritePermission();
+        final int match = s_urlMatcher.match(uri);
+        switch (match) {
+            case URL_ALL:
+                final long row = getWritableDatabase().insertOrThrow(CARRIER_ID_TABLE, null,
+                        values);
+                if (row > 0) {
+                    final Uri newUri = ContentUris.withAppendedId(
+                            CarrierId.All.CONTENT_URI, row);
+                    getContext().getContentResolver().notifyChange(
+                            CarrierId.All.CONTENT_URI, null);
+                    return newUri;
+                }
+                return null;
+            default:
+                throw new IllegalArgumentException("Cannot insert that URL: " + uri);
+        }
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        checkWritePermission();
+        if (VDBG) {
+            Log.d(TAG, "delete:"
+                    + " uri=" + uri
+                    + " selection={" + selection + "}"
+                    + " selection=" + selection
+                    + " selectionArgs=" + Arrays.toString(selectionArgs));
+        }
+        final int match = s_urlMatcher.match(uri);
+        switch (match) {
+            case URL_ALL:
+                final int count = getWritableDatabase().delete(CARRIER_ID_TABLE, selection,
+                        selectionArgs);
+                Log.d(TAG, "  delete.count=" + count);
+                if (count > 0) {
+                    getContext().getContentResolver().notifyChange(
+                            CarrierId.All.CONTENT_URI, null);
+                }
+                return count;
+            default:
+                throw new IllegalArgumentException("Cannot delete that URL: " + uri);
+        }
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        checkWritePermission();
+        if (VDBG) {
+            Log.d(TAG, "update:"
+                    + " uri=" + uri
+                    + " values={" + values + "}"
+                    + " selection=" + selection
+                    + " selectionArgs=" + Arrays.toString(selectionArgs));
+        }
+
+        final int match = s_urlMatcher.match(uri);
+        switch (match) {
+            case URL_ALL_UPDATE_FROM_PB:
+                return updateDatabaseFromPb(getWritableDatabase());
+            case URL_ALL:
+                final int count = getWritableDatabase().update(CARRIER_ID_TABLE, values, selection,
+                        selectionArgs);
+                Log.d(TAG, "  update.count=" + count);
+                if (count > 0) {
+                    getContext().getContentResolver().notifyChange(CarrierId.All.CONTENT_URI, null);
+                }
+                return count;
+            default:
+                return updateCarrierIdForCurrentSubscription(uri, values);
+
+        }
+    }
+
+    /**
+     * These methods can be overridden in a subclass for testing CarrierIdProvider using an
+     * in-memory database.
+     */
+    SQLiteDatabase getReadableDatabase() {
+        return mDbHelper.getReadableDatabase();
+    }
+    SQLiteDatabase getWritableDatabase() {
+        return mDbHelper.getWritableDatabase();
+    }
+
+    private class CarrierIdDatabaseHelper extends SQLiteOpenHelper {
+        private final String TAG = CarrierIdDatabaseHelper.class.getSimpleName();
+
+        /**
+         * CarrierIdDatabaseHelper carrier identification database helper class.
+         * @param context of the user.
+         */
+        public CarrierIdDatabaseHelper(Context context) {
+            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+            Log.d(TAG, "onCreate");
+            db.execSQL(getStringForCarrierIdTableCreation(CARRIER_ID_TABLE));
+            db.execSQL(getStringForIndexCreation(CARRIER_ID_TABLE));
+        }
+
+        public void createCarrierTable(SQLiteDatabase db) {
+            db.execSQL(getStringForCarrierIdTableCreation(CARRIER_ID_TABLE));
+            db.execSQL(getStringForIndexCreation(CARRIER_ID_TABLE));
+        }
+
+        public void dropCarrierTable(SQLiteDatabase db) {
+            db.execSQL("DROP TABLE IF EXISTS " + CARRIER_ID_TABLE + ";");
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            Log.d(TAG, "dbh.onUpgrade:+ db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
+            if (oldVersion < DATABASE_VERSION) {
+                dropCarrierTable(db);
+                createCarrierTable(db);
+            }
+        }
+    }
+
+    /**
+     * Parse and persist pb file as database default values.
+     * Use version number to detect file update.
+     * Update database with data from assets or ota only if version jumps.
+     */
+    private int updateDatabaseFromPb(SQLiteDatabase db) {
+        Log.d(TAG, "update database from pb file");
+        int rows = 0;
+        CarrierIdProto.CarrierList carrierList = getUpdateCarrierList();
+        // No update is needed
+        if (carrierList == null) return rows;
+
+        ContentValues cv;
+        List<ContentValues> cvs;
+        try {
+            // Batch all insertions in a single transaction to improve efficiency.
+            db.beginTransaction();
+            db.delete(CARRIER_ID_TABLE, null, null);
+            for (CarrierIdProto.CarrierId id : carrierList.carrierId) {
+                for (CarrierIdProto.CarrierAttribute attr : id.carrierAttribute) {
+                    cv = new ContentValues();
+                    cv.put(CarrierId.CARRIER_ID, id.canonicalId);
+                    cv.put(CarrierId.CARRIER_NAME, id.carrierName);
+                    cvs = new ArrayList<>();
+                    convertCarrierAttrToContentValues(cv, cvs, attr, 0);
+                    for (ContentValues contentVal : cvs) {
+                        // When a constraint violation occurs, the row that contains the violation
+                        // is not inserted. But the command continues executing normally.
+                        if (db.insertWithOnConflict(CARRIER_ID_TABLE, null, contentVal,
+                                SQLiteDatabase.CONFLICT_IGNORE) > 0) {
+                            rows++;
+                        } else {
+                            Log.e(TAG, "updateDatabaseFromPB insertion failure, row: "
+                                    + rows + "carrier id: " + id.canonicalId);
+                            // TODO metrics
+                        }
+                    }
+                }
+            }
+            Log.d(TAG, "update database from pb. inserted rows = " + rows);
+            if (rows > 0) {
+                // Notify listener of DB change
+                getContext().getContentResolver().notifyChange(CarrierId.All.CONTENT_URI, null);
+            }
+            setAppliedVersion(carrierList.version);
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+        return rows;
+    }
+
+    /**
+     * Recursively loop through carrier attribute list to get all combinations.
+     */
+    private void convertCarrierAttrToContentValues(ContentValues cv, List<ContentValues> cvs,
+            CarrierIdProto.CarrierAttribute attr, int index) {
+        if (index > CARRIER_ATTR_END_IDX) {
+            cvs.add(new ContentValues(cv));
+            return;
+        }
+        boolean found = false;
+        switch (index) {
+            case MCCMNC_INDEX:
+                for (String str : attr.mccmncTuple) {
+                    cv.put(CarrierId.All.MCCMNC, str);
+                    convertCarrierAttrToContentValues(cv, cvs, attr, index + 1);
+                    cv.remove(CarrierId.All.MCCMNC);
+                    found = true;
+                }
+                break;
+            case IMSI_PREFIX_INDEX:
+                for (String str : attr.imsiPrefixXpattern) {
+                    cv.put(CarrierId.All.IMSI_PREFIX_XPATTERN, str);
+                    convertCarrierAttrToContentValues(cv, cvs, attr, index + 1);
+                    cv.remove(CarrierId.All.IMSI_PREFIX_XPATTERN);
+                    found = true;
+                }
+                break;
+            case GID1_INDEX:
+                for (String str : attr.gid1) {
+                    cv.put(CarrierId.All.GID1, str);
+                    convertCarrierAttrToContentValues(cv, cvs, attr, index + 1);
+                    cv.remove(CarrierId.All.GID1);
+                    found = true;
+                }
+                break;
+            case GID2_INDEX:
+                for (String str : attr.gid2) {
+                    cv.put(CarrierId.All.GID2, str);
+                    convertCarrierAttrToContentValues(cv, cvs, attr, index + 1);
+                    cv.remove(CarrierId.All.GID2);
+                    found = true;
+                }
+                break;
+            case PLMN_INDEX:
+                for (String str : attr.plmn) {
+                    cv.put(CarrierId.All.PLMN, str);
+                    convertCarrierAttrToContentValues(cv, cvs, attr, index + 1);
+                    cv.remove(CarrierId.All.PLMN);
+                    found = true;
+                }
+                break;
+            case SPN_INDEX:
+                for (String str : attr.spn) {
+                    cv.put(CarrierId.All.SPN, str);
+                    convertCarrierAttrToContentValues(cv, cvs, attr, index + 1);
+                    cv.remove(CarrierId.All.SPN);
+                    found = true;
+                }
+                break;
+            case APN_INDEX:
+                for (String str : attr.preferredApn) {
+                    cv.put(CarrierId.All.APN, str);
+                    convertCarrierAttrToContentValues(cv, cvs, attr, index + 1);
+                    cv.remove(CarrierId.All.APN);
+                    found = true;
+                }
+                break;
+            case ICCID_PREFIX_INDEX:
+                for (String str : attr.iccidPrefix) {
+                    cv.put(CarrierId.All.ICCID_PREFIX, str);
+                    convertCarrierAttrToContentValues(cv, cvs, attr, index + 1);
+                    cv.remove(CarrierId.All.ICCID_PREFIX);
+                    found = true;
+                }
+                break;
+            default:
+                Log.e(TAG, "unsupported index: " + index);
+                break;
+        }
+        // if attribute at index is empty, move forward to the next attribute
+        if (!found) {
+            convertCarrierAttrToContentValues(cv, cvs, attr, index + 1);
+        }
+    }
+
+    /**
+     * Return the update carrierList.
+     * Get the latest version from the last applied, assets and ota file. if the latest version
+     * is newer than the last applied, update is required. Otherwise no update is required and
+     * the returned carrierList will be null.
+     */
+    private CarrierIdProto.CarrierList getUpdateCarrierList() {
+        int version = getAppliedVersion();
+        CarrierIdProto.CarrierList carrierList = null;
+        CarrierIdProto.CarrierList assets = null;
+        CarrierIdProto.CarrierList ota = null;
+        InputStream is = null;
+
+        try {
+            is = getContext().getAssets().open(ASSETS_PB_FILE);
+            assets = CarrierIdProto.CarrierList.parseFrom(readInputStreamToByteArray(is));
+        } catch (IOException ex) {
+            Log.e(TAG, "read carrier list from assets pb failure: " + ex);
+        } finally {
+            IoUtils.closeQuietly(is);
+        }
+        try {
+            is = new FileInputStream(new File(Environment.getDataDirectory(), OTA_UPDATED_PB_PATH));
+            ota = CarrierIdProto.CarrierList.parseFrom(readInputStreamToByteArray(is));
+        } catch (IOException ex) {
+            Log.e(TAG, "read carrier list from ota pb failure: " + ex);
+        } finally {
+            IoUtils.closeQuietly(is);
+        }
+
+        // compare version
+        if (assets != null && assets.version > version) {
+            carrierList = assets;
+            version = assets.version;
+        }
+        if (ota != null && ota.version > version) {
+            carrierList = ota;
+            version = ota.version;
+        }
+        Log.d(TAG, "latest version: " + version + " need update: " + (carrierList != null));
+        return carrierList;
+    }
+
+    private int getAppliedVersion() {
+        final SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE,
+                Context.MODE_PRIVATE);
+        return sp.getInt(VERSION_KEY, -1);
+    }
+
+    private void setAppliedVersion(int version) {
+        final SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE,
+                Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = sp.edit();
+        editor.putInt(VERSION_KEY, version);
+        editor.apply();
+    }
+
+    /**
+     * Util function to convert inputStream to byte array before parsing proto data.
+     */
+    private static byte[] readInputStreamToByteArray(InputStream inputStream) throws IOException {
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        int nRead;
+        int size = 16 * 1024; // Read 16k chunks
+        byte[] data = new byte[size];
+        while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
+            buffer.write(data, 0, nRead);
+        }
+        buffer.flush();
+        return buffer.toByteArray();
+    }
+
+    private int updateCarrierIdForCurrentSubscription(Uri uri, ContentValues cv) {
+        // Parse the subId
+        int subId;
+        try {
+            subId = Integer.parseInt(uri.getLastPathSegment());
+        } catch (NumberFormatException e) {
+            throw new IllegalArgumentException("invalid subid in provided uri " + uri);
+        }
+        Log.d(TAG, "updateCarrierIdForSubId: " + subId);
+
+        // Handle DEFAULT_SUBSCRIPTION_ID
+        if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+            subId = SubscriptionController.getInstance().getDefaultSubId();
+        }
+
+        if (!SubscriptionController.getInstance().isActiveSubId(subId)) {
+            // Remove absent subId from the currentSubscriptionMap.
+            final List activeSubscriptions = Arrays.asList(SubscriptionController.getInstance()
+                    .getActiveSubIdList());
+            int count = 0;
+            for (int subscription : mCurrentSubscriptionMap.keySet()) {
+                if (!activeSubscriptions.contains(subscription)) {
+                    count++;
+                    Log.d(TAG, "updateCarrierIdForSubId: " + subscription);
+                    mCurrentSubscriptionMap.remove(subscription);
+                    getContext().getContentResolver().notifyChange(CarrierId.CONTENT_URI, null);
+                }
+            }
+            return count;
+        } else {
+            mCurrentSubscriptionMap.put(subId,
+                    new Pair(cv.getAsInteger(CarrierId.CARRIER_ID),
+                    cv.getAsString(CarrierId.CARRIER_NAME)));
+            getContext().getContentResolver().notifyChange(CarrierId.CONTENT_URI, null);
+            return 1;
+        }
+    }
+
+    private Cursor queryCarrierIdForCurrentSubscription(Uri uri, String[] projectionIn) {
+        // Parse the subId, using the default subId if subId is not provided
+        int subId = SubscriptionController.getInstance().getDefaultSubId();
+        if (!TextUtils.isEmpty(uri.getLastPathSegment())) {
+            try {
+                subId = Integer.parseInt(uri.getLastPathSegment());
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException("invalid subid in provided uri" + uri);
+            }
+        }
+        Log.d(TAG, "queryCarrierIdForSubId: " + subId);
+
+        // Handle DEFAULT_SUBSCRIPTION_ID
+        if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+            subId = SubscriptionController.getInstance().getDefaultSubId();
+        }
+
+        if (!mCurrentSubscriptionMap.containsKey(subId)) {
+            // Return an empty cursor if subId is not belonging to current subscriptions.
+            return new MatrixCursor(projectionIn, 0);
+        }
+        final MatrixCursor c = new MatrixCursor(projectionIn, 1);
+        final MatrixCursor.RowBuilder row = c.newRow();
+        for (int i = 0; i < c.getColumnCount(); i++) {
+            final String columnName = c.getColumnName(i);
+            if (CarrierId.CARRIER_ID.equals(columnName)) {
+                row.add(mCurrentSubscriptionMap.get(subId).first);
+            } else if (CarrierId.CARRIER_NAME.equals(columnName)) {
+                row.add(mCurrentSubscriptionMap.get(subId).second);
+            } else {
+                throw new IllegalArgumentException("Invalid column " + projectionIn[i]);
+            }
+        }
+        return c;
+    }
+
+    private void checkReadPermission() {
+        int status = getContext().checkCallingOrSelfPermission(
+                "android.permission.READ_PRIVILEGED_PHONE_STATE");
+        if (status == PackageManager.PERMISSION_GRANTED) {
+            return;
+        }
+        throw new SecurityException("No permission to read CarrierId provider");
+    }
+
+    private void checkWritePermission() {
+        int status = getContext().checkCallingOrSelfPermission(
+                "android.permission.MODIFY_PHONE_STATE");
+        if (status == PackageManager.PERMISSION_GRANTED) {
+            return;
+        }
+        throw new SecurityException("No permission to write CarrierId provider");
+    }
+}
diff --git a/src/com/android/providers/telephony/CarrierProvider.java b/src/com/android/providers/telephony/CarrierProvider.java
index a4b6ea0..d359e06 100644
--- a/src/com/android/providers/telephony/CarrierProvider.java
+++ b/src/com/android/providers/telephony/CarrierProvider.java
@@ -82,7 +82,7 @@
                 null, values);
         if (row > 0) {
             Uri newUri = ContentUris.withAppendedId(CONTENT_URI, row);
-            getContext().getContentResolver().notifyChange(newUri, null);
+            getContext().getContentResolver().notifyChange(CONTENT_URI, null);
             return newUri;
         }
         return null;
@@ -115,6 +115,9 @@
         }
         final int count = getWritableDatabase().update(CarrierDatabaseHelper.CARRIER_KEY_TABLE,
                 values, selection, selectionArgs);
+        if (count > 0) {
+            getContext().getContentResolver().notifyChange(CONTENT_URI, null);
+        }
         Log.d(TAG, "  update.count=" + count);
         return count;
     }
diff --git a/src/com/android/providers/telephony/MmsProvider.java b/src/com/android/providers/telephony/MmsProvider.java
index 547b22e..30158c3 100644
--- a/src/com/android/providers/telephony/MmsProvider.java
+++ b/src/com/android/providers/telephony/MmsProvider.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.app.AppOpsManager;
 import android.content.ContentProvider;
+import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
@@ -38,6 +39,7 @@
 import android.provider.Telephony.CanonicalAddressesColumns;
 import android.provider.Telephony.Mms;
 import android.provider.Telephony.Mms.Addr;
+import android.provider.Telephony.Mms.Inbox;
 import android.provider.Telephony.Mms.Part;
 import android.provider.Telephony.Mms.Rate;
 import android.provider.Telephony.MmsSms;
@@ -360,6 +362,7 @@
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         ContentValues finalValues;
         Uri res = Mms.CONTENT_URI;
+        Uri caseSpecificUri = null;
         long rowId;
 
         if (table.equals(TABLE_PDU)) {
@@ -409,6 +412,11 @@
                 return null;
             }
 
+            // Notify change when an MMS is received.
+            if (msgBox == Mms.MESSAGE_BOX_INBOX) {
+                caseSpecificUri = ContentUris.withAppendedId(Mms.Inbox.CONTENT_URI, rowId);
+            }
+
             res = Uri.parse(res + "/" + rowId);
         } else if (table.equals(TABLE_ADDR)) {
             finalValues = new ContentValues(values);
@@ -584,7 +592,7 @@
         }
 
         if (notify) {
-            notifyChange(res);
+            notifyChange(res, caseSpecificUri);
         }
         return res;
     }
@@ -680,7 +688,7 @@
         }
 
         if ((deletedRows > 0) && notify) {
-            notifyChange(uri);
+            notifyChange(uri, null);
         }
         return deletedRows;
     }
@@ -856,7 +864,7 @@
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         int count = db.update(table, finalValues, finalSelection, selectionArgs);
         if (notify && (count > 0)) {
-            notifyChange(uri);
+            notifyChange(uri, null);
         }
         return count;
     }
@@ -973,11 +981,16 @@
         values.remove(Mms._ID);
     }
 
-    private void notifyChange(final Uri uri) {
+    private void notifyChange(final Uri uri, final Uri caseSpecificUri) {
         final Context context = getContext();
+        if (caseSpecificUri != null) {
+            context.getContentResolver().notifyChange(
+                caseSpecificUri, null, true, UserHandle.USER_ALL);
+        }
         context.getContentResolver().notifyChange(
                 MmsSms.CONTENT_URI, null, true, UserHandle.USER_ALL);
-        ProviderUtil.notifyIfNotDefaultSmsApp(uri, getCallingPackage(), context);
+        ProviderUtil.notifyIfNotDefaultSmsApp(caseSpecificUri == null ? uri : caseSpecificUri,
+                getCallingPackage(), context);
     }
 
     private final static String TAG = "MmsProvider";
diff --git a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
index 4b84fe5..1dc2106 100644
--- a/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
+++ b/src/com/android/providers/telephony/MmsSmsDatabaseHelper.java
@@ -21,11 +21,15 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.SharedPreferences;
 import android.database.Cursor;
+import android.database.DatabaseErrorHandler;
+import android.database.DefaultDatabaseErrorHandler;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.os.storage.StorageManager;
+import android.preference.PreferenceManager;
 import android.provider.BaseColumns;
 import android.provider.Telephony;
 import android.provider.Telephony.Mms;
@@ -35,11 +39,14 @@
 import android.provider.Telephony.MmsSms;
 import android.provider.Telephony.MmsSms.PendingMessages;
 import android.provider.Telephony.Sms;
+import android.provider.Telephony.Sms.Intents;
 import android.provider.Telephony.Threads;
 import android.telephony.SubscriptionManager;
 import android.util.Log;
+import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.PhoneFactory;
 import com.google.android.mms.pdu.EncodedStringValue;
 import com.google.android.mms.pdu.PduHeaders;
 
@@ -50,6 +57,7 @@
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * A {@link SQLiteOpenHelper} that handles DB management of SMS and MMS tables.
@@ -233,6 +241,7 @@
 
     private static MmsSmsDatabaseHelper sDeInstance = null;
     private static MmsSmsDatabaseHelper sCeInstance = null;
+    private static MmsSmsDatabaseErrorHandler sDbErrorHandler = null;
 
     private static final String[] BIND_ARGS_NONE = new String[0];
 
@@ -240,26 +249,74 @@
     private static boolean sFakeLowStorageTest = false;     // for testing only
 
     static final String DATABASE_NAME = "mmssms.db";
-    static final int DATABASE_VERSION = 66;
+    static final int DATABASE_VERSION = 67;
     private static final int IDLE_CONNECTION_TIMEOUT_MS = 30000;
 
     private final Context mContext;
     private LowStorageMonitor mLowStorageMonitor;
 
+    // SharedPref key used to check if initial create has been done (if onCreate has already been
+    // called once)
+    private static final String INITIAL_CREATE_DONE = "initial_create_done";
+    // cache for INITIAL_CREATE_DONE shared pref so access to it can be avoided when possible
+    private static AtomicBoolean sInitialCreateDone = new AtomicBoolean(false);
 
-    private MmsSmsDatabaseHelper(Context context) {
-        super(context, DATABASE_NAME, null, DATABASE_VERSION);
+    /**
+     * The primary purpose of this DatabaseErrorHandler is to broadcast an intent on corruption and
+     * print a Slog.wtf so database corruption can be caught earlier.
+     */
+    private static class MmsSmsDatabaseErrorHandler implements DatabaseErrorHandler {
+        private DefaultDatabaseErrorHandler mDefaultDatabaseErrorHandler
+                = new DefaultDatabaseErrorHandler();
+        private Context mContext;
+
+        MmsSmsDatabaseErrorHandler(Context context) {
+            mContext = context;
+        }
+
+        @Override
+        public void onCorruption(SQLiteDatabase dbObj) {
+            String logMsg = "Corruption reported by sqlite on database: " + dbObj.getPath();
+            localLogWtf(logMsg);
+            sendDbLostIntent(mContext, true);
+            // Let the default error handler take other actions
+            mDefaultDatabaseErrorHandler.onCorruption(dbObj);
+        }
+    }
+
+    private MmsSmsDatabaseHelper(Context context, MmsSmsDatabaseErrorHandler dbErrorHandler) {
+        super(context, DATABASE_NAME, null, DATABASE_VERSION, dbErrorHandler);
         mContext = context;
         // Memory optimization - close idle connections after 30s of inactivity
         setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
+        try {
+            PhoneFactory.addLocalLog(TAG, 100);
+        } catch (IllegalArgumentException e) {
+            // ignore
+        }
     }
 
+    private static synchronized MmsSmsDatabaseErrorHandler getDbErrorHandler(Context context) {
+        if (sDbErrorHandler == null) {
+            sDbErrorHandler = new MmsSmsDatabaseErrorHandler(context);
+        }
+        return sDbErrorHandler;
+    }
+
+    private static void sendDbLostIntent(Context context, boolean isCorrupted) {
+        // Broadcast ACTION_SMS_MMS_DB_LOST
+        Intent intent = new Intent(Sms.Intents.ACTION_SMS_MMS_DB_LOST);
+        intent.putExtra(Sms.Intents.EXTRA_IS_CORRUPTED, isCorrupted);
+        intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+        context.sendBroadcast(intent, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+    }
     /**
      * Returns a singleton helper for the combined MMS and SMS database in device encrypted storage.
      */
     /* package */ static synchronized MmsSmsDatabaseHelper getInstanceForDe(Context context) {
         if (sDeInstance == null) {
-            sDeInstance = new MmsSmsDatabaseHelper(ProviderUtil.getDeviceEncryptedContext(context));
+            Context deContext = ProviderUtil.getDeviceEncryptedContext(context);
+            sDeInstance = new MmsSmsDatabaseHelper(deContext, getDbErrorHandler(deContext));
         }
         return sDeInstance;
     }
@@ -271,8 +328,8 @@
     /* package */ static synchronized MmsSmsDatabaseHelper getInstanceForCe(Context context) {
         if (sCeInstance == null) {
             if (StorageManager.isFileEncryptedNativeOrEmulated()) {
-                sCeInstance = new MmsSmsDatabaseHelper(
-                    ProviderUtil.getCredentialEncryptedContext(context));
+                Context ceContext = ProviderUtil.getCredentialEncryptedContext(context);
+                sCeInstance = new MmsSmsDatabaseHelper(ceContext, getDbErrorHandler(ceContext));
             } else {
                 sCeInstance = getInstanceForDe(context);
             }
@@ -463,6 +520,28 @@
 
     @Override
     public void onCreate(SQLiteDatabase db) {
+        localLog("onCreate: Creating all SMS-MMS tables.");
+        // if FBE is not supported, or if this onCreate is for CE partition database
+        if (!StorageManager.isFileEncryptedNativeOrEmulated()
+                || mContext.isCredentialProtectedStorage()) {
+            localLog("onCreate: broadcasting ACTION_SMS_MMS_DB_CREATED");
+            // Broadcast ACTION_SMS_MMS_DB_CREATED
+            Intent intent = new Intent(Sms.Intents.ACTION_SMS_MMS_DB_CREATED);
+            intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+
+            if (isInitialCreateDone()) {
+                // this onCreate is called after onCreate was called once initially. The db file
+                // disappeared mysteriously?
+                localLogWtf("onCreate: was already called once earlier");
+                intent.putExtra(Intents.EXTRA_IS_INITIAL_CREATE, false);
+                sendDbLostIntent(mContext, false);
+            } else {
+                setInitialCreateDone();
+                intent.putExtra(Intents.EXTRA_IS_INITIAL_CREATE, true);
+            }
+
+            mContext.sendBroadcast(intent, android.Manifest.permission.READ_SMS);
+        }
         createMmsTables(db);
         createSmsTables(db);
         createCommonTables(db);
@@ -472,6 +551,30 @@
         createIndices(db);
     }
 
+    private static void localLog(String logMsg) {
+        Log.d(TAG, logMsg);
+        PhoneFactory.localLog(TAG, logMsg);
+    }
+
+    private static void localLogWtf(String logMsg) {
+        Slog.wtf(TAG, logMsg);
+        PhoneFactory.localLog(TAG, logMsg);
+    }
+
+    private boolean isInitialCreateDone() {
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+        return sp.getBoolean(INITIAL_CREATE_DONE, false);
+    }
+
+    private void setInitialCreateDone() {
+        if (!sInitialCreateDone.getAndSet(true)) {
+            SharedPreferences.Editor editor
+                    = PreferenceManager.getDefaultSharedPreferences(mContext).edit();
+            editor.putBoolean(INITIAL_CREATE_DONE, true);
+            editor.commit();
+        }
+    }
+
     // When upgrading the database we need to populate the words
     // table with the rows out of sms and part.
     private void populateWordsTable(SQLiteDatabase db) {
@@ -567,6 +670,8 @@
     private void createIndices(SQLiteDatabase db) {
         createThreadIdIndex(db);
         createThreadIdDateIndex(db);
+        createPartMidIndex(db);
+        createAddrMsgIdIndex(db);
     }
 
     private void createThreadIdIndex(SQLiteDatabase db) {
@@ -587,6 +692,22 @@
         }
     }
 
+    private void createPartMidIndex(SQLiteDatabase db) {
+        try {
+            db.execSQL("CREATE INDEX IF NOT EXISTS partMidIndex ON part (mid)");
+        } catch (Exception ex) {
+            Log.e(TAG, "got exception creating indices: " + ex.toString());
+        }
+    }
+
+    private void createAddrMsgIdIndex(SQLiteDatabase db) {
+        try {
+            db.execSQL("CREATE INDEX IF NOT EXISTS addrMsgIdIndex ON addr (msg_id)");
+        } catch (Exception ex) {
+            Log.e(TAG, "got exception creating indices: " + ex.toString());
+        }
+    }
+
     private void createMmsTables(SQLiteDatabase db) {
         // N.B.: Whenever the columns here are changed, the columns in
         // {@ref MmsSmsProvider} must be changed to match.
@@ -889,30 +1010,32 @@
             "content_url TEXT," +
             "offset INTEGER);";
 
+    /**
+     * This table is used by the SMS dispatcher to hold
+     * incomplete partial messages until all the parts arrive.
+     */
+    @VisibleForTesting
+    public static String CREATE_RAW_TABLE_STRING =
+            "CREATE TABLE raw (" +
+            "_id INTEGER PRIMARY KEY," +
+            "date INTEGER," +
+            "reference_number INTEGER," + // one per full message
+            "count INTEGER," + // the number of parts
+            "sequence INTEGER," + // the part number of this message
+            "destination_port INTEGER," +
+            "address TEXT," +
+            "sub_id INTEGER DEFAULT " + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " +
+            "pdu TEXT," + // the raw PDU for this part
+            "deleted INTEGER DEFAULT 0," + // bool to indicate if row is deleted
+            "message_body TEXT," + // message body
+            "display_originating_addr TEXT);";
+    // email address if from an email gateway, otherwise same as address
     private void createSmsTables(SQLiteDatabase db) {
         // N.B.: Whenever the columns here are changed, the columns in
         // {@ref MmsSmsProvider} must be changed to match.
         db.execSQL(CREATE_SMS_TABLE_STRING);
 
-        /**
-         * This table is used by the SMS dispatcher to hold
-         * incomplete partial messages until all the parts arrive.
-         */
-        db.execSQL("CREATE TABLE raw (" +
-                   "_id INTEGER PRIMARY KEY," +
-                   "date INTEGER," +
-                   "reference_number INTEGER," + // one per full message
-                   "count INTEGER," + // the number of parts
-                   "sequence INTEGER," + // the part number of this message
-                   "destination_port INTEGER," +
-                   "address TEXT," +
-                   "sub_id INTEGER DEFAULT " + SubscriptionManager.INVALID_SUBSCRIPTION_ID + ", " +
-                   "pdu TEXT," + // the raw PDU for this part
-                   "deleted INTEGER DEFAULT 0," + // bool to indicate if row is deleted
-                   "message_body TEXT," + // message body
-                   "display_originating_addr TEXT);"
-                   // email address if from an email gateway, otherwise same as address
-        );
+        db.execSQL(CREATE_RAW_TABLE_STRING);
 
         db.execSQL(CREATE_ATTACHMENTS_TABLE_STRING);
 
@@ -1486,11 +1609,28 @@
             } finally {
                 db.endTransaction();
             }
-
+            // fall through
+        case 66:
+            if (currentVersion <= 66) {
+                return;
+            }
+            db.beginTransaction();
+            try {
+                createPartMidIndex(db);
+                createAddrMsgIdIndex(db);
+                db.setTransactionSuccessful();
+            } catch (Throwable ex) {
+                Log.e(TAG, ex.getMessage(), ex);
+                break; // force to destroy all old data;
+            } finally {
+                db.endTransaction();
+            }
             return;
         }
 
         Log.e(TAG, "Destroying all old data.");
+        localLog("onUpgrade: Calling dropAll() and onCreate(). Upgrading database"
+                + " from version " + oldVersion + " to " + currentVersion + "failed.");
         dropAll(db);
         onCreate(db);
     }
@@ -1499,6 +1639,7 @@
         // Clean the database out in order to start over from scratch.
         // We don't need to drop our triggers here because SQLite automatically
         // drops a trigger when its attached database is dropped.
+        localLog("****DROPPING ALL SMS-MMS TABLES****");
         db.execSQL("DROP TABLE IF EXISTS canonical_addresses");
         db.execSQL("DROP TABLE IF EXISTS threads");
         db.execSQL("DROP TABLE IF EXISTS " + MmsSmsProvider.TABLE_PENDING_MSG);
@@ -1790,19 +1931,41 @@
     }
 
     @Override
+    public synchronized  SQLiteDatabase getReadableDatabase() {
+        SQLiteDatabase db = super.getWritableDatabase();
+
+        // getReadableDatabase gets or creates a database. So we know for sure that a database has
+        // already been created at this point.
+        if (mContext.isCredentialProtectedStorage()) {
+            setInitialCreateDone();
+        }
+
+        return db;
+    }
+
+    @Override
     public synchronized SQLiteDatabase getWritableDatabase() {
         SQLiteDatabase db = super.getWritableDatabase();
 
+        // getWritableDatabase gets or creates a database. So we know for sure that a database has
+        // already been created at this point.
+        if (mContext.isCredentialProtectedStorage()) {
+            setInitialCreateDone();
+        }
+
         if (!sTriedAutoIncrement) {
             sTriedAutoIncrement = true;
             boolean hasAutoIncrementThreads = hasAutoIncrement(db, MmsSmsProvider.TABLE_THREADS);
             boolean hasAutoIncrementAddresses = hasAutoIncrement(db, "canonical_addresses");
             boolean hasAutoIncrementPart = hasAutoIncrement(db, "part");
             boolean hasAutoIncrementPdu = hasAutoIncrement(db, "pdu");
-            Log.d(TAG, "[getWritableDatabase] hasAutoIncrementThreads: " + hasAutoIncrementThreads +
+            String logMsg = "[getWritableDatabase]" +
+                    " hasAutoIncrementThreads: " + hasAutoIncrementThreads +
                     " hasAutoIncrementAddresses: " + hasAutoIncrementAddresses +
                     " hasAutoIncrementPart: " + hasAutoIncrementPart +
-                    " hasAutoIncrementPdu: " + hasAutoIncrementPdu);
+                    " hasAutoIncrementPdu: " + hasAutoIncrementPdu;
+            Log.d(TAG, logMsg);
+            localLog(logMsg);
             boolean autoIncrementThreadsSuccess = true;
             boolean autoIncrementAddressesSuccess = true;
             boolean autoIncrementPartSuccess = true;
diff --git a/src/com/android/providers/telephony/ServiceStateProvider.java b/src/com/android/providers/telephony/ServiceStateProvider.java
index dcbcc6a..e589171 100644
--- a/src/com/android/providers/telephony/ServiceStateProvider.java
+++ b/src/com/android/providers/telephony/ServiceStateProvider.java
@@ -26,17 +26,13 @@
 import android.net.Uri;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.SubscriptionController;
 
 import java.lang.NumberFormatException;
 import java.util.HashMap;
-import java.util.Objects;
 
 import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionId;
 import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionIdAndField;
@@ -149,7 +145,7 @@
             newSS.setRilVoiceRadioTechnology(values.getAsInteger(RIL_VOICE_RADIO_TECHNOLOGY));
             newSS.setRilDataRadioTechnology(values.getAsInteger(RIL_DATA_RADIO_TECHNOLOGY));
             newSS.setCssIndicator(values.getAsInteger(CSS_INDICATOR));
-            newSS.setSystemAndNetworkId(values.getAsInteger(SYSTEM_ID),
+            newSS.setCdmaSystemAndNetworkId(values.getAsInteger(SYSTEM_ID),
                     values.getAsInteger(NETWORK_ID));
             newSS.setCdmaRoamingIndicator(values.getAsInteger(CDMA_ROAMING_INDICATOR));
             newSS.setCdmaDefaultRoamingIndicator(
@@ -232,8 +228,8 @@
             final int ril_voice_radio_technology = ss.getRilVoiceRadioTechnology();
             final int ril_data_radio_technology = ss.getRilDataRadioTechnology();
             final int css_indicator = ss.getCssIndicator();
-            final int network_id = ss.getNetworkId();
-            final int system_id = ss.getSystemId();
+            final int network_id = ss.getCdmaNetworkId();
+            final int system_id = ss.getCdmaSystemId();
             final int cdma_roaming_indicator = ss.getCdmaRoamingIndicator();
             final int cdma_default_roaming_indicator = ss.getCdmaDefaultRoamingIndicator();
             final int cdma_eri_icon_index = ss.getCdmaEriIconIndex();
diff --git a/src/com/android/providers/telephony/SmsProvider.java b/src/com/android/providers/telephony/SmsProvider.java
index 37a1044..2b40d7e 100644
--- a/src/com/android/providers/telephony/SmsProvider.java
+++ b/src/com/android/providers/telephony/SmsProvider.java
@@ -43,6 +43,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 
@@ -90,6 +92,8 @@
     @Override
     public boolean onCreate() {
         setAppOps(AppOpsManager.OP_READ_SMS, AppOpsManager.OP_WRITE_SMS);
+        // So we have two database files. One in de, one in ce. Here only "raw" table is in
+        // mDeOpenHelper, other tables are all in mCeOpenHelper.
         mDeOpenHelper = MmsSmsDatabaseHelper.getInstanceForDe(getContext());
         mCeOpenHelper = MmsSmsDatabaseHelper.getInstanceForCe(getContext());
         TelephonyBackupAgent.DeferredSmsMmsRestoreService.startIfFilesExist(getContext());
@@ -280,7 +284,8 @@
     }
 
     private SQLiteOpenHelper getDBOpenHelper(int match) {
-        if (match == SMS_RAW_MESSAGE) {
+        // Raw table is stored on de database. Other tables are stored in ce database.
+        if (match == SMS_RAW_MESSAGE || match == SMS_RAW_MESSAGE_PERMANENT_DELETE) {
             return mDeOpenHelper;
         }
         return mCeOpenHelper;
@@ -843,9 +848,12 @@
     }
 
     // Db open helper for tables stored in CE(Credential Encrypted) storage.
-    private SQLiteOpenHelper mCeOpenHelper;
-    // Db open helper for tables stored in DE(Device Encrypted) storage.
-    private SQLiteOpenHelper mDeOpenHelper;
+    @VisibleForTesting
+    public SQLiteOpenHelper mCeOpenHelper;
+    // Db open helper for tables stored in DE(Device Encrypted) storage. It's currently only used
+    // to store raw table.
+    @VisibleForTesting
+    public SQLiteOpenHelper mDeOpenHelper;
 
     private final static String TAG = "SmsProvider";
     private final static String VND_ANDROID_SMS = "vnd.android.cursor.item/sms";
diff --git a/src/com/android/providers/telephony/TelephonyProvider.java b/src/com/android/providers/telephony/TelephonyProvider.java
index 3869928..8ff9121 100644
--- a/src/com/android/providers/telephony/TelephonyProvider.java
+++ b/src/com/android/providers/telephony/TelephonyProvider.java
@@ -18,6 +18,7 @@
 package com.android.providers.telephony;
 
 import static android.provider.Telephony.Carriers.APN;
+import static android.provider.Telephony.Carriers.APN_SET_ID;
 import static android.provider.Telephony.Carriers.AUTH_TYPE;
 import static android.provider.Telephony.Carriers.BEARER;
 import static android.provider.Telephony.Carriers.BEARER_BITMASK;
@@ -27,6 +28,7 @@
 import static android.provider.Telephony.Carriers.CARRIER_ENABLED;
 import static android.provider.Telephony.Carriers.CONTENT_URI;
 import static android.provider.Telephony.Carriers.CURRENT;
+import static android.provider.Telephony.Carriers.DEFAULT_SORT_ORDER;
 import static android.provider.Telephony.Carriers.EDITED;
 import static android.provider.Telephony.Carriers.MAX_CONNS;
 import static android.provider.Telephony.Carriers.MAX_CONNS_TIME;
@@ -40,7 +42,12 @@
 import static android.provider.Telephony.Carriers.MVNO_MATCH_DATA;
 import static android.provider.Telephony.Carriers.MVNO_TYPE;
 import static android.provider.Telephony.Carriers.NAME;
+import static android.provider.Telephony.Carriers.NETWORK_TYPE_BITMASK;
+import static android.provider.Telephony.Carriers.NO_SET_SET;
 import static android.provider.Telephony.Carriers.NUMERIC;
+import static android.provider.Telephony.Carriers.OWNED_BY;
+import static android.provider.Telephony.Carriers.OWNED_BY_OTHERS;
+import static android.provider.Telephony.Carriers.OWNED_BY_DPC;
 import static android.provider.Telephony.Carriers.PASSWORD;
 import static android.provider.Telephony.Carriers.PORT;
 import static android.provider.Telephony.Carriers.PROFILE_ID;
@@ -73,6 +80,7 @@
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.database.Cursor;
+import android.database.MatrixCursor;
 import android.database.SQLException;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
@@ -83,6 +91,7 @@
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -99,6 +108,10 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.IApnSourceService;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.dataconnection.ApnSetting;
+import com.android.internal.telephony.uicc.IccRecords;
+import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -110,6 +123,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Consumer;
@@ -121,7 +135,7 @@
     private static final boolean DBG = true;
     private static final boolean VDBG = false; // STOPSHIP if true
 
-    private static final int DATABASE_VERSION = 21 << 16;
+    private static final int DATABASE_VERSION = 26 << 16;
     private static final int URL_UNKNOWN = 0;
     private static final int URL_TELEPHONY = 1;
     private static final int URL_CURRENT = 2;
@@ -138,11 +152,20 @@
     private static final int URL_SIMINFO_USING_SUBID = 13;
     private static final int URL_UPDATE_DB = 14;
     private static final int URL_DELETE = 15;
+    private static final int URL_DPC = 16;
+    private static final int URL_DPC_ID = 17;
+    private static final int URL_FILTERED = 18;
+    private static final int URL_FILTERED_ID = 19;
+    private static final int URL_ENFORCE_MANAGED = 20;
+    private static final int URL_PREFERAPNSET = 21;
+    private static final int URL_PREFERAPNSET_USING_SUBID = 22;
+
 
     private static final String TAG = "TelephonyProvider";
     private static final String CARRIERS_TABLE = "carriers";
     private static final String CARRIERS_TABLE_TMP = "carriers_tmp";
     private static final String SIMINFO_TABLE = "siminfo";
+    private static final String SIMINFO_TABLE_TMP = "siminfo_tmp";
 
     private static final String PREF_FILE_APN = "preferred-apn";
     private static final String COLUMN_APN_ID = "apn_id";
@@ -154,14 +177,20 @@
     private static final String BUILD_ID_FILE = "build-id";
     private static final String RO_BUILD_ID = "ro_build_id";
 
+    private static final String ENFORCED_FILE = "dpc-apn-enforced";
+    private static final String ENFORCED_KEY = "enforced";
+
     private static final String PREF_FILE = "telephonyprovider";
     private static final String APN_CONF_CHECKSUM = "apn_conf_checksum";
 
     private static final String PARTNER_APNS_PATH = "etc/apns-conf.xml";
     private static final String OEM_APNS_PATH = "telephony/apns-conf.xml";
-    private static final String OTA_UPDATED_APNS_PATH = "misc/apns-conf.xml";
+    private static final String OTA_UPDATED_APNS_PATH = "misc/apns/apns-conf.xml";
     private static final String OLD_APNS_PATH = "etc/old-apns-conf.xml";
 
+    private static final String DEFAULT_PROTOCOL = "IP";
+    private static final String DEFAULT_ROAMING_PROTOCOL = "IP";
+
     private static final UriMatcher s_urlMatcher = new UriMatcher(UriMatcher.NO_MATCH);
 
     private static final ContentValues s_currentNullMap;
@@ -185,37 +214,51 @@
             EDITED + "=" + CARRIER_DELETED_BUT_PRESENT_IN_XML;
     private static final String IS_NOT_CARRIER_DELETED_BUT_PRESENT_IN_XML =
             EDITED + "!=" + CARRIER_DELETED_BUT_PRESENT_IN_XML;
+    private static final String IS_OWNED_BY_DPC = OWNED_BY + "=" + OWNED_BY_DPC;
+    private static final String IS_NOT_OWNED_BY_DPC = OWNED_BY + "!=" + OWNED_BY_DPC;
+
+    private static final String ORDER_BY_SUB_ID =
+            SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + " ASC";
 
     private static final int INVALID_APN_ID = -1;
     private static final List<String> CARRIERS_UNIQUE_FIELDS = new ArrayList<String>();
+    private static final Map<String, String> CARRIERS_UNIQUE_FIELDS_DEFAULTS = new HashMap();
 
-    private static Boolean s_apnSourceServiceExists;
+    @VisibleForTesting
+    static Boolean s_apnSourceServiceExists;
 
     protected final Object mLock = new Object();
     @GuardedBy("mLock")
     private IApnSourceService mIApnSourceService;
+    private Injector mInjector;
+
+    private boolean mManagedApnEnforced;
 
     static {
         // Columns not included in UNIQUE constraint: name, current, edited, user, server, password,
         // authtype, type, protocol, roaming_protocol, sub_id, modem_cognitive, max_conns,
-        // wait_time, max_conns_time, mtu, bearer_bitmask, user_visible
-        CARRIERS_UNIQUE_FIELDS.add(NUMERIC);
-        CARRIERS_UNIQUE_FIELDS.add(MCC);
-        CARRIERS_UNIQUE_FIELDS.add(MNC);
-        CARRIERS_UNIQUE_FIELDS.add(APN);
-        CARRIERS_UNIQUE_FIELDS.add(PROXY);
-        CARRIERS_UNIQUE_FIELDS.add(PORT);
-        CARRIERS_UNIQUE_FIELDS.add(MMSPROXY);
-        CARRIERS_UNIQUE_FIELDS.add(MMSPORT);
-        CARRIERS_UNIQUE_FIELDS.add(MMSC);
-        CARRIERS_UNIQUE_FIELDS.add(CARRIER_ENABLED);
-        CARRIERS_UNIQUE_FIELDS.add(BEARER);
-        CARRIERS_UNIQUE_FIELDS.add(MVNO_TYPE);
-        CARRIERS_UNIQUE_FIELDS.add(MVNO_MATCH_DATA);
-        CARRIERS_UNIQUE_FIELDS.add(PROFILE_ID);
-        CARRIERS_UNIQUE_FIELDS.add(PROTOCOL);
-        CARRIERS_UNIQUE_FIELDS.add(ROAMING_PROTOCOL);
-        CARRIERS_UNIQUE_FIELDS.add(USER_EDITABLE);
+        // wait_time, max_conns_time, mtu, bearer_bitmask, user_visible, network_type_bitmask
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(NUMERIC, "");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MCC, "");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MNC, "");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(APN, "");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PROXY, "");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PORT, "");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MMSPROXY, "");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MMSPORT, "");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MMSC, "");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(CARRIER_ENABLED, "1");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(BEARER, "0");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MVNO_TYPE, "");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(MVNO_MATCH_DATA, "");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PROFILE_ID, "0");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(PROTOCOL, "IP");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(ROAMING_PROTOCOL, "IP");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(USER_EDITABLE, "1");
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(OWNED_BY, String.valueOf(OWNED_BY_OTHERS));
+        CARRIERS_UNIQUE_FIELDS_DEFAULTS.put(APN_SET_ID, String.valueOf(NO_SET_SET));
+
+        CARRIERS_UNIQUE_FIELDS.addAll(CARRIERS_UNIQUE_FIELDS_DEFAULTS.keySet());
     }
 
     @VisibleForTesting
@@ -238,11 +281,12 @@
                 AUTH_TYPE + " INTEGER DEFAULT -1," +
                 TYPE + " TEXT DEFAULT ''," +
                 CURRENT + " INTEGER," +
-                PROTOCOL + " TEXT DEFAULT 'IP'," +
-                ROAMING_PROTOCOL + " TEXT DEFAULT 'IP'," +
+                PROTOCOL + " TEXT DEFAULT " + DEFAULT_PROTOCOL + "," +
+                ROAMING_PROTOCOL + " TEXT DEFAULT " + DEFAULT_ROAMING_PROTOCOL + "," +
                 CARRIER_ENABLED + " BOOLEAN DEFAULT 1," +
                 BEARER + " INTEGER DEFAULT 0," +
                 BEARER_BITMASK + " INTEGER DEFAULT 0," +
+                NETWORK_TYPE_BITMASK + " INTEGER DEFAULT 0," +
                 MVNO_TYPE + " TEXT DEFAULT ''," +
                 MVNO_MATCH_DATA + " TEXT DEFAULT ''," +
                 SUBSCRIPTION_ID + " INTEGER DEFAULT "
@@ -256,51 +300,64 @@
                 EDITED + " INTEGER DEFAULT " + UNEDITED + "," +
                 USER_VISIBLE + " BOOLEAN DEFAULT 1," +
                 USER_EDITABLE + " BOOLEAN DEFAULT 1," +
+                OWNED_BY + " INTEGER DEFAULT " + OWNED_BY_OTHERS + "," +
+                APN_SET_ID + " INTEGER DEFAULT " + NO_SET_SET + "," +
                 // Uniqueness collisions are used to trigger merge code so if a field is listed
                 // here it means we will accept both (user edited + new apn_conf definition)
                 // Columns not included in UNIQUE constraint: name, current, edited,
                 // user, server, password, authtype, type, sub_id, modem_cognitive, max_conns,
-                // wait_time, max_conns_time, mtu, bearer_bitmask, user_visible.
+                // wait_time, max_conns_time, mtu, bearer_bitmask, user_visible,
+                // network_type_bitmask.
                 "UNIQUE (" + TextUtils.join(", ", CARRIERS_UNIQUE_FIELDS) + "));";
     }
 
     @VisibleForTesting
-    public static final String CREATE_SIMINFO_TABLE_STRING = "CREATE TABLE " + SIMINFO_TABLE + "("
-            + SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID
+    public static String getStringForSimInfoTableCreation(String tableName) {
+        return "CREATE TABLE " + tableName + "("
+                + SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID
                 + " INTEGER PRIMARY KEY AUTOINCREMENT,"
-            + SubscriptionManager.ICC_ID + " TEXT NOT NULL,"
-            + SubscriptionManager.SIM_SLOT_INDEX
+                + SubscriptionManager.ICC_ID + " TEXT NOT NULL,"
+                + SubscriptionManager.SIM_SLOT_INDEX
                 + " INTEGER DEFAULT " + SubscriptionManager.SIM_NOT_INSERTED + ","
-            + SubscriptionManager.DISPLAY_NAME + " TEXT,"
-            + SubscriptionManager.CARRIER_NAME + " TEXT,"
-            + SubscriptionManager.NAME_SOURCE
+                + SubscriptionManager.DISPLAY_NAME + " TEXT,"
+                + SubscriptionManager.CARRIER_NAME + " TEXT,"
+                + SubscriptionManager.NAME_SOURCE
                 + " INTEGER DEFAULT " + SubscriptionManager.NAME_SOURCE_DEFAULT_SOURCE + ","
-            + SubscriptionManager.COLOR + " INTEGER DEFAULT " + SubscriptionManager.COLOR_DEFAULT + ","
-            + SubscriptionManager.NUMBER + " TEXT,"
-            + SubscriptionManager.DISPLAY_NUMBER_FORMAT
+                + SubscriptionManager.COLOR + " INTEGER DEFAULT "
+                + SubscriptionManager.COLOR_DEFAULT + ","
+                + SubscriptionManager.NUMBER + " TEXT,"
+                + SubscriptionManager.DISPLAY_NUMBER_FORMAT
                 + " INTEGER NOT NULL DEFAULT " + SubscriptionManager.DISPLAY_NUMBER_DEFAULT + ","
-            + SubscriptionManager.DATA_ROAMING
+                + SubscriptionManager.DATA_ROAMING
                 + " INTEGER DEFAULT " + SubscriptionManager.DATA_ROAMING_DEFAULT + ","
-            + SubscriptionManager.MCC + " INTEGER DEFAULT 0,"
-            + SubscriptionManager.MNC + " INTEGER DEFAULT 0,"
-            + SubscriptionManager.SIM_PROVISIONING_STATUS
+                + SubscriptionManager.MCC + " INTEGER DEFAULT 0,"
+                + SubscriptionManager.MNC + " INTEGER DEFAULT 0,"
+                + SubscriptionManager.SIM_PROVISIONING_STATUS
                 + " INTEGER DEFAULT " + SubscriptionManager.SIM_PROVISIONED + ","
-            + SubscriptionManager.IS_EMBEDDED + " INTEGER DEFAULT 0,"
-            + SubscriptionManager.ACCESS_RULES + " BLOB,"
-            + SubscriptionManager.IS_REMOVABLE + " INTEGER DEFAULT 0,"
-            + SubscriptionManager.CB_EXTREME_THREAT_ALERT + " INTEGER DEFAULT 1,"
-            + SubscriptionManager.CB_SEVERE_THREAT_ALERT + " INTEGER DEFAULT 1,"
-            + SubscriptionManager.CB_AMBER_ALERT + " INTEGER DEFAULT 1,"
-            + SubscriptionManager.CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1,"
-            + SubscriptionManager.CB_ALERT_SOUND_DURATION + " INTEGER DEFAULT 4,"
-            + SubscriptionManager.CB_ALERT_REMINDER_INTERVAL + " INTEGER DEFAULT 0,"
-            + SubscriptionManager.CB_ALERT_VIBRATE + " INTEGER DEFAULT 1,"
-            + SubscriptionManager.CB_ALERT_SPEECH + " INTEGER DEFAULT 1,"
-            + SubscriptionManager.CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0,"
-            + SubscriptionManager.CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1,"
-            + SubscriptionManager.CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 0,"
-            + SubscriptionManager.CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1"
-            + ");";
+                + SubscriptionManager.IS_EMBEDDED + " INTEGER DEFAULT 0,"
+                + SubscriptionManager.CARD_ID + " TEXT NOT NULL,"
+                + SubscriptionManager.ACCESS_RULES + " BLOB,"
+                + SubscriptionManager.IS_REMOVABLE + " INTEGER DEFAULT 0,"
+                + SubscriptionManager.CB_EXTREME_THREAT_ALERT + " INTEGER DEFAULT 1,"
+                + SubscriptionManager.CB_SEVERE_THREAT_ALERT + " INTEGER DEFAULT 1,"
+                + SubscriptionManager.CB_AMBER_ALERT + " INTEGER DEFAULT 1,"
+                + SubscriptionManager.CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1,"
+                + SubscriptionManager.CB_ALERT_SOUND_DURATION + " INTEGER DEFAULT 4,"
+                + SubscriptionManager.CB_ALERT_REMINDER_INTERVAL + " INTEGER DEFAULT 0,"
+                + SubscriptionManager.CB_ALERT_VIBRATE + " INTEGER DEFAULT 1,"
+                + SubscriptionManager.CB_ALERT_SPEECH + " INTEGER DEFAULT 1,"
+                + SubscriptionManager.CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0,"
+                + SubscriptionManager.CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1,"
+                + SubscriptionManager.CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 0,"
+                + SubscriptionManager.CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1,"
+                + SubscriptionManager.ENHANCED_4G_MODE_ENABLED + " INTEGER DEFAULT -1,"
+                + SubscriptionManager.VT_IMS_ENABLED + " INTEGER DEFAULT -1,"
+                + SubscriptionManager.WFC_IMS_ENABLED + " INTEGER DEFAULT -1,"
+                + SubscriptionManager.WFC_IMS_MODE + " INTEGER DEFAULT -1,"
+                + SubscriptionManager.WFC_IMS_ROAMING_MODE + " INTEGER DEFAULT -1,"
+                + SubscriptionManager.WFC_IMS_ROAMING_ENABLED + " INTEGER DEFAULT -1"
+                + ");";
+    }
 
     static {
         s_urlMatcher.addURI("telephony", "carriers", URL_TELEPHONY);
@@ -309,6 +366,7 @@
         s_urlMatcher.addURI("telephony", "carriers/restore", URL_RESTOREAPN);
         s_urlMatcher.addURI("telephony", "carriers/preferapn", URL_PREFERAPN);
         s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update", URL_PREFERAPN_NO_UPDATE);
+        s_urlMatcher.addURI("telephony", "carriers/preferapnset", URL_PREFERAPNSET);
 
         s_urlMatcher.addURI("telephony", "siminfo", URL_SIMINFO);
 
@@ -318,10 +376,25 @@
         s_urlMatcher.addURI("telephony", "carriers/preferapn/subId/*", URL_PREFERAPN_USING_SUBID);
         s_urlMatcher.addURI("telephony", "carriers/preferapn_no_update/subId/*",
                 URL_PREFERAPN_NO_UPDATE_USING_SUBID);
+        s_urlMatcher.addURI("telephony", "carriers/preferapnset/subId/*",
+                URL_PREFERAPNSET_USING_SUBID);
 
         s_urlMatcher.addURI("telephony", "carriers/update_db", URL_UPDATE_DB);
         s_urlMatcher.addURI("telephony", "carriers/delete", URL_DELETE);
 
+        // Only called by DevicePolicyManager to manipulate DPC records.
+        s_urlMatcher.addURI("telephony", "carriers/dpc", URL_DPC);
+        // Only called by DevicePolicyManager to manipulate a DPC record with certain _ID.
+        s_urlMatcher.addURI("telephony", "carriers/dpc/#", URL_DPC_ID);
+        // Only called by Settings app, DcTracker and other telephony components to get APN list
+        // according to whether DPC records are enforced.
+        s_urlMatcher.addURI("telephony", "carriers/filtered", URL_FILTERED);
+        // Only called by Settings app, DcTracker and other telephony components to get a
+        // single APN according to whether DPC records are enforced.
+        s_urlMatcher.addURI("telephony", "carriers/filtered/#", URL_FILTERED_ID);
+        // Only Called by DevicePolicyManager to enforce DPC records.
+        s_urlMatcher.addURI("telephony", "carriers/enforce_managed", URL_ENFORCE_MANAGED);
+
         s_currentNullMap = new ContentValues(1);
         s_currentNullMap.put(CURRENT, "0");
 
@@ -329,6 +402,25 @@
         s_currentSetMap.put(CURRENT, "1");
     }
 
+    /**
+     * Unit test will subclass it to inject mocks.
+     */
+    @VisibleForTesting
+    static class Injector {
+        int binderGetCallingUid() {
+            return Binder.getCallingUid();
+        }
+    }
+
+    public TelephonyProvider() {
+        this(new Injector());
+    }
+
+    @VisibleForTesting
+    public TelephonyProvider(Injector injector) {
+        mInjector = injector;
+    }
+
     private static class DatabaseHelper extends SQLiteOpenHelper {
         // Context to access resources with
         private Context mContext;
@@ -368,7 +460,7 @@
         @Override
         public void onCreate(SQLiteDatabase db) {
             if (DBG) log("dbh.onCreate:+ db=" + db);
-            createSimInfoTable(db);
+            createSimInfoTable(db, SIMINFO_TABLE);
             createCarriersTable(db, CARRIERS_TABLE);
             // if CarrierSettings app is installed, we expect it to do the initializiation instead
             if (apnSourceServiceExists(mContext)) {
@@ -390,7 +482,7 @@
             } catch (SQLiteException e) {
                 loge("Exception " + SIMINFO_TABLE + "e=" + e);
                 if (e.getMessage().startsWith("no such table")) {
-                    createSimInfoTable(db);
+                    createSimInfoTable(db, SIMINFO_TABLE);
                 }
             }
             try {
@@ -405,9 +497,9 @@
             if (VDBG) log("dbh.onOpen:- db=" + db);
         }
 
-        private void createSimInfoTable(SQLiteDatabase db) {
-            if (DBG) log("dbh.createSimInfoTable:+");
-            db.execSQL(CREATE_SIMINFO_TABLE_STRING);
+        private void createSimInfoTable(SQLiteDatabase db, String tableName) {
+            if (DBG) log("dbh.createSimInfoTable:+ " + tableName);
+            db.execSQL(getStringForSimInfoTableCreation(tableName));
             if (DBG) log("dbh.createSimInfoTable:-");
         }
 
@@ -819,52 +911,9 @@
                 oldVersion = 18 << 16 | 6;
             }
             if (oldVersion < (19 << 16 | 6)) {
-                // Upgrade steps from version 18 are:
-                // 1. Create a temp table- done in createCarriersTable()
-                // 2. copy over APNs from old table to new table - done in copyDataToTmpTable()
-                // 3. Drop the existing table.
-                // 4. Copy over the tmp table.
-                Cursor c;
-                String[] proj = {"_id"};
-                if (VDBG) {
-                    c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null);
-                    log("dbh.onUpgrade:- before upgrading total number of rows: " + c.getCount());
-                    c.close();
-                }
-
-                c = db.query(CARRIERS_TABLE, null, null, null, null, null, null);
-
-                if (VDBG) {
-                    log("dbh.onUpgrade:- starting data copy of existing rows: " +
-                            + ((c == null) ? 0 : c.getCount()));
-                }
-
-                db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE_TMP);
-
-                createCarriersTable(db, CARRIERS_TABLE_TMP);
-
-                copyDataToTmpTable(db, c);
-                c.close();
-
-                db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE);
-
-                db.execSQL("ALTER TABLE " + CARRIERS_TABLE_TMP + " rename to " + CARRIERS_TABLE +
-                        ";");
-
-                if (VDBG) {
-                    c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null);
-                    log("dbh.onUpgrade:- after upgrading total number of rows: " + c.getCount());
-                    c.close();
-                    c = db.query(CARRIERS_TABLE, proj, IS_UNEDITED, null, null, null, null);
-                    log("dbh.onUpgrade:- after upgrading total number of rows with " + IS_UNEDITED +
-                            ": " + c.getCount());
-                    c.close();
-                    c = db.query(CARRIERS_TABLE, proj, IS_EDITED, null, null, null, null);
-                    log("dbh.onUpgrade:- after upgrading total number of rows with " + IS_EDITED +
-                            ": " + c.getCount());
-                    c.close();
-                }
-                oldVersion = 19 << 16 | 6;
+                // Do nothing. This is to avoid recreating table twice. Table is anyway recreated
+                // for version 24 and that takes care of updates for this version as well.
+                // This version added more fields protocol and roaming protocol to the primary key.
             }
             if (oldVersion < (20 << 16 | 6)) {
                 try {
@@ -885,7 +934,7 @@
             }
             if (oldVersion < (21 << 16 | 6)) {
                 try {
-                    // Try to update the siminfo table. It might not be there.
+                    // Try to update the carriers table. It might not be there.
                     db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " +
                             USER_EDITABLE + " INTEGER DEFAULT 1;");
                 } catch (SQLiteException e) {
@@ -898,11 +947,235 @@
                 }
                 oldVersion = 21 << 16 | 6;
             }
+            if (oldVersion < (22 << 16 | 6)) {
+                try {
+                    // Try to update the siminfo table. It might not be there.
+                    db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
+                            + SubscriptionManager.ENHANCED_4G_MODE_ENABLED
+                            + " INTEGER DEFAULT -1;");
+                    db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
+                            + SubscriptionManager.VT_IMS_ENABLED + " INTEGER DEFAULT -1;");
+                    db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
+                            + SubscriptionManager.WFC_IMS_ENABLED + " INTEGER DEFAULT -1;");
+                    db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
+                            + SubscriptionManager.WFC_IMS_MODE + " INTEGER DEFAULT -1;");
+                    db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
+                            + SubscriptionManager.WFC_IMS_ROAMING_MODE + " INTEGER DEFAULT -1;");
+                    db.execSQL("ALTER TABLE " + SIMINFO_TABLE + " ADD COLUMN "
+                            + SubscriptionManager.WFC_IMS_ROAMING_ENABLED + " INTEGER DEFAULT -1;");
+                } catch (SQLiteException e) {
+                    if (DBG) {
+                        log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " +
+                                "The table will get created in onOpen.");
+                    }
+                }
+                oldVersion = 22 << 16 | 6;
+            }
+            if (oldVersion < (23 << 16 | 6)) {
+                try {
+                    db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " +
+                            OWNED_BY + " INTEGER DEFAULT " + OWNED_BY_OTHERS + ";");
+                } catch (SQLiteException e) {
+                    if (DBG) {
+                        log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " +
+                                "The table will get created in onOpen.");
+                    }
+                }
+                oldVersion = 23 << 16 | 6;
+            }
+            if (oldVersion < (24 << 16 | 6)) {
+                Cursor c = null;
+                String[] proj = {"_id"};
+                recreateDB(c, db, proj, /* version */24);
+                if (VDBG) {
+                    c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null);
+                    log("dbh.onUpgrade:- after upgrading total number of rows: " + c.getCount());
+                    c.close();
+                    c = db.query(
+                            CARRIERS_TABLE, proj, NETWORK_TYPE_BITMASK, null, null, null, null);
+                    log("dbh.onUpgrade:- after upgrading total number of rows with "
+                            + NETWORK_TYPE_BITMASK + ": " + c.getCount());
+                    c.close();
+                }
+                oldVersion = 24 << 16 | 6;
+            }
+            if (oldVersion < (25 << 16 | 6)) {
+                // Add a new column SubscriptionManager.CARD_ID into the database and set the value
+                // to be the same as the existing column SubscriptionManager.ICC_ID. In order to do
+                // this, we need to first make a copy of the existing SIMINFO_TABLE, set the value
+                // of the new column SubscriptionManager.CARD_ID, and replace the SIMINFO_TABLE with
+                // the new table.
+                Cursor c = null;
+                String[] proj = {SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID};
+                recreateSimInfoDB(c, db, proj);
+                if (VDBG) {
+                    c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null);
+                    log("dbh.onUpgrade:- after upgrading " + SIMINFO_TABLE
+                            + " total number of rows: " + c.getCount());
+                    c.close();
+                    c = db.query(SIMINFO_TABLE, proj, SubscriptionManager.CARD_ID + " IS NOT NULL",
+                            null, null, null, null);
+                    log("dbh.onUpgrade:- after upgrading total number of rows with "
+                            + SubscriptionManager.CARD_ID + ": " + c.getCount());
+                    c.close();
+                }
+                oldVersion = 25 << 16 | 6;
+            }
+            if (oldVersion < (26 << 16 | 6)) {
+                // Add a new column Carriers.APN_SET_ID into the database and set the value to
+                // Carriers.NO_SET_SET by default.
+                try {
+                    db.execSQL("ALTER TABLE " + CARRIERS_TABLE + " ADD COLUMN " +
+                            APN_SET_ID + " INTEGER DEFAULT " + NO_SET_SET + ";");
+                } catch (SQLiteException e) {
+                    if (DBG) {
+                        log("onUpgrade skipping " + CARRIERS_TABLE + " upgrade. " +
+                                "The table will get created in onOpen.");
+                    }
+                }
+                oldVersion = 26 << 16 | 6;
+            }
             if (DBG) {
                 log("dbh.onUpgrade:- db=" + db + " oldV=" + oldVersion + " newV=" + newVersion);
             }
         }
 
+        private void recreateSimInfoDB(Cursor c, SQLiteDatabase db, String[] proj) {
+            if (VDBG) {
+                c = db.query(SIMINFO_TABLE, proj, null, null, null, null, null);
+                log("dbh.onUpgrade:+ before upgrading " + SIMINFO_TABLE +
+                        " total number of rows: " + c.getCount());
+                c.close();
+            }
+
+            // Sort in ascending order by subscription id to make sure the rows do not get flipped
+            // during the query and added in the new sim info table in another order (sub id is
+            // stored in settings between migrations).
+            c = db.query(SIMINFO_TABLE, null, null, null, null, null, ORDER_BY_SUB_ID);
+
+            db.execSQL("DROP TABLE IF EXISTS " + SIMINFO_TABLE_TMP);
+
+            createSimInfoTable(db, SIMINFO_TABLE_TMP);
+
+            copySimInfoDataToTmpTable(db, c);
+            c.close();
+
+            db.execSQL("DROP TABLE IF EXISTS " + SIMINFO_TABLE);
+
+            db.execSQL("ALTER TABLE " + SIMINFO_TABLE_TMP + " rename to " + SIMINFO_TABLE + ";");
+
+        }
+
+        private void copySimInfoDataToTmpTable(SQLiteDatabase db, Cursor c) {
+            // Move entries from SIMINFO_TABLE to SIMINFO_TABLE_TMP
+            if (c != null) {
+                while (c.moveToNext()) {
+                    ContentValues cv = new ContentValues();
+                    copySimInfoValuesV24(cv, c);
+                    // The card ID is supposed to be the ICCID of the profile for UICC card, and
+                    // the EID of the card for eUICC card. Since EID is unknown for old entries in
+                    // SIMINFO_TABLE, we use ICCID as the card ID for all the old entries while
+                    // upgrading the SIMINFO_TABLE. In UiccController, both the card ID and ICCID
+                    // will be checked when user queries the slot information using the card ID
+                    // from the database.
+                    getCardIdfromIccid(cv, c);
+                    try {
+                        db.insert(SIMINFO_TABLE_TMP, null, cv);
+                        if (VDBG) {
+                            log("dbh.copySimInfoDataToTmpTable: db.insert returned >= 0; " +
+                                "insert successful for cv " + cv);
+                        }
+                    } catch (SQLException e) {
+                        if (VDBG)
+                            log("dbh.copySimInfoDataToTmpTable insertWithOnConflict exception " +
+                                e + " for cv " + cv);
+                    }
+                }
+            }
+        }
+
+        private void copySimInfoValuesV24(ContentValues cv, Cursor c) {
+            // String vals
+            getStringValueFromCursor(cv, c, SubscriptionManager.ICC_ID);
+            getStringValueFromCursor(cv, c, SubscriptionManager.DISPLAY_NAME);
+            getStringValueFromCursor(cv, c, SubscriptionManager.CARRIER_NAME);
+            getStringValueFromCursor(cv, c, SubscriptionManager.NUMBER);
+
+            // bool/int vals
+            getIntValueFromCursor(cv, c, SubscriptionManager.SIM_SLOT_INDEX);
+            getIntValueFromCursor(cv, c, SubscriptionManager.NAME_SOURCE);
+            getIntValueFromCursor(cv, c, SubscriptionManager.COLOR);
+            getIntValueFromCursor(cv, c, SubscriptionManager.DISPLAY_NUMBER_FORMAT);
+            getIntValueFromCursor(cv, c, SubscriptionManager.DATA_ROAMING);
+            getIntValueFromCursor(cv, c, SubscriptionManager.MCC);
+            getIntValueFromCursor(cv, c, SubscriptionManager.MNC);
+            getIntValueFromCursor(cv, c, SubscriptionManager.SIM_PROVISIONING_STATUS);
+            getIntValueFromCursor(cv, c, SubscriptionManager.IS_EMBEDDED);
+            getIntValueFromCursor(cv, c, SubscriptionManager.IS_REMOVABLE);
+            getIntValueFromCursor(cv, c, SubscriptionManager.CB_EXTREME_THREAT_ALERT);
+            getIntValueFromCursor(cv, c, SubscriptionManager.CB_SEVERE_THREAT_ALERT);
+            getIntValueFromCursor(cv, c, SubscriptionManager.CB_AMBER_ALERT);
+            getIntValueFromCursor(cv, c, SubscriptionManager.CB_EMERGENCY_ALERT);
+            getIntValueFromCursor(cv, c, SubscriptionManager.CB_ALERT_SOUND_DURATION);
+            getIntValueFromCursor(cv, c, SubscriptionManager.CB_ALERT_REMINDER_INTERVAL);
+            getIntValueFromCursor(cv, c, SubscriptionManager.CB_ALERT_VIBRATE);
+            getIntValueFromCursor(cv, c, SubscriptionManager.CB_ALERT_SPEECH);
+            getIntValueFromCursor(cv, c, SubscriptionManager.CB_ETWS_TEST_ALERT);
+            getIntValueFromCursor(cv, c, SubscriptionManager.CB_CHANNEL_50_ALERT);
+            getIntValueFromCursor(cv, c, SubscriptionManager.CB_CMAS_TEST_ALERT);
+            getIntValueFromCursor(cv, c, SubscriptionManager.CB_OPT_OUT_DIALOG);
+            getIntValueFromCursor(cv, c, SubscriptionManager.ENHANCED_4G_MODE_ENABLED);
+            getIntValueFromCursor(cv, c, SubscriptionManager.VT_IMS_ENABLED);
+            getIntValueFromCursor(cv, c, SubscriptionManager.WFC_IMS_ENABLED);
+            getIntValueFromCursor(cv, c, SubscriptionManager.WFC_IMS_MODE);
+            getIntValueFromCursor(cv, c, SubscriptionManager.WFC_IMS_ROAMING_MODE);
+            getIntValueFromCursor(cv, c, SubscriptionManager.WFC_IMS_ROAMING_ENABLED);
+
+            // Blob vals
+            getBlobValueFromCursor(cv, c, SubscriptionManager.ACCESS_RULES);
+        }
+
+        private void getCardIdfromIccid(ContentValues cv, Cursor c) {
+            int columnIndex = c.getColumnIndex(SubscriptionManager.ICC_ID);
+            if (columnIndex != -1) {
+                String fromCursor = c.getString(columnIndex);
+                if (!TextUtils.isEmpty(fromCursor)) {
+                    cv.put(SubscriptionManager.CARD_ID, fromCursor);
+                }
+            }
+        }
+
+        private void recreateDB(Cursor c, SQLiteDatabase db, String[] proj, int version) {
+            // Upgrade steps are:
+            // 1. Create a temp table- done in createCarriersTable()
+            // 2. copy over APNs from old table to new table - done in copyDataToTmpTable()
+            // 3. Drop the existing table.
+            // 4. Copy over the tmp table.
+            if (VDBG) {
+                c = db.query(CARRIERS_TABLE, proj, null, null, null, null, null);
+                log("dbh.onUpgrade:- before upgrading total number of rows: " + c.getCount());
+                c.close();
+            }
+
+            c = db.query(CARRIERS_TABLE, null, null, null, null, null, null);
+
+            if (VDBG) {
+                log("dbh.onUpgrade:- starting data copy of existing rows: " +
+                        + ((c == null) ? 0 : c.getCount()));
+            }
+
+            db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE_TMP);
+
+            createCarriersTable(db, CARRIERS_TABLE_TMP);
+
+            copyDataToTmpTable(db, c);
+            c.close();
+
+            db.execSQL("DROP TABLE IF EXISTS " + CARRIERS_TABLE);
+
+            db.execSQL("ALTER TABLE " + CARRIERS_TABLE_TMP + " rename to " + CARRIERS_TABLE + ";");
+        }
+
         private void preserveUserAndCarrierApns(SQLiteDatabase db) {
             if (VDBG) log("preserveUserAndCarrierApns");
             XmlPullParser confparser;
@@ -1034,9 +1307,9 @@
             whereArgs[i++] = values.containsKey(TYPE) ?
                     values.getAsString(TYPE) : "";
             whereArgs[i++] = values.containsKey(PROTOCOL) ?
-                    values.getAsString(PROTOCOL) : "IP";
+                    values.getAsString(PROTOCOL) : DEFAULT_PROTOCOL;
             whereArgs[i++] = values.containsKey(ROAMING_PROTOCOL) ?
-                    values.getAsString(ROAMING_PROTOCOL) : "IP";
+                    values.getAsString(ROAMING_PROTOCOL) : DEFAULT_ROAMING_PROTOCOL;
 
             if (values.containsKey(CARRIER_ENABLED) &&
                     (values.getAsString(CARRIER_ENABLED).
@@ -1097,6 +1370,8 @@
                 while (c.moveToNext()) {
                     ContentValues cv = new ContentValues();
                     copyApnValuesV17(cv, c);
+                    // Sync bearer bitmask and network type bitmask
+                    getNetworkTypeBitmaskFromCursor(cv, c);
                     try {
                         db.insertWithOnConflict(CARRIERS_TABLE_TMP, null, cv,
                                 SQLiteDatabase.CONFLICT_ABORT);
@@ -1173,6 +1448,11 @@
                         int bearer_bitmask = ServiceState.getBitmaskForTech(
                                 Integer.parseInt(bearerStr));
                         cv.put(BEARER_BITMASK, bearer_bitmask);
+
+                        int networkTypeBitmask = ServiceState.getBitmaskForTech(
+                                ServiceState.rilRadioTechnologyToNetworkType(
+                                        Integer.parseInt(bearerStr)));
+                        cv.put(NETWORK_TYPE_BITMASK, networkTypeBitmask);
                     }
 
                     int userEditedColumnIdx = c.getColumnIndex("user_edited");
@@ -1182,7 +1462,7 @@
                             cv.put(EDITED, new Integer(user_edited));
                         }
                     } else {
-                        cv.put(EDITED, USER_EDITED);
+                        cv.put(EDITED, CARRIER_EDITED);
                     }
 
                     // New EDITED column. Default value (UNEDITED) will
@@ -1242,6 +1522,37 @@
             }
         }
 
+        /**
+         * If NETWORK_TYPE_BITMASK does not exist (upgrade from version 23 to version 24), generate
+         * NETWORK_TYPE_BITMASK with the use of BEARER_BITMASK. If NETWORK_TYPE_BITMASK existed
+         * (upgrade from version 24 to forward), always map NETWORK_TYPE_BITMASK to BEARER_BITMASK.
+         */
+        private void getNetworkTypeBitmaskFromCursor(ContentValues cv, Cursor c) {
+            int columnIndex = c.getColumnIndex(NETWORK_TYPE_BITMASK);
+            if (columnIndex != -1) {
+                getStringValueFromCursor(cv, c, NETWORK_TYPE_BITMASK);
+                // Map NETWORK_TYPE_BITMASK to BEARER_BITMASK if NETWORK_TYPE_BITMASK existed;
+                String fromCursor = c.getString(columnIndex);
+                if (!TextUtils.isEmpty(fromCursor) && fromCursor.matches("\\d+")) {
+                    int networkBitmask = Integer.valueOf(fromCursor);
+                    int bearerBitmask = ServiceState.convertNetworkTypeBitmaskToBearerBitmask(
+                            networkBitmask);
+                    cv.put(BEARER_BITMASK, String.valueOf(bearerBitmask));
+                }
+                return;
+            }
+            columnIndex = c.getColumnIndex(BEARER_BITMASK);
+            if (columnIndex != -1) {
+                String fromCursor = c.getString(columnIndex);
+                if (!TextUtils.isEmpty(fromCursor) && fromCursor.matches("\\d+")) {
+                    int bearerBitmask = Integer.valueOf(fromCursor);
+                    int networkBitmask = ServiceState.convertBearerBitmaskToNetworkTypeBitmask(
+                            bearerBitmask);
+                    cv.put(NETWORK_TYPE_BITMASK, String.valueOf(networkBitmask));
+                }
+            }
+        }
+
         private void getIntValueFromCursor(ContentValues cv, Cursor c, String key) {
             int columnIndex = c.getColumnIndex(key);
             if (columnIndex != -1) {
@@ -1256,6 +1567,16 @@
             }
         }
 
+        private void getBlobValueFromCursor(ContentValues cv, Cursor c, String key) {
+            int columnIndex = c.getColumnIndex(key);
+            if (columnIndex != -1) {
+                byte[] fromCursor = c.getBlob(columnIndex);
+                if (fromCursor != null) {
+                    cv.put(key, fromCursor);
+                }
+            }
+        }
+
         /**
          * Gets the next row of apn values.
          *
@@ -1306,6 +1627,7 @@
             addIntAttribute(parser, "wait_time", map, WAIT_TIME);
             addIntAttribute(parser, "max_conns_time", map, MAX_CONNS_TIME);
             addIntAttribute(parser, "mtu", map, MTU);
+            addIntAttribute(parser, "apn_set_id", map, APN_SET_ID);
 
 
             addBoolAttribute(parser, "carrier_enabled", map, CARRIER_ENABLED);
@@ -1313,10 +1635,26 @@
             addBoolAttribute(parser, "user_visible", map, USER_VISIBLE);
             addBoolAttribute(parser, "user_editable", map, USER_EDITABLE);
 
+            int networkTypeBitmask = 0;
+            String networkTypeList = parser.getAttributeValue(null, "network_type_bitmask");
+            if (networkTypeList != null) {
+                networkTypeBitmask = ServiceState.getBitmaskFromString(networkTypeList);
+            }
+            map.put(NETWORK_TYPE_BITMASK, networkTypeBitmask);
+
             int bearerBitmask = 0;
-            String bearerList = parser.getAttributeValue(null, "bearer_bitmask");
-            if (bearerList != null) {
-                bearerBitmask = ServiceState.getBitmaskFromString(bearerList);
+            if (networkTypeList != null) {
+                bearerBitmask =
+                        ServiceState.convertNetworkTypeBitmaskToBearerBitmask(networkTypeBitmask);
+            } else {
+                String bearerList = parser.getAttributeValue(null, "bearer_bitmask");
+                if (bearerList != null) {
+                    bearerBitmask = ServiceState.getBitmaskFromString(bearerList);
+                }
+                // Update the network type bitmask to keep them sync.
+                networkTypeBitmask = ServiceState.convertBearerBitmaskToNetworkTypeBitmask(
+                        bearerBitmask);
+                map.put(NETWORK_TYPE_BITMASK, networkTypeBitmask);
             }
             map.put(BEARER_BITMASK, bearerBitmask);
 
@@ -1459,10 +1797,10 @@
                         if (VDBG) {
                             log("mergeFieldsAndUpdateDb: Calling separateRowsNeeded() oldType=" +
                                     oldType + " old bearer=" + oldRow.getInt(oldRow.getColumnIndex(
-                                    BEARER_BITMASK)) +
+                                    BEARER_BITMASK)) +  " old networkType=" +
+                                    oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK)) +
                                     " old profile_id=" + oldRow.getInt(oldRow.getColumnIndex(
-                                    PROFILE_ID)) +
-                                    " newRow " + newRow);
+                                    PROFILE_ID)) + " newRow " + newRow);
                         }
 
                         // If separate rows are needed, do not need to merge any further
@@ -1488,8 +1826,7 @@
                         newRow.put(TYPE, mergedType.toString());
                     }
                 }
-                mergedValues.put(TYPE, newRow.getAsString(
-                        TYPE));
+                mergedValues.put(TYPE, newRow.getAsString(TYPE));
             }
 
             if (newRow.containsKey(BEARER_BITMASK)) {
@@ -1505,6 +1842,24 @@
                 mergedValues.put(BEARER_BITMASK, newRow.getAsInteger(BEARER_BITMASK));
             }
 
+            if (newRow.containsKey(NETWORK_TYPE_BITMASK)) {
+                int oldBitmask = oldRow.getInt(oldRow.getColumnIndex(NETWORK_TYPE_BITMASK));
+                int newBitmask = newRow.getAsInteger(NETWORK_TYPE_BITMASK);
+                if (oldBitmask != newBitmask) {
+                    if (oldBitmask == 0 || newBitmask == 0) {
+                        newRow.put(NETWORK_TYPE_BITMASK, 0);
+                    } else {
+                        newRow.put(NETWORK_TYPE_BITMASK, (oldBitmask | newBitmask));
+                    }
+                }
+                mergedValues.put(NETWORK_TYPE_BITMASK, newRow.getAsInteger(NETWORK_TYPE_BITMASK));
+            }
+
+            if (newRow.containsKey(BEARER_BITMASK)
+                    && newRow.containsKey(NETWORK_TYPE_BITMASK)) {
+                syncBearerBitmaskAndNetworkTypeBitmask(mergedValues);
+            }
+
             if (!onUpgrade) {
                 // Do not overwrite a carrier or user edit with EDITED=UNEDITED
                 if (newRow.containsKey(EDITED)) {
@@ -1635,28 +1990,23 @@
                     TYPE,
                     EDITED,
                     BEARER_BITMASK,
+                    NETWORK_TYPE_BITMASK,
                     PROFILE_ID };
             String selection = TextUtils.join("=? AND ", CARRIERS_UNIQUE_FIELDS) + "=?";
             int i = 0;
-            String[] selectionArgs = new String[14];
-            selectionArgs[i++] = row.getAsString(NUMERIC);
-            selectionArgs[i++] = row.getAsString(MCC);
-            selectionArgs[i++] = row.getAsString(MNC);
-            selectionArgs[i++] = row.containsKey(APN) ? row.getAsString(APN) : "";
-            selectionArgs[i++] = row.containsKey(PROXY) ? row.getAsString(PROXY) : "";
-            selectionArgs[i++] = row.containsKey(PORT) ? row.getAsString(PORT) : "";
-            selectionArgs[i++] = row.containsKey(MMSPROXY) ? row.getAsString(MMSPROXY) : "";
-            selectionArgs[i++] = row.containsKey(MMSPORT) ? row.getAsString(MMSPORT) : "";
-            selectionArgs[i++] = row.containsKey(MMSC) ? row.getAsString(MMSC) : "";
-            selectionArgs[i++] = row.containsKey(CARRIER_ENABLED) &&
-                    (row.getAsString(CARRIER_ENABLED).equals("0") ||
-                            row.getAsString(CARRIER_ENABLED).equals("false")) ?
-                    "0" : "1";
-            selectionArgs[i++] = row.containsKey(BEARER) ? row.getAsString(BEARER) : "0";
-            selectionArgs[i++] = row.containsKey(MVNO_TYPE) ? row.getAsString(MVNO_TYPE) : "";
-            selectionArgs[i++] = row.containsKey(MVNO_MATCH_DATA) ?
-                    row.getAsString(MVNO_MATCH_DATA) : "";
-            selectionArgs[i++] = row.containsKey(PROFILE_ID) ? row.getAsString(PROFILE_ID) : "0";
+            String[] selectionArgs = new String[CARRIERS_UNIQUE_FIELDS.size()];
+            for (String field : CARRIERS_UNIQUE_FIELDS) {
+                if (CARRIER_ENABLED.equals(field)) {
+                    // for CARRIER_ENABLED we overwrite the value "false" with "0"
+                    selectionArgs[i++] = row.containsKey(CARRIER_ENABLED) &&
+                            (row.getAsString(CARRIER_ENABLED).equals("0") ||
+                                    row.getAsString(CARRIER_ENABLED).equals("false")) ?
+                            "0" : CARRIERS_UNIQUE_FIELDS_DEFAULTS.get(CARRIER_ENABLED);
+                } else {
+                    selectionArgs[i++] = row.containsKey(field) ?
+                            row.getAsString(field) : CARRIERS_UNIQUE_FIELDS_DEFAULTS.get(field);
+                }
+            }
 
             Cursor c = db.query(table, columns, selection, selectionArgs, null, null, null);
 
@@ -1830,10 +2180,30 @@
             }
         }
 
+        SharedPreferences sp = getContext().getSharedPreferences(ENFORCED_FILE,
+                Context.MODE_PRIVATE);
+        mManagedApnEnforced = sp.getBoolean(ENFORCED_KEY, false);
+
         if (VDBG) log("onCreate:- ret true");
+
         return true;
     }
 
+    private synchronized boolean isManagedApnEnforced() {
+        return mManagedApnEnforced;
+    }
+
+    private void setManagedApnEnforced(boolean enforced) {
+        SharedPreferences sp = getContext().getSharedPreferences(ENFORCED_FILE,
+                Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = sp.edit();
+        editor.putBoolean(ENFORCED_KEY, enforced);
+        editor.apply();
+        synchronized (this) {
+            mManagedApnEnforced = enforced;
+        }
+    }
+
     private void setPreferredApnId(Long id, int subId, boolean saveApn) {
         SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_APN,
                 Context.MODE_PRIVATE);
@@ -1867,6 +2237,16 @@
         return apnId;
     }
 
+    private int getPreferredApnSetId(int subId) {
+        SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_FULL_APN,
+                Context.MODE_PRIVATE);
+        try {
+            return Integer.parseInt(sp.getString(APN_SET_ID + subId, null));
+        } catch (NumberFormatException e) {
+            return NO_SET_SET;
+        }
+    }
+
     private void deletePreferredApnId() {
         SharedPreferences sp = getContext().getSharedPreferences(PREF_FILE_APN,
                 Context.MODE_PRIVATE);
@@ -1900,6 +2280,7 @@
         SQLiteDatabase db = getWritableDatabase();
         // query all unique fields from id
         String[] proj = CARRIERS_UNIQUE_FIELDS.toArray(new String[CARRIERS_UNIQUE_FIELDS.size()]);
+
         Cursor c = db.query(CARRIERS_TABLE, proj, "_id=" + id, null, null, null, null);
         if (c != null) {
             if (c.getCount() == 1) {
@@ -1971,6 +2352,17 @@
         }
     }
 
+    boolean isCallingFromSystemOrPhoneUid() {
+        return mInjector.binderGetCallingUid() == Process.SYSTEM_UID ||
+                mInjector.binderGetCallingUid() == Process.PHONE_UID;
+    }
+
+    void ensureCallingFromSystemOrPhoneUid(String message) {
+        if (!isCallingFromSystemOrPhoneUid()) {
+            throw new SecurityException(message);
+        }
+    }
+
     @Override
     public synchronized Cursor query(Uri url, String[] projectionIn, String selection,
             String[] selectionArgs, String sort) {
@@ -1984,6 +2376,8 @@
         qb.setStrict(true); // a little protection from injection attacks
         qb.setTables(CARRIERS_TABLE);
 
+        List<String> constraints = new ArrayList<String>();
+
         int match = s_urlMatcher.match(url);
         switch (match) {
             case URL_TELEPHONY_USING_SUBID: {
@@ -1995,13 +2389,13 @@
                     return null;
                 }
                 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
-                qb.appendWhere(NUMERIC + " = '" + mTelephonyManager.getSimOperator(subId) + "'");
-                // FIXME alter the selection to pass subId
-                // selection = selection + "and subId = "
+                constraints.add(NUMERIC + " = '" + mTelephonyManager.getSimOperator(subId) + "'");
+                // TODO b/74213956 turn this back on once insertion includes correct sub id
+                // constraints.add(SUBSCRIPTION_ID + "=" + subIdString);
             }
             // intentional fall through from above case
-            // do nothing
             case URL_TELEPHONY: {
+                constraints.add(IS_NOT_OWNED_BY_DPC);
                 break;
             }
 
@@ -2014,19 +2408,21 @@
                     return null;
                 }
                 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
-                // FIXME alter the selection to pass subId
-                // selection = selection + "and subId = "
+                // TODO b/74213956 turn this back on once insertion includes correct sub id
+                // constraints.add(SUBSCRIPTION_ID + "=" + subIdString);
             }
             //intentional fall through from above case
             case URL_CURRENT: {
-                qb.appendWhere("current IS NOT NULL");
+                constraints.add("current IS NOT NULL");
+                constraints.add(IS_NOT_OWNED_BY_DPC);
                 // do not ignore the selection since MMS may use it.
                 //selection = null;
                 break;
             }
 
             case URL_ID: {
-                qb.appendWhere("_id = " + url.getPathSegments().get(1));
+                constraints.add("_id = " + url.getPathSegments().get(1));
+                constraints.add(IS_NOT_OWNED_BY_DPC);
                 break;
             }
 
@@ -2040,14 +2436,67 @@
                     return null;
                 }
                 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
+                // TODO b/74213956 turn this back on once insertion includes correct sub id
+                // constraints.add(SUBSCRIPTION_ID + "=" + subIdString);
             }
             //intentional fall through from above case
             case URL_PREFERAPN:
             case URL_PREFERAPN_NO_UPDATE: {
-                qb.appendWhere("_id = " + getPreferredApnId(subId, true));
+                constraints.add("_id = " + getPreferredApnId(subId, true));
                 break;
             }
 
+            case URL_PREFERAPNSET_USING_SUBID: {
+                subIdString = url.getLastPathSegment();
+                try {
+                    subId = Integer.parseInt(subIdString);
+                } catch (NumberFormatException e) {
+                    loge("NumberFormatException" + e);
+                    return null;
+                }
+                if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
+                // TODO b/74213956 turn this back on once insertion includes correct sub id
+                // constraints.add(SUBSCRIPTION_ID + "=" + subIdString);
+            }
+            // intentional fall through from above case
+            case URL_PREFERAPNSET: {
+                final int set = getPreferredApnSetId(subId);
+                if (set != NO_SET_SET) {
+                    constraints.add(APN_SET_ID + "=" + set);
+                }
+                break;
+            }
+
+            case URL_DPC: {
+                ensureCallingFromSystemOrPhoneUid("URL_DPC called from non SYSTEM_UID.");
+                // DPC query only returns DPC records.
+                constraints.add(IS_OWNED_BY_DPC);
+                break;
+            }
+
+            case URL_FILTERED_ID: {
+                constraints.add("_id = " + url.getLastPathSegment());
+            }
+            //intentional fall through from above case
+            case URL_FILTERED: {
+                if(isManagedApnEnforced()) {
+                    // If enforced, return DPC records only.
+                    constraints.add(IS_OWNED_BY_DPC);
+                } else {
+                    // Otherwise return non-DPC records only.
+                    constraints.add(IS_NOT_OWNED_BY_DPC);
+                }
+                break;
+            }
+
+            case URL_ENFORCE_MANAGED: {
+                ensureCallingFromSystemOrPhoneUid(
+                        "URL_ENFORCE_MANAGED called from non SYSTEM_UID.");
+                MatrixCursor cursor = new MatrixCursor(new String[]{ENFORCED_KEY});
+                cursor.addRow(new Object[]{isManagedApnEnforced() ? 1 : 0});
+                return cursor;
+            }
+
             case URL_SIMINFO: {
                 qb.setTables(SIMINFO_TABLE);
                 break;
@@ -2058,6 +2507,11 @@
             }
         }
 
+        // appendWhere doesn't add ANDs so we do it ourselves
+        if (constraints.size() > 0) {
+            qb.appendWhere(TextUtils.join(" AND ", constraints));
+        }
+
         if (match != URL_SIMINFO) {
             // Determine if we need to do a check for fields in the selection
             boolean selectionContainsSensitiveFields;
@@ -2144,12 +2598,15 @@
             return "vnd.android.cursor.dir/telephony-carrier";
 
         case URL_ID:
+        case URL_FILTERED_ID:
             return "vnd.android.cursor.item/telephony-carrier";
 
         case URL_PREFERAPN_USING_SUBID:
         case URL_PREFERAPN_NO_UPDATE_USING_SUBID:
         case URL_PREFERAPN:
         case URL_PREFERAPN_NO_UPDATE:
+        case URL_PREFERAPNSET:
+        case URL_PREFERAPNSET_USING_SUBID:
             return "vnd.android.cursor.item/telephony-carrier";
 
         default:
@@ -2198,11 +2655,49 @@
         return rowAndNotify.first;
     }
 
+    /**
+     * Internal insert function to prevent code duplication for URL_TELEPHONY and URL_DPC.
+     *
+     * @param values the value that caller wants to insert
+     * @return a pair in which the first element refers to the Uri for the row inserted, the second
+     *         element refers to whether sends out nofitication.
+     */
+    private Pair<Uri, Boolean> insertRowWithValue(ContentValues values) {
+        Uri result = null;
+        boolean notify = false;
+        SQLiteDatabase db = getWritableDatabase();
+
+        try {
+            // Abort on conflict of unique fields and attempt merge
+            long rowID = db.insertWithOnConflict(CARRIERS_TABLE, null, values,
+                    SQLiteDatabase.CONFLICT_ABORT);
+            if (rowID >= 0) {
+                result = ContentUris.withAppendedId(CONTENT_URI, rowID);
+                notify = true;
+            }
+            if (VDBG) log("insert: inserted " + values.toString() + " rowID = " + rowID);
+        } catch (SQLException e) {
+            log("insert: exception " + e);
+            // Insertion failed which could be due to a conflict. Check if that is the case
+            // and merge the entries
+            Cursor oldRow = DatabaseHelper.selectConflictingRow(db, CARRIERS_TABLE, values);
+            if (oldRow != null) {
+                ContentValues mergedValues = new ContentValues();
+                DatabaseHelper.mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
+                        mergedValues, false, getContext());
+                oldRow.close();
+                notify = true;
+            }
+        }
+        return Pair.create(result, notify);
+    }
+
     private Pair<Uri, Boolean> insertSingleRow(Uri url, ContentValues initialValues) {
         Uri result = null;
         int subId = SubscriptionManager.getDefaultSubscriptionId();
 
         checkPermission();
+        syncBearerBitmaskAndNetworkTypeBitmask(initialValues);
 
         boolean notify = false;
         SQLiteDatabase db = getWritableDatabase();
@@ -2233,34 +2728,14 @@
 
                 values = DatabaseHelper.setDefaultValue(values);
                 if (!values.containsKey(EDITED)) {
-                    values.put(EDITED, USER_EDITED);
+                    values.put(EDITED, CARRIER_EDITED);
                 }
+                // Owned_by should be others if inserted via general uri.
+                values.put(OWNED_BY, OWNED_BY_OTHERS);
 
-                try {
-                    // Replace on conflict so that if same APN is present in db with edited
-                    // as UNEDITED or USER/CARRIER_DELETED, it is replaced with
-                    // edited USER/CARRIER_EDITED
-                    long rowID = db.insertWithOnConflict(CARRIERS_TABLE, null, values,
-                            SQLiteDatabase.CONFLICT_REPLACE);
-                    if (rowID >= 0) {
-                        result = ContentUris.withAppendedId(CONTENT_URI, rowID);
-                        notify = true;
-                    }
-                    if (VDBG) log("insert: inserted " + values.toString() + " rowID = " + rowID);
-                } catch (SQLException e) {
-                    log("insert: exception " + e);
-                    // Insertion failed which could be due to a conflict. Check if that is the case
-                    // and merge the entries
-                    Cursor oldRow = DatabaseHelper.selectConflictingRow(db, CARRIERS_TABLE, values);
-                    if (oldRow != null) {
-                        ContentValues mergedValues = new ContentValues();
-                        DatabaseHelper.mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
-                                mergedValues, false, getContext());
-                        oldRow.close();
-                        notify = true;
-                    }
-                }
-
+                Pair<Uri, Boolean> ret = insertRowWithValue(values);
+                result = ret.first;
+                notify = ret.second;
                 break;
             }
 
@@ -2323,6 +2798,32 @@
                 break;
             }
 
+            case URL_DPC: {
+                ensureCallingFromSystemOrPhoneUid("URL_DPC called from non SYSTEM_UID.");
+
+                ContentValues values;
+                if (initialValues != null) {
+                    values = new ContentValues(initialValues);
+                } else {
+                    values = new ContentValues();
+                }
+
+                // Owned_by should be DPC if inserted via URL_DPC.
+                values.put(OWNED_BY, OWNED_BY_DPC);
+                // DPC records should not be user editable.
+                values.put(USER_EDITABLE, false);
+
+                final long rowID = db.insertWithOnConflict(CARRIERS_TABLE, null, values,
+                        SQLiteDatabase.CONFLICT_IGNORE);
+                if (rowID >= 0) {
+                    result = ContentUris.withAppendedId(CONTENT_URI, rowID);
+                    notify = true;
+                }
+                if (VDBG) log("insert: inserted " + values.toString() + " rowID = " + rowID);
+
+                break;
+            }
+
             case URL_SIMINFO: {
                long id = db.insert(SIMINFO_TABLE, null, initialValues);
                result = ContentUris.withAppendedId(SubscriptionManager.CONTENT_URI, id);
@@ -2334,8 +2835,7 @@
     }
 
     @Override
-    public synchronized int delete(Uri url, String where, String[] whereArgs)
-    {
+    public synchronized int delete(Uri url, String where, String[] whereArgs) {
         int count = 0;
         int subId = SubscriptionManager.getDefaultSubscriptionId();
         String userOrCarrierEdited = ") and (" +
@@ -2359,7 +2859,8 @@
                 // Delete preferred APN for all subIds
                 deletePreferredApnId();
                 // Delete unedited entries
-                count = db.delete(CARRIERS_TABLE, "(" + where + unedited, whereArgs);
+                count = db.delete(CARRIERS_TABLE, "(" + where + unedited + " and " +
+                        IS_NOT_OWNED_BY_DPC, whereArgs);
                 break;
             }
 
@@ -2380,10 +2881,11 @@
             case URL_TELEPHONY:
             {
                 // Delete user/carrier edited entries
-                count = db.delete(CARRIERS_TABLE, "(" + where + userOrCarrierEdited, whereArgs);
+                count = db.delete(CARRIERS_TABLE, "(" + where + userOrCarrierEdited
+                        + " and " + IS_NOT_OWNED_BY_DPC, whereArgs);
                 // Otherwise mark as user deleted instead of deleting
-                count += db.update(CARRIERS_TABLE, cv, "(" + where + notUserOrCarrierEdited,
-                        whereArgs);
+                count += db.update(CARRIERS_TABLE, cv, "(" + where +
+                        notUserOrCarrierEdited + " and " + IS_NOT_OWNED_BY_DPC, whereArgs);
                 break;
             }
 
@@ -2403,10 +2905,11 @@
             case URL_CURRENT:
             {
                 // Delete user/carrier edited entries
-                count = db.delete(CARRIERS_TABLE, "(" + where + userOrCarrierEdited, whereArgs);
+                count = db.delete(CARRIERS_TABLE, "(" + where + userOrCarrierEdited
+                        + " and " + IS_NOT_OWNED_BY_DPC, whereArgs);
                 // Otherwise mark as user deleted instead of deleting
-                count += db.update(CARRIERS_TABLE, cv, "(" + where + notUserOrCarrierEdited,
-                        whereArgs);
+                count += db.update(CARRIERS_TABLE, cv, "(" + where +
+                        notUserOrCarrierEdited + " and " + IS_NOT_OWNED_BY_DPC, whereArgs);
                 break;
             }
 
@@ -2414,11 +2917,13 @@
             {
                 // Delete user/carrier edited entries
                 count = db.delete(CARRIERS_TABLE,
-                        "(" + _ID + "=?" + userOrCarrierEdited,
+                        "(" + _ID + "=?" + userOrCarrierEdited +
+                                " and " + IS_NOT_OWNED_BY_DPC,
                         new String[] { url.getLastPathSegment() });
                 // Otherwise mark as user deleted instead of deleting
                 count += db.update(CARRIERS_TABLE, cv,
-                        "(" + _ID + "=?" + notUserOrCarrierEdited,
+                        "(" + _ID + "=?" + notUserOrCarrierEdited +
+                                " and " + IS_NOT_OWNED_BY_DPC,
                         new String[]{url.getLastPathSegment() });
                 break;
             }
@@ -2432,11 +2937,15 @@
                     throw new IllegalArgumentException("Invalid subId " + url);
                 }
                 if (DBG) log("subIdString = " + subIdString + " subId = " + subId);
-                // FIXME use subId in query
             }
+            // intentional fall through from above case
+
             case URL_RESTOREAPN: {
                 count = 1;
                 restoreDefaultAPN(subId);
+                getContext().getContentResolver().notifyChange(
+                        Uri.withAppendedPath(CONTENT_URI, "restore/subId/" + subId), null,
+                        true, UserHandle.USER_ALL);
                 break;
             }
 
@@ -2461,6 +2970,15 @@
                 break;
             }
 
+            case URL_DPC_ID: {
+                ensureCallingFromSystemOrPhoneUid("URL_DPC_ID called from non SYSTEM_UID.");
+
+                // Only delete if owned by DPC.
+                count = db.delete(CARRIERS_TABLE, "(" + _ID + "=?)" + " and " + IS_OWNED_BY_DPC,
+                        new String[] { url.getLastPathSegment() });
+                break;
+            }
+
             case URL_SIMINFO: {
                 count = db.delete(SIMINFO_TABLE, where, whereArgs);
                 break;
@@ -2493,6 +3011,7 @@
         int subId = SubscriptionManager.getDefaultSubscriptionId();
 
         checkPermission();
+        syncBearerBitmaskAndNetworkTypeBitmask(values);
 
         SQLiteDatabase db = getWritableDatabase();
         int match = s_urlMatcher.match(url);
@@ -2515,13 +3034,14 @@
             case URL_TELEPHONY:
             {
                 if (!values.containsKey(EDITED)) {
-                    values.put(EDITED, USER_EDITED);
+                    values.put(EDITED, CARRIER_EDITED);
                 }
 
                 // Replace on conflict so that if same APN is present in db with edited
                 // as UNEDITED or USER/CARRIER_DELETED, it is replaced with
                 // edited USER/CARRIER_EDITED
-                count = db.updateWithOnConflict(CARRIERS_TABLE, values, where, whereArgs,
+                count = db.updateWithOnConflict(CARRIERS_TABLE, values, where +
+                                " and " + IS_NOT_OWNED_BY_DPC, whereArgs,
                         SQLiteDatabase.CONFLICT_REPLACE);
                 break;
             }
@@ -2543,31 +3063,46 @@
             case URL_CURRENT:
             {
                 if (!values.containsKey(EDITED)) {
-                    values.put(EDITED, USER_EDITED);
+                    values.put(EDITED, CARRIER_EDITED);
                 }
                 // Replace on conflict so that if same APN is present in db with edited
                 // as UNEDITED or USER/CARRIER_DELETED, it is replaced with
                 // edited USER/CARRIER_EDITED
-                count = db.updateWithOnConflict(CARRIERS_TABLE, values, where, whereArgs,
-                        SQLiteDatabase.CONFLICT_REPLACE);
+                count = db.updateWithOnConflict(CARRIERS_TABLE, values, where +
+                                " and " + IS_NOT_OWNED_BY_DPC,
+                        whereArgs, SQLiteDatabase.CONFLICT_REPLACE);
                 break;
             }
 
             case URL_ID:
             {
+                String rowID = url.getLastPathSegment();
                 if (where != null || whereArgs != null) {
                     throw new UnsupportedOperationException(
                             "Cannot update URL " + url + " with a where clause");
                 }
                 if (!values.containsKey(EDITED)) {
-                    values.put(EDITED, USER_EDITED);
+                    values.put(EDITED, CARRIER_EDITED);
                 }
-                // Replace on conflict so that if same APN is present in db with edited
-                // as UNEDITED or USER/CARRIER_DELETED, it is replaced with
-                // edited USER/CARRIER_EDITED
-                count = db.updateWithOnConflict(CARRIERS_TABLE, values,
-                        _ID + "=?", new String[] { url.getLastPathSegment() },
-                        SQLiteDatabase.CONFLICT_REPLACE);
+
+                try {
+                    count = db.updateWithOnConflict(CARRIERS_TABLE, values, _ID + "=?" + " and " +
+                            IS_NOT_OWNED_BY_DPC, new String[] { rowID },
+                            SQLiteDatabase.CONFLICT_ABORT);
+                } catch (SQLException e) {
+                    // Update failed which could be due to a conflict. Check if that is
+                    // the case and merge the entries
+                    log("update: exception " + e);
+                    Cursor oldRow = DatabaseHelper.selectConflictingRow(db, CARRIERS_TABLE, values);
+                    if (oldRow != null) {
+                        ContentValues mergedValues = new ContentValues();
+                        DatabaseHelper.mergeFieldsAndUpdateDb(db, CARRIERS_TABLE, oldRow, values,
+                                mergedValues, false, getContext());
+                        oldRow.close();
+                        db.delete(CARRIERS_TABLE, _ID + "=?" + " and " + IS_NOT_OWNED_BY_DPC,
+                                new String[] { rowID });
+                    }
+                }
                 break;
             }
 
@@ -2599,6 +3134,32 @@
                 break;
             }
 
+            case URL_DPC_ID:
+            {
+                ensureCallingFromSystemOrPhoneUid("URL_DPC_ID called from non SYSTEM_UID.");
+
+                if (where != null || whereArgs != null) {
+                    throw new UnsupportedOperationException(
+                            "Cannot update URL " + url + " with a where clause");
+                }
+                count = db.updateWithOnConflict(CARRIERS_TABLE, values,
+                        _ID + "=?" + " and " + IS_OWNED_BY_DPC,
+                        new String[] { url.getLastPathSegment() }, SQLiteDatabase.CONFLICT_IGNORE);
+                break;
+            }
+
+            case URL_ENFORCE_MANAGED: {
+                ensureCallingFromSystemOrPhoneUid(
+                        "URL_ENFORCE_MANAGED called from non SYSTEM_UID.");
+                if (values != null) {
+                    if (values.containsKey(ENFORCED_KEY)) {
+                        setManagedApnEnforced(values.getAsBoolean(ENFORCED_KEY));
+                        count = 1;
+                    }
+                }
+                break;
+            }
+
             case URL_SIMINFO: {
                 count = db.update(SIMINFO_TABLE, values, where, whereArgs);
                 uriType = URL_SIMINFO;
@@ -2650,9 +3211,19 @@
 
     private void restoreDefaultAPN(int subId) {
         SQLiteDatabase db = getWritableDatabase();
+        TelephonyManager telephonyManager =
+                (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
+        String where = null;
+        if (telephonyManager.getPhoneCount() > 1) {
+            where = getWhereClauseForRestoreDefaultApn(db, subId);
+        }
+        if (TextUtils.isEmpty(where)) {
+            where = IS_NOT_OWNED_BY_DPC;
+        }
+        log("restoreDefaultAPN: where: " + where);
 
         try {
-            db.delete(CARRIERS_TABLE, null, null);
+            db.delete(CARRIERS_TABLE, where, null);
         } catch (SQLException e) {
             loge("got exception when deleting to restore: " + e);
         }
@@ -2678,6 +3249,54 @@
         }
     }
 
+    private String getWhereClauseForRestoreDefaultApn(SQLiteDatabase db, int subId) {
+        IccRecords iccRecords = getIccRecords(subId);
+        if (iccRecords == null) {
+            return null;
+        }
+        TelephonyManager telephonyManager =
+                (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
+        String simOperator = telephonyManager.getSimOperator(subId);
+        Cursor cursor = db.query(CARRIERS_TABLE, new String[] {MVNO_TYPE, MVNO_MATCH_DATA},
+                NUMERIC + "='" + simOperator + "'", null, null, null, DEFAULT_SORT_ORDER);
+        String where = null;
+
+        if (cursor != null) {
+            cursor.moveToFirst();
+            while (!cursor.isAfterLast()) {
+                String mvnoType = cursor.getString(0 /* MVNO_TYPE index */);
+                String mvnoMatchData = cursor.getString(1 /* MVNO_MATCH_DATA index */);
+                if (!TextUtils.isEmpty(mvnoType) && !TextUtils.isEmpty(mvnoMatchData)
+                        && ApnSetting.mvnoMatches(iccRecords, mvnoType, mvnoMatchData)) {
+                    where = NUMERIC + "='" + simOperator + "'"
+                            + " AND " + MVNO_TYPE + "='" + mvnoType + "'"
+                            + " AND " + MVNO_MATCH_DATA + "='" + mvnoMatchData + "'"
+                            + " AND " + IS_NOT_OWNED_BY_DPC;
+                    break;
+                }
+                cursor.moveToNext();
+            }
+            cursor.close();
+
+            if (TextUtils.isEmpty(where)) {
+                where = NUMERIC + "='" + simOperator + "'"
+                        + " AND (" + MVNO_TYPE + "='' OR " + MVNO_MATCH_DATA + "='')"
+                        + " AND " + IS_NOT_OWNED_BY_DPC;
+            }
+        }
+        return where;
+    }
+
+    @VisibleForTesting
+    IccRecords getIccRecords(int subId) {
+        TelephonyManager telephonyManager =
+                TelephonyManager.from(getContext()).createForSubscriptionId(subId);
+        int family = telephonyManager.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ?
+                UiccController.APP_FAM_3GPP : UiccController.APP_FAM_3GPP2;
+        return UiccController.getInstance().getIccRecords(
+                SubscriptionManager.getPhoneId(subId), family);
+    }
+
     private synchronized void updateApnDb() {
         if (apnSourceServiceExists(getContext())) {
             loge("called updateApnDb when apn source service exists");
@@ -2697,7 +3316,7 @@
         // Delete entries in db
         try {
             if (VDBG) log("updateApnDb: deleting edited=UNEDITED entries");
-            db.delete(CARRIERS_TABLE, IS_UNEDITED, null);
+            db.delete(CARRIERS_TABLE, IS_UNEDITED + " and " + IS_NOT_OWNED_BY_DPC, null);
         } catch (SQLException e) {
             loge("got exception when deleting to update: " + e);
         }
@@ -2711,6 +3330,31 @@
     }
 
     /**
+     * Sync the bearer bitmask and network type bitmask when inserting and updating.
+     * Since bearerBitmask is deprecating, map the networkTypeBitmask to bearerBitmask if
+     * networkTypeBitmask was provided. But if networkTypeBitmask was not provided, map the
+     * bearerBitmask to networkTypeBitmask.
+     */
+    private static void syncBearerBitmaskAndNetworkTypeBitmask(ContentValues values) {
+        if (values.containsKey(NETWORK_TYPE_BITMASK)) {
+            int convertedBitmask = ServiceState.convertNetworkTypeBitmaskToBearerBitmask(
+                    values.getAsInteger(NETWORK_TYPE_BITMASK));
+            if (values.containsKey(BEARER_BITMASK)
+                    && convertedBitmask != values.getAsInteger(BEARER_BITMASK)) {
+                loge("Network type bitmask and bearer bitmask are not compatible.");
+            }
+            values.put(BEARER_BITMASK, ServiceState.convertNetworkTypeBitmaskToBearerBitmask(
+                    values.getAsInteger(NETWORK_TYPE_BITMASK)));
+        } else {
+            if (values.containsKey(BEARER_BITMASK)) {
+                int convertedBitmask = ServiceState.convertBearerBitmaskToNetworkTypeBitmask(
+                        values.getAsInteger(BEARER_BITMASK));
+                values.put(NETWORK_TYPE_BITMASK, convertedBitmask);
+            }
+        }
+    }
+
+    /**
      * Log with debug
      *
      * @param s is string log
diff --git a/tests/Android.mk b/tests/Android.mk
index ffd2e39..14f528f 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -4,15 +4,20 @@
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_STATIC_JAVA_LIBRARIES := mockito-target \
-                               legacy-android-test \
                                compatibility-device-util \
                                android-support-test
 
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
+LOCAL_JAVA_LIBRARIES := \
+    android.test.runner \
+    telephony-common \
+    android.test.base \
+    android.test.mock \
+
 
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 
 LOCAL_PACKAGE_NAME := TelephonyProviderTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 LOCAL_CERTIFICATE := platform
 
diff --git a/tests/AndroidTest.xml b/tests/AndroidTest.xml
index 2a691a7..129f4d9 100644
--- a/tests/AndroidTest.xml
+++ b/tests/AndroidTest.xml
@@ -23,5 +23,6 @@
     <test class="com.android.tradefed.testtype.InstrumentationTest" >
         <option name="package" value="com.android.providers.telephony.tests" />
         <option name="runner" value="android.test.InstrumentationTestRunner" />
+        <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java b/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java
new file mode 100644
index 0000000..4adcf43
--- /dev/null
+++ b/tests/src/com/android/providers/telephony/CarrierIdProviderTest.java
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.providers.telephony;
+
+import android.content.ContentValues;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Telephony.CarrierId;
+import android.test.mock.MockContentResolver;
+import android.test.mock.MockContext;
+import android.util.Log;
+
+import com.android.internal.telephony.SubscriptionController;
+
+import junit.framework.TestCase;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Tests for testing CRUD operations of CarrierIdProvider.
+ * Uses CarrierIdProviderTestable to set up in-memory database
+ *
+ * Build, install and run the tests by running the commands below:
+ *     runtest --path <dir or file>
+ *     runtest --path <dir or file> --test-method <testMethodName>
+ *     e.g.)
+ *         runtest --path tests/src/com/android/providers/telephony/CarrierIdProviderTest.java \
+ *                 --test-method testInsertCarrierInfo
+ */
+public class CarrierIdProviderTest extends TestCase {
+
+    private static final String TAG = CarrierIdProviderTest.class.getSimpleName();
+
+    private static final String dummy_mccmnc = "MCCMNC_DUMMY";
+    private static final String dummy_gid1 = "GID1_DUMMY";
+    private static final String dummy_gid2 = "GID2_DUMMY";
+    private static final String dummy_plmn = "PLMN_DUMMY";
+    private static final String dummy_imsi_prefix = "IMSI_PREFIX_DUMMY";
+    private static final String dummy_spn = "SPN_DUMMY";
+    private static final String dummy_apn = "APN_DUMMY";
+    private static final String dummy_iccid_prefix = "ICCID_PREFIX_DUMMY";
+    private static final String dummy_name = "NAME_DUMMY";
+    private static final int dummy_cid = 0;
+
+    private MockContextWithProvider mContext;
+    private MockContentResolver mContentResolver;
+    private CarrierIdProviderTestable mCarrierIdProviderTestable;
+    private FakeContentObserver mContentObserver;
+    private SharedPreferences mSharedPreferences = mock(SharedPreferences.class);
+    private SubscriptionController mSubController = mock(SubscriptionController.class);
+
+    private class FakeContentResolver extends MockContentResolver {
+        @Override
+        public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
+            super.notifyChange(uri, observer, syncToNetwork);
+            Log.d(TAG, "onChanged(uri=" + uri + ")" + observer);
+            mContentObserver.dispatchChange(false, uri);
+        }
+    }
+
+    private class FakeContentObserver extends ContentObserver {
+        private boolean changed = false;
+        private FakeContentObserver(Handler handler) {
+            super(handler);
+        }
+        @Override
+        public void onChange(boolean selfChange) {
+            changed = true;
+        }
+    }
+
+    /**
+     * This is used to give the CarrierIdProviderTest a mocked context which takes a
+     * CarrierIdProvider and attaches it to the ContentResolver.
+     */
+    private class MockContextWithProvider extends MockContext {
+        private final MockContentResolver mResolver;
+
+        public MockContextWithProvider(CarrierIdProvider carrierIdProvider) {
+            mResolver = new FakeContentResolver();
+
+            ProviderInfo providerInfo = new ProviderInfo();
+            providerInfo.authority = CarrierIdProvider.AUTHORITY;
+
+            // Add context to given carrierIdProvider
+            carrierIdProvider.attachInfoForTesting(this, providerInfo);
+            Log.d(TAG, "MockContextWithProvider: carrierIdProvider.getContext(): "
+                    + carrierIdProvider.getContext());
+
+            // Add given carrierIdProvider to mResolver, so that mResolver can send queries
+            // to the provider.
+            mResolver.addProvider(CarrierIdProvider.AUTHORITY, carrierIdProvider);
+            Log.d(TAG, "MockContextWithProvider: Add carrierIdProvider to mResolver");
+        }
+
+        @Override
+        public Object getSystemService(String name) {
+            Log.d(TAG, "getSystemService: returning null");
+            return null;
+        }
+
+        @Override
+        public MockContentResolver getContentResolver() {
+            return mResolver;
+        }
+
+        @Override
+        public int checkCallingOrSelfPermission(String permission) {
+            return PackageManager.PERMISSION_GRANTED;
+        }
+
+        @Override
+        public SharedPreferences getSharedPreferences(String name, int mode) {
+            return mSharedPreferences;
+        }
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mCarrierIdProviderTestable = new CarrierIdProviderTestable();
+        mContext = new MockContextWithProvider(mCarrierIdProviderTestable);
+        mContentResolver = mContext.getContentResolver();
+        mContentObserver = new FakeContentObserver(null);
+        Field field = SubscriptionController.class.getDeclaredField("sInstance");
+        field.setAccessible(true);
+        field.set(null, mSubController);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mCarrierIdProviderTestable.closeDatabase();
+        super.tearDown();
+    }
+
+    /**
+     * Test inserting values in carrier identification table.
+     */
+    @Test
+    public void testInsertCarrierInfo() {
+        try {
+            mContentResolver.insert(CarrierId.All.CONTENT_URI, createCarrierInfoInternal());
+            Cursor countCursor = mContentResolver.query(CarrierId.All.CONTENT_URI,
+                    new String[]{"count(*) AS count"},
+                    null,
+                    null,
+                    null);
+            countCursor.moveToFirst();
+            assertEquals(1, countCursor.getInt(0));
+            assertTrue(mContentObserver.changed);
+        } catch (Exception e) {
+            Log.d(TAG, "Error inserting carrier info:" + e);
+        }
+    }
+
+    /**
+     * Test invalid insertion of duplicate info
+     */
+    @Test
+    public void testDuplicateInsertionCarrierInfo() {
+        try {
+            //insert same row twice to break uniqueness constraint
+            ContentValues contentValues = createCarrierInfoInternal();
+            mContentResolver.insert(CarrierId.All.CONTENT_URI, contentValues);
+            mContentResolver.insert(CarrierId.All.CONTENT_URI, contentValues);
+            Assert.fail("should throw an exception for duplicate carrier info");
+        } catch (Exception e) {
+            Log.d(TAG, "Error inserting carrier info:" + e);
+        }
+    }
+
+    /**
+     * Test invalid insertion of null mccmnc
+     */
+    @Test
+    public void testInvalidInsertionCarrierInfo() {
+        try {
+            //insert a row with null mnccmnc to break not null constraint
+            ContentValues contentValues = new ContentValues();
+            contentValues.put(CarrierId.All.GID1, dummy_gid1);
+            mContentResolver.insert(CarrierId.All.CONTENT_URI, contentValues);
+            Assert.fail("should throw an exception for null mccmnc");
+        } catch (SQLException e) {
+            Log.d(TAG, "Error inserting carrier info:" + e);
+            assertFalse(mContentObserver.changed);
+        }
+    }
+
+    /**
+     * Test delete.
+     */
+    @Test
+    public void testDeleteCarrierInfo() {
+        try {
+            mContentResolver.insert(CarrierId.All.CONTENT_URI,
+                    createCarrierInfoInternal());
+        } catch (Exception e) {
+            Log.d(TAG, "Error inserting carrier info:" + e);
+        }
+        int numRowsDeleted = -1;
+        try {
+            String whereClause = CarrierId.All.MCCMNC + "=?";
+            String[] whereArgs = new String[] { dummy_mccmnc };
+            numRowsDeleted = mContentResolver.delete(CarrierId.All.CONTENT_URI,
+                    whereClause, whereArgs);
+        } catch (Exception e) {
+            Log.d(TAG, "Error deleting values:" + e);
+        }
+        assertEquals(1, numRowsDeleted);
+        assertTrue(mContentObserver.changed);
+    }
+
+    /**
+     * Test update & query.
+     */
+    @Test
+    public void testUpdateCarrierInfo() {
+        int cid = -1;
+        ContentValues contentValues = createCarrierInfoInternal();
+
+        try {
+            mContentResolver.insert(CarrierId.All.CONTENT_URI, contentValues);
+        } catch (Exception e) {
+            Log.d(TAG, "Error inserting carrierInfo:" + e);
+        }
+
+        try {
+            contentValues.put(CarrierId.CARRIER_ID, 1);
+            mContentResolver.update(CarrierId.All.CONTENT_URI, contentValues,
+                    CarrierId.All.MCCMNC + "=?", new String[] { dummy_mccmnc });
+        } catch (Exception e) {
+            Log.d(TAG, "Error updating values:" + e);
+        }
+
+        try {
+            Cursor findEntry = mContentResolver.query(CarrierId.All.CONTENT_URI,
+                    new String[] { CarrierId.CARRIER_ID},
+                    CarrierId.All.MCCMNC + "=?", new String[] { dummy_mccmnc },
+                    null);
+            findEntry.moveToFirst();
+            cid = findEntry.getInt(0);
+        } catch (Exception e) {
+            Log.d(TAG, "Query failed:" + e);
+        }
+        assertEquals(1, cid);
+        assertTrue(mContentObserver.changed);
+    }
+
+    @Test
+    public void testMultiRowInsertionQuery() {
+        ContentValues contentValues = createCarrierInfoInternal();
+
+        try {
+            // insert a MVNO
+            mContentResolver.insert(CarrierId.All.CONTENT_URI, contentValues);
+            // insert its MNO
+            contentValues = new ContentValues();
+            contentValues.put(CarrierId.All.MCCMNC, dummy_mccmnc);
+            contentValues.put(CarrierId.CARRIER_ID, 1);
+            mContentResolver.insert(CarrierId.All.CONTENT_URI, contentValues);
+        } catch (Exception e) {
+            Log.d(TAG, "Error inserting carrierInfo:" + e);
+        }
+
+        Cursor findEntry = null;
+        String[] columns = {CarrierId.CARRIER_ID, CarrierId.All.ICCID_PREFIX};
+        try {
+            findEntry = mContentResolver.query(CarrierId.All.CONTENT_URI, columns,
+                    CarrierId.All.MCCMNC + "=?", new String[] { dummy_mccmnc },
+                    null);
+        } catch (Exception e) {
+            Log.d(TAG, "Query failed:" + e);
+        }
+        assertEquals(2, findEntry.getCount());
+
+        try {
+            // query based on mccmnc & gid1 & iccid_prefix
+            findEntry = mContentResolver.query(CarrierId.All.CONTENT_URI, columns,
+                    CarrierId.All.MCCMNC + "=? and "
+                    + CarrierId.All.GID1 + "=? and "
+                    + CarrierId.All.ICCID_PREFIX + "=?",
+                    new String[] { dummy_mccmnc, dummy_gid1, dummy_iccid_prefix }, null);
+        } catch (Exception e) {
+            Log.d(TAG, "Query failed:" + e);
+        }
+        assertEquals(1, findEntry.getCount());
+        findEntry.moveToFirst();
+        assertEquals(dummy_cid, findEntry.getInt(0));
+        assertEquals(dummy_iccid_prefix, findEntry.getString(1));
+    }
+
+    @Test
+    public void testGetVersion() {
+        doReturn(5).when(mSharedPreferences).getInt(eq("version"), anyInt());
+        int version = 0;
+        try {
+            Cursor cursor = mContext.getContentResolver().query(
+                    Uri.withAppendedPath(CarrierId.All.CONTENT_URI,
+                            "get_version"), null, null, null);
+            cursor.moveToFirst();
+            version = cursor.getInt(0);
+        } catch (Exception e) {
+            Log.d(TAG, "Error querying carrier list version:" + e);
+        }
+        assertEquals(5, version);
+    }
+
+    @Test
+    public void testUpdateCurrentSubscription() {
+        // update carrier id for subId 1
+        try {
+            ContentValues cv = new ContentValues();
+            cv.put(CarrierId.CARRIER_ID, dummy_cid);
+            cv.put(CarrierId.CARRIER_NAME, dummy_name);
+            doReturn(1).when(mSubController).getDefaultSubId();
+            doReturn(true).when(mSubController).isActiveSubId(eq(1));
+            mContext.getContentResolver().update(Uri.withAppendedPath(CarrierId.CONTENT_URI,
+                    "1"), cv, null, null);
+        } catch (Exception e) {
+            Log.d(TAG, "Error updating current subscription: " + e);
+            e.printStackTrace();
+        }
+        int carrierId = -1;
+        String carrierName = null;
+
+        // query carrier id for subId 1
+        try {
+            final Cursor c = mContext.getContentResolver().query(
+                    Uri.withAppendedPath(CarrierId.CONTENT_URI, "1"),
+                    new String[] {CarrierId.CARRIER_ID, CarrierId.CARRIER_NAME}, null, null);
+            c.moveToFirst();
+            carrierId = c.getInt(0);
+            carrierName = c.getString(1);
+        } catch (Exception e) {
+            Log.d(TAG, "Error query current subscription: " + e);
+        }
+        assertEquals(dummy_cid, carrierId);
+        assertEquals(dummy_name, carrierName);
+
+        // query carrier id for subId 2
+        int count  = -1;
+        try {
+            final Cursor c = mContext.getContentResolver().query(
+                    Uri.withAppendedPath(CarrierId.CONTENT_URI, "2"),
+                    new String[]{CarrierId.CARRIER_ID, CarrierId.CARRIER_NAME}, null, null);
+            count = c.getCount();
+        } catch (Exception e) {
+            Log.d(TAG, "Error query current subscription: " + e);
+        }
+        assertEquals(0, count);
+
+        // query without subId, expect return carrier id of the default subId
+        try {
+            final Cursor c = mContext.getContentResolver().query(CarrierId.CONTENT_URI,
+                    new String[]{CarrierId.CARRIER_ID, CarrierId.CARRIER_NAME}, null, null);
+            c.moveToFirst();
+            carrierId = c.getInt(0);
+            carrierName = c.getString(1);
+        } catch (Exception e) {
+            Log.d(TAG, "Error query current subscription: " + e);
+        }
+        assertEquals(dummy_cid, carrierId);
+        assertEquals(dummy_name, carrierName);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testQueryCurrrentSubscription_wrongProjection() {
+        mContext.getContentResolver().query(CarrierId.CONTENT_URI,
+                new String[]{CarrierId.CARRIER_ID, CarrierId.CARRIER_NAME, CarrierId.All.MCCMNC},
+                null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testQueryWithWrongURI() {
+        try {
+            mContext.getContentResolver().query(Uri.withAppendedPath(
+                    CarrierId.CONTENT_URI, "invalid"),
+                    new String[]{CarrierId.CARRIER_ID, CarrierId.CARRIER_NAME}, null, null);
+            Assert.fail("should throw an exception for wrong uri");
+        } catch (IllegalArgumentException ex) {
+        }
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testUpdateCurrentSubscription_WrongURI() {
+        try {
+            ContentValues cv = new ContentValues();
+            cv.put(CarrierId.CARRIER_ID, dummy_cid);
+            cv.put(CarrierId.CARRIER_NAME, dummy_name);
+            doReturn(1).when(mSubController).getDefaultSubId();
+            doReturn(true).when(mSubController).isActiveSubId(eq(1));
+
+            mContext.getContentResolver().update(CarrierId.CONTENT_URI, cv, null, null);
+            Assert.fail("should throw an exception for wrong uri");
+        } catch (IllegalArgumentException ex) {
+            assertFalse(mContentObserver.changed);
+        }
+    }
+
+    private static ContentValues createCarrierInfoInternal() {
+        ContentValues contentValues = new ContentValues();
+        contentValues.put(CarrierId.All.MCCMNC, dummy_mccmnc);
+        contentValues.put(CarrierId.All.GID1, dummy_gid1);
+        contentValues.put(CarrierId.All.GID2, dummy_gid2);
+        contentValues.put(CarrierId.All.PLMN, dummy_plmn);
+        contentValues.put(CarrierId.All.IMSI_PREFIX_XPATTERN, dummy_imsi_prefix);
+        contentValues.put(CarrierId.All.SPN, dummy_spn);
+        contentValues.put(CarrierId.All.APN, dummy_apn);
+        contentValues.put(CarrierId.All.ICCID_PREFIX, dummy_iccid_prefix);
+        contentValues.put(CarrierId.CARRIER_NAME, dummy_name);
+        contentValues.put(CarrierId.CARRIER_ID, dummy_cid);
+        return contentValues;
+    }
+}
diff --git a/tests/src/com/android/providers/telephony/CarrierIdProviderTestable.java b/tests/src/com/android/providers/telephony/CarrierIdProviderTestable.java
new file mode 100644
index 0000000..8468801
--- /dev/null
+++ b/tests/src/com/android/providers/telephony/CarrierIdProviderTestable.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.providers.telephony;
+
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+/**
+ * A subclass of CarrierIdProvider used for testing on an in-memory database
+ */
+public class CarrierIdProviderTestable extends CarrierIdProvider {
+    private static final String TAG = CarrierIdProviderTestable.class.getSimpleName();
+
+    private InMemoryCarrierIdProviderDbHelper mDbHelper;
+
+    @Override
+    public boolean onCreate() {
+        Log.d(TAG, "onCreate called: mDbHelper = new InMemoryCarrierIdProviderDbHelper()");
+        mDbHelper = new InMemoryCarrierIdProviderDbHelper();
+        return true;
+    }
+
+    // close mDbHelper database object
+    protected void closeDatabase() {
+        mDbHelper.close();
+    }
+
+    @Override
+    SQLiteDatabase getReadableDatabase() {
+        Log.d(TAG, "getReadableDatabase called" + mDbHelper.getReadableDatabase());
+        return mDbHelper.getReadableDatabase();
+    }
+
+    @Override
+    SQLiteDatabase getWritableDatabase() {
+        Log.d(TAG, "getWritableDatabase called" + mDbHelper.getWritableDatabase());
+        return mDbHelper.getWritableDatabase();
+    }
+
+    /**
+     * An in memory DB for CarrierIdProviderTestable to use
+     */
+    public static class InMemoryCarrierIdProviderDbHelper extends SQLiteOpenHelper {
+        public InMemoryCarrierIdProviderDbHelper() {
+            super(null,      // no context is needed for in-memory db
+                  null,      // db file name is null for in-memory db
+                  null,      // CursorFactory is null by default
+                  1);        // db version is no-op for tests
+            Log.d(TAG, "InMemoryCarrierIdProviderDbHelper creating in-memory database");
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+            //set up the Carrier id table
+            Log.d(TAG, "InMemoryCarrierIdProviderDbHelper onCreate creating the carrier infp table");
+            db.execSQL(CarrierIdProvider.getStringForCarrierIdTableCreation(
+                    CarrierIdProvider.CARRIER_ID_TABLE));
+            db.execSQL(CarrierIdProvider.getStringForIndexCreation(
+                    CarrierIdProvider.CARRIER_ID_TABLE));
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+            Log.d(TAG, "InMemoryCarrierIdProviderDbHelper onUpgrade doing nothing");
+            return;
+        }
+    }
+}
diff --git a/tests/src/com/android/providers/telephony/ServiceStateProviderTest.java b/tests/src/com/android/providers/telephony/ServiceStateProviderTest.java
index 685d9be..fd15d01 100644
--- a/tests/src/com/android/providers/telephony/ServiceStateProviderTest.java
+++ b/tests/src/com/android/providers/telephony/ServiceStateProviderTest.java
@@ -16,31 +16,16 @@
 
 package com.android.providers.telephony;
 
-import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.ProviderInfo;
-import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.Uri;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Looper;
 import android.support.test.InstrumentationRegistry;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
-import android.test.mock.MockContentProvider;
 import android.test.mock.MockContentResolver;
-import android.test.mock.MockContext;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import com.android.internal.telephony.CarrierActionAgent;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.GsmCdmaPhone;
-import com.android.internal.telephony.PhoneFactory;
-import com.android.internal.telephony.ServiceStateTracker;
 
 import org.junit.After;
 import org.junit.Before;
@@ -49,11 +34,8 @@
 import org.mockito.MockitoAnnotations;
 import org.mockito.Spy;
 
-import static android.app.job.JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS;
-import static android.Manifest.permission.MODIFY_PHONE_STATE;
 import static android.provider.Telephony.ServiceStateTable;
 import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionId;
-import static android.provider.Telephony.ServiceStateTable.getContentValuesForServiceState;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -199,8 +181,8 @@
         final int rilVoiceRadioTechnology = ss.getRilVoiceRadioTechnology();
         final int rilDataRadioTechnology = ss.getRilDataRadioTechnology();
         final int cssIndicator = ss.getCssIndicator();
-        final int networkId = ss.getNetworkId();
-        final int systemId = ss.getSystemId();
+        final int networkId = ss.getCdmaNetworkId();
+        final int systemId = ss.getCdmaSystemId();
         final int cdmaRoamingIndicator = ss.getCdmaRoamingIndicator();
         final int cdmaDefaultRoamingIndicator = ss.getCdmaDefaultRoamingIndicator();
         final int cdmaEriIconIndex = ss.getCdmaEriIconIndex();
@@ -243,11 +225,11 @@
 
         ServiceState oldSS = new ServiceState();
         oldSS.setStateOutOfService();
-        oldSS.setSystemAndNetworkId(1, 1);
+        oldSS.setCdmaSystemAndNetworkId(1, 1);
 
         ServiceState newSS = new ServiceState();
         newSS.setStateOutOfService();
-        newSS.setSystemAndNetworkId(0, 0);
+        newSS.setCdmaSystemAndNetworkId(0, 0);
 
         // Test that notifyChange is not called for these fields
         boolean notifyChangeWasCalled = false;
diff --git a/tests/src/com/android/providers/telephony/SmsProviderTest.java b/tests/src/com/android/providers/telephony/SmsProviderTest.java
index 8fba85b..ba63203 100644
--- a/tests/src/com/android/providers/telephony/SmsProviderTest.java
+++ b/tests/src/com/android/providers/telephony/SmsProviderTest.java
@@ -17,12 +17,14 @@
 package com.android.providers.telephony;
 
 import android.app.AppOpsManager;
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
 import android.content.res.Resources;
 import android.database.ContentObserver;
+import android.database.Cursor;
 import android.net.Uri;
 import android.provider.Telephony;
 import android.telephony.TelephonyManager;
@@ -58,6 +60,20 @@
 
     private int notifyChangeCount;
 
+    private final String mFakePdu = "123abc";
+    private final String mFakeAddress = "FakeAddress";
+    private final String mFakeOriginatingAddr = "FakeDisplayAddress";
+    private final String mFakeMessageBody = "FakeMessageBody";
+    private final int mFakeRefNumber = 123;
+    private final int mFakeSequence = 1;
+    private final int mFakeCount = 1;
+    private final int mFakePort = 1 << 19;
+    private final long mDate = 0;
+
+    private final Uri mRawUri =
+            Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw");
+    private final Uri mRawUriPermanentDelete =
+            Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete");
 
     /**
      * This is used to give the SmsProviderTest a mocked context which takes a
@@ -170,4 +186,86 @@
         assertEquals(Uri.parse("content://sms/attachments/1"),
                 mContentResolver.insert(Uri.parse("content://sms/attachments"), values));
     }
-}
\ No newline at end of file
+
+    @Test
+    @SmallTest
+    public void testRawTableInsert() {
+        // insert test contentValues
+        assertEquals(Uri.parse("content://sms/raw/1"),
+                mContentResolver.insert(mRawUri, getFakeRawValue()));
+
+        // Query and confirm contents.
+        Cursor cursor = mContentResolver.query(mRawUri, null, null, null, null);
+        assertEquals(1, cursor.getCount());
+        cursor.moveToNext();
+        assertEquals(mFakePdu, cursor.getString(cursor.getColumnIndex("pdu")));
+        assertEquals(mFakeAddress, cursor.getString(cursor.getColumnIndex("address")));
+        assertEquals(mFakeOriginatingAddr,
+                cursor.getString(cursor.getColumnIndex("display_originating_addr")));
+        assertEquals(mFakeMessageBody, cursor.getString(cursor.getColumnIndex("message_body")));
+        assertEquals(mDate, cursor.getInt(cursor.getColumnIndex("date")));
+        assertEquals(mFakePort, cursor.getInt(cursor.getColumnIndex("destination_port")));
+        assertEquals(mFakeRefNumber, cursor.getInt(cursor.getColumnIndex("reference_number")));
+        assertEquals(mFakeSequence, cursor.getInt(cursor.getColumnIndex("sequence")));
+        assertEquals(mFakeCount, cursor.getInt(cursor.getColumnIndex("count")));
+        assertEquals(0, cursor.getInt(cursor.getColumnIndex("deleted")));
+
+        // Insert another two.
+        assertEquals(Uri.parse("content://sms/raw/2"),
+                mContentResolver.insert(mRawUri, getFakeRawValue()));
+        assertEquals(Uri.parse("content://sms/raw/3"),
+                mContentResolver.insert(mRawUri, getFakeRawValue()));
+
+        cursor.close();
+    }
+
+    @Test
+    @SmallTest
+    public void testRawTableDelete() throws Exception {
+        assertEquals(Uri.parse("content://sms/raw/1"),
+                mContentResolver.insert(mRawUri, getFakeRawValue()));
+
+        // Mark as deleted.
+        String where = "reference_number=?";
+        String[] whereArgs = {Integer.toString(mFakeRefNumber)};
+        assertEquals(1, mContentResolver.delete(mRawUri, where, whereArgs));
+
+        // The row should still be in table, with column "deleted" to be 1.
+        Cursor cursor = mSmsProviderTestable.mDeOpenHelper.getReadableDatabase().query(
+                "raw", null, null, null, null, null, null);
+        assertEquals(1, cursor.getCount());
+        cursor.moveToNext();
+        assertEquals(1, cursor.getInt(cursor.getColumnIndex("deleted")));
+        cursor.close();
+
+        // The deleted row should be purged.
+        cursor = mContentResolver.query(mRawUri, null, null, null, null);
+        assertEquals(0, cursor.getCount());
+
+        // Permanent delete all rows.
+        assertEquals(Uri.parse("content://sms/raw/1"),
+                mContentResolver.insert(mRawUri, getFakeRawValue()));
+        assertEquals(Uri.parse("content://sms/raw/2"),
+                mContentResolver.insert(mRawUri, getFakeRawValue()));
+        assertEquals(2, mContentResolver.delete(mRawUriPermanentDelete, null, null));
+        cursor = mSmsProviderTestable.mDeOpenHelper.getReadableDatabase().query(
+                "raw", null, null, null, null, null, null);
+        assertEquals(0, cursor.getCount());
+        cursor.close();
+    }
+
+    private ContentValues getFakeRawValue() {
+        ContentValues values = new ContentValues();
+        values.put("pdu", mFakePdu);
+        values.put("date", mDate);
+        values.put("destination_port", mFakePort);
+        values.put("address", mFakeAddress);
+        values.put("display_originating_addr", mFakeOriginatingAddr);
+        values.put("reference_number", mFakeRefNumber);
+        values.put("sequence", mFakeSequence);
+        values.put("count", mFakeCount);
+        values.put("message_body", mFakeMessageBody);
+
+        return values;
+    }
+}
diff --git a/tests/src/com/android/providers/telephony/SmsProviderTestable.java b/tests/src/com/android/providers/telephony/SmsProviderTestable.java
index 9c3372e..3c077fa 100644
--- a/tests/src/com/android/providers/telephony/SmsProviderTestable.java
+++ b/tests/src/com/android/providers/telephony/SmsProviderTestable.java
@@ -25,30 +25,18 @@
 public class SmsProviderTestable extends SmsProvider {
     private static final String TAG = "SmsProviderTestable";
 
-    private InMemorySmsProviderDbHelper mDbHelper;
-
     @Override
     public boolean onCreate() {
         Log.d(TAG, "onCreate called: mDbHelper = new InMemorySmsProviderDbHelper()");
-        mDbHelper = new InMemorySmsProviderDbHelper();
+        mCeOpenHelper = new InMemorySmsProviderDbHelper();
+        mDeOpenHelper = new InMemorySmsProviderDbHelper();
         return true;
     }
 
-    @Override
-    SQLiteDatabase getReadableDatabase(int match) {
-        Log.d(TAG, "getReadableDatabase called");
-        return mDbHelper.getReadableDatabase();
-    }
-
-    @Override
-    SQLiteDatabase getWritableDatabase(int match) {
-        Log.d(TAG, "getWritableDatabase called");
-        return mDbHelper.getWritableDatabase();
-    }
-
     // close mDbHelper database object
     protected void closeDatabase() {
-        mDbHelper.close();
+        mCeOpenHelper.close();
+        mDeOpenHelper.close();
     }
 
     /**
@@ -70,6 +58,7 @@
             // Set up the sms tables
             Log.d(TAG, "InMemorySmsProviderDbHelper onCreate creating the sms tables");
             db.execSQL(MmsSmsDatabaseHelper.CREATE_SMS_TABLE_STRING);
+            db.execSQL(MmsSmsDatabaseHelper.CREATE_RAW_TABLE_STRING);
             db.execSQL(MmsSmsDatabaseHelper.CREATE_ATTACHMENTS_TABLE_STRING);
         }
 
diff --git a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
index 1f221f5..dde9e5c 100644
--- a/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
+++ b/tests/src/com/android/providers/telephony/TelephonyProviderTest.java
@@ -19,11 +19,13 @@
 import android.annotation.TargetApi;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
+import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
 import android.content.res.Resources;
+import android.content.SharedPreferences;
 import android.database.Cursor;
 import android.database.ContentObserver;
 import android.database.DatabaseErrorHandler;
@@ -33,8 +35,11 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.FileUtils;
+import android.os.Process;
 import android.provider.Telephony.Carriers;
+import android.support.test.InstrumentationRegistry;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.test.AndroidTestCase;
 import android.test.mock.MockContentProvider;
 import android.test.mock.MockContentResolver;
@@ -50,6 +55,20 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Map;
+import java.util.Set;
 
 
 /**
@@ -72,7 +91,31 @@
     private TelephonyProviderTestable mTelephonyProviderTestable;
 
     private int notifyChangeCount;
+    private int notifyChangeRestoreCount;
 
+    private static final String TEST_SUBID = "1";
+    private static final String TEST_OPERATOR = "123456";
+    private static final String TEST_MCC = "123";
+    private static final String TEST_MNC = "456";
+    // Used to test the path for URL_TELEPHONY_USING_SUBID with subid 1
+    private static final Uri CONTENT_URI_WITH_SUBID = Uri.parse(
+            "content://telephony/carriers/subId/" + TEST_SUBID);
+
+    // Used to test the "restore to default"
+    private static final Uri URL_RESTOREAPN_USING_SUBID = Uri.parse(
+            "content://telephony/carriers/restore/subId/" + TEST_SUBID);
+    // Used to test the preferred apn
+    private static final Uri URL_PREFERAPN_USING_SUBID = Uri.parse(
+            "content://telephony/carriers/preferapn/subId/" + TEST_SUBID);
+
+    private static final String COLUMN_APN_ID = "apn_id";
+
+    // Constants for DPC related tests.
+    private static final Uri URI_DPC = Uri.parse("content://telephony/carriers/dpc");
+    private static final Uri URI_TELEPHONY = Carriers.CONTENT_URI;
+    private static final Uri URI_FILTERED = Uri.parse("content://telephony/carriers/filtered");
+    private static final Uri URI_ENFORCE_MANAGED= Uri.parse("content://telephony/carriers/enforce_managed");
+    private static final String ENFORCED_KEY = "enforced";
 
     /**
      * This is used to give the TelephonyProviderTest a mocked context which takes a
@@ -81,6 +124,7 @@
      */
     private class MockContextWithProvider extends MockContext {
         private final MockContentResolver mResolver;
+        private TelephonyManager mTelephonyManager = mock(TelephonyManager.class);
 
         public MockContextWithProvider(TelephonyProvider telephonyProvider) {
             mResolver = new MockContentResolver() {
@@ -88,9 +132,15 @@
                 public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
                         int userHandle) {
                     notifyChangeCount++;
+                    if (URL_RESTOREAPN_USING_SUBID.equals(uri)) {
+                        notifyChangeRestoreCount++;
+                    }
                 }
             };
 
+            // return test subId 0 for all operators
+            doReturn(TEST_OPERATOR).when(mTelephonyManager).getSimOperator(anyInt());
+
             // Add authority="telephony" to given telephonyProvider
             ProviderInfo providerInfo = new ProviderInfo();
             providerInfo.authority = "telephony";
@@ -108,8 +158,13 @@
 
         @Override
         public Object getSystemService(String name) {
-            Log.d(TAG, "getSystemService: returning null");
-            return null;
+            if (name.equals(Context.TELEPHONY_SERVICE)) {
+                Log.d(TAG, "getSystemService: returning mock TM");
+                return mTelephonyManager;
+            } else {
+                Log.d(TAG, "getSystemService: returning null");
+                return null;
+            }
         }
 
         @Override
@@ -123,6 +178,11 @@
             return mResolver;
         }
 
+        @Override
+        public SharedPreferences getSharedPreferences(String name, int mode) {
+            return InstrumentationRegistry.getContext().getSharedPreferences(name, mode);
+        }
+
         // Gives permission to write to the APN table within the MockContext
         @Override
         public int checkCallingOrSelfPermission(String permission) {
@@ -145,6 +205,7 @@
         mContext = new MockContextWithProvider(mTelephonyProviderTestable);
         mContentResolver = (MockContentResolver) mContext.getContentResolver();
         notifyChangeCount = 0;
+        notifyChangeRestoreCount = 0;
     }
 
     @Override
@@ -165,7 +226,7 @@
         final String insertApn = "exampleApnName";
         final String insertName = "exampleName";
         final Integer insertCurrent = 1;
-        final String insertNumeric = "123456";
+        final String insertNumeric = TEST_OPERATOR;
         contentValues.put(Carriers.APN, insertApn);
         contentValues.put(Carriers.NAME, insertName);
         contentValues.put(Carriers.CURRENT, insertCurrent);
@@ -222,18 +283,135 @@
     @Test
     @SmallTest
     public void testInsertCarriers() {
+        doSimpleTestForUri(Carriers.CONTENT_URI);
+    }
+
+    /**
+     * Test updating values in carriers table. Verify that when update hits a conflict using URL_ID
+     * we merge the rows.
+     */
+    @Test
+    @SmallTest
+    public void testUpdateConflictingCarriers() {
+        // insert 2 test contentValues
+        ContentValues contentValues = new ContentValues();
+        final String insertApn = "exampleApnName";
+        final String insertName = "exampleName";
+        final String insertNumeric = TEST_OPERATOR;
+        final String insertMcc = TEST_MCC;
+        final String insertMnc = TEST_MNC;
+        contentValues.put(Carriers.APN, insertApn);
+        contentValues.put(Carriers.NAME, insertName);
+        contentValues.put(Carriers.NUMERIC, insertNumeric);
+        contentValues.put(Carriers.MCC, insertMcc);
+        contentValues.put(Carriers.MNC, insertMnc);
+
+        ContentValues contentValues2 = new ContentValues();
+        final String insertName2 = "exampleName2";
+        contentValues2.put(Carriers.NAME, insertName2);
+
+        Uri row1 = mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
+        Uri row2 = mContentResolver.insert(Carriers.CONTENT_URI, contentValues2);
+
+        // use URL_ID to update row2 apn so it conflicts with row1
+        Log.d(TAG, "testUpdateConflictingCarriers: update row2=" + row2);
+        contentValues.put(Carriers.NAME, insertName2);
+        mContentResolver.update(row2, contentValues, null, null);
+
+        // verify that only 1 APN now exists and it has the fields from row1 and row2
+        final String[] testProjection =
+        {
+            Carriers.APN,
+            Carriers.NAME,
+            Carriers.NUMERIC,
+            Carriers.MCC,
+            Carriers.MNC
+        };
+        Cursor cursor = mContentResolver.query(Carriers.CONTENT_URI, testProjection, null, null,
+                null);
+        assertNotNull(cursor);
+        assertEquals(1, cursor.getCount());
+        cursor.moveToFirst();
+        assertEquals(insertApn, cursor.getString(0 /* APN */));
+        assertEquals(insertName2, cursor.getString(1 /* NAME */));
+        assertEquals(insertNumeric, cursor.getString(2 /* NUMERIC */));
+        assertEquals(insertMcc, cursor.getString(3 /* MCC */));
+        assertEquals(insertMnc, cursor.getString(4 /* MNC */));
+    }
+
+    /**
+     * Test inserting, querying, and deleting values in carriers table.
+     * Verify that the inserted values match the result of the query and are deleted.
+     */
+    @Test
+    @SmallTest
+    public void testInsertCarriersWithSubId() {
+        doSimpleTestForUri(CONTENT_URI_WITH_SUBID);
+    }
+
+    private void doSimpleTestForUri(Uri uri) {
         // insert test contentValues
         ContentValues contentValues = new ContentValues();
         final String insertApn = "exampleApnName";
         final String insertName = "exampleName";
-        final Integer insertCurrent = 1;
-        final String insertNumeric = "123456";
+        final String insertNumeric = TEST_OPERATOR;
         contentValues.put(Carriers.APN, insertApn);
         contentValues.put(Carriers.NAME, insertName);
-        contentValues.put(Carriers.CURRENT, insertCurrent);
         contentValues.put(Carriers.NUMERIC, insertNumeric);
 
         Log.d(TAG, "testInsertCarriers Inserting contentValues: " + contentValues);
+        mContentResolver.insert(uri, contentValues);
+
+        // get values in table
+        final String[] testProjection =
+        {
+            Carriers.APN,
+            Carriers.NAME,
+        };
+        final String selection = Carriers.NUMERIC + "=?";
+        String[] selectionArgs = { insertNumeric };
+        Log.d(TAG, "testInsertCarriers query projection: " + testProjection
+                + "\ntestInsertCarriers selection: " + selection
+                + "\ntestInsertCarriers selectionArgs: " + selectionArgs);
+        Cursor cursor = mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
+
+        // verify that inserted values match results of query
+        assertNotNull(cursor);
+        assertEquals(1, cursor.getCount());
+        cursor.moveToFirst();
+        final String resultApn = cursor.getString(0);
+        final String resultName = cursor.getString(1);
+        assertEquals(insertApn, resultApn);
+        assertEquals(insertName, resultName);
+
+        // delete test content
+        final String selectionToDelete = Carriers.NUMERIC + "=?";
+        String[] selectionArgsToDelete = { insertNumeric };
+        Log.d(TAG, "testInsertCarriers deleting selection: " + selectionToDelete
+                + "testInsertCarriers selectionArgs: " + selectionArgs);
+        int numRowsDeleted = mContentResolver.delete(uri, selectionToDelete, selectionArgsToDelete);
+        assertEquals(1, numRowsDeleted);
+
+        // verify that deleted values are gone
+        cursor = mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
+        assertEquals(0, cursor.getCount());
+    }
+
+    @Test
+    @SmallTest
+    public void testOwnedBy() {
+        // insert test contentValues
+        ContentValues contentValues = new ContentValues();
+        final String insertApn = "exampleApnName";
+        final String insertName = "exampleName";
+        final String insertNumeric = TEST_OPERATOR;
+        final Integer insertOwnedBy = Carriers.OWNED_BY_OTHERS;
+        contentValues.put(Carriers.APN, insertApn);
+        contentValues.put(Carriers.NAME, insertName);
+        contentValues.put(Carriers.NUMERIC, insertNumeric);
+        contentValues.put(Carriers.OWNED_BY, insertOwnedBy);
+
+        Log.d(TAG, "testInsertCarriers Inserting contentValues: " + contentValues);
         mContentResolver.insert(Carriers.CONTENT_URI, contentValues);
 
         // get values in table
@@ -241,7 +419,7 @@
         {
             Carriers.APN,
             Carriers.NAME,
-            Carriers.CURRENT,
+            Carriers.OWNED_BY,
         };
         final String selection = Carriers.NUMERIC + "=?";
         String[] selectionArgs = { insertNumeric };
@@ -257,10 +435,11 @@
         cursor.moveToFirst();
         final String resultApn = cursor.getString(0);
         final String resultName = cursor.getString(1);
-        final Integer resultCurrent = cursor.getInt(2);
+        final Integer resultOwnedBy = cursor.getInt(2);
         assertEquals(insertApn, resultApn);
         assertEquals(insertName, resultName);
-        assertEquals(insertCurrent, resultCurrent);
+        // Verify that OWNED_BY is force set to OWNED_BY_OTHERS when inserted with general uri
+        assertEquals(insertOwnedBy, resultOwnedBy);
 
         // delete test content
         final String selectionToDelete = Carriers.NUMERIC + "=?";
@@ -290,10 +469,12 @@
         final String insertDisplayName = "exampleDisplayName";
         final String insertCarrierName = "exampleCarrierName";
         final String insertIccId = "exampleIccId";
+        final String insertCardId = "exampleCardId";
         contentValues.put(SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID, insertSubId);
         contentValues.put(SubscriptionManager.DISPLAY_NAME, insertDisplayName);
         contentValues.put(SubscriptionManager.CARRIER_NAME, insertCarrierName);
         contentValues.put(SubscriptionManager.ICC_ID, insertIccId);
+        contentValues.put(SubscriptionManager.CARD_ID, insertCardId);
 
         Log.d(TAG, "testSimTable Inserting contentValues: " + contentValues);
         mContentResolver.insert(SubscriptionManager.CONTENT_URI, contentValues);
@@ -303,6 +484,7 @@
         {
             SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID,
             SubscriptionManager.CARRIER_NAME,
+            SubscriptionManager.CARD_ID,
         };
         final String selection = SubscriptionManager.DISPLAY_NAME + "=?";
         String[] selectionArgs = { insertDisplayName };
@@ -317,8 +499,10 @@
         cursor.moveToFirst();
         final int resultSubId = cursor.getInt(0);
         final String resultCarrierName = cursor.getString(1);
+        final String resultCardId = cursor.getString(2);
         assertEquals(insertSubId, resultSubId);
         assertEquals(insertCarrierName, resultCarrierName);
+        assertEquals(insertCardId, resultCardId);
 
         // delete test content
         final String selectionToDelete = SubscriptionManager.DISPLAY_NAME + "=?";
@@ -334,4 +518,825 @@
                 testProjection, selection, selectionArgs, null);
         assertEquals(0, cursor.getCount());
     }
+
+    private int parseIdFromInsertedUri(Uri uri) throws NumberFormatException {
+        return (uri != null) ? Integer.parseInt(uri.getLastPathSegment()) : -1;
+    }
+
+    private int insertApnRecord(Uri uri, String apn, String name, int current, String numeric) {
+        ContentValues contentValues = new ContentValues();
+        contentValues.put(Carriers.APN, apn);
+        contentValues.put(Carriers.NAME, name);
+        contentValues.put(Carriers.CURRENT, current);
+        contentValues.put(Carriers.NUMERIC, numeric);
+        Uri resultUri = mContentResolver.insert(uri, contentValues);
+        return parseIdFromInsertedUri(resultUri);
+    }
+
+    /**
+     * Test URL_ENFORCE_MANAGED and URL_FILTERED works correctly.
+     * Verify that when enforce is set true via URL_ENFORCE_MANAGED, only DPC records are returned
+     * for URL_FILTERED and URL_FILTERED_ID.
+     * Verify that when enforce is set false via URL_ENFORCE_MANAGED, only non-DPC records
+     * are returned for URL_FILTERED and URL_FILTERED_ID.
+     */
+    @Test
+    @SmallTest
+    public void testEnforceManagedUri() {
+        mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
+
+        final int current = 1;
+        final String numeric = "123456789";
+
+        // Insert DPC record.
+        final String dpcRecordApn = "exampleApnNameDPC";
+        final String dpcRecordName = "exampleNameDPC";
+        final int dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
+                current, numeric);
+
+        // Insert non-DPC record.
+        final String othersRecordApn = "exampleApnNameOTHERS";
+        final String othersRecordName = "exampleNameDPOTHERS";
+        final int othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
+                current, numeric);
+
+        // Set enforced = false.
+        ContentValues enforceManagedValue = new ContentValues();
+        enforceManagedValue.put(ENFORCED_KEY, false);
+        Log.d(TAG, "testEnforceManagedUri Updating enforced = false: "
+                + enforceManagedValue);
+        mContentResolver.update(URI_ENFORCE_MANAGED, enforceManagedValue, "", new String[]{});
+
+        // Verify that enforced is set to false in TelephonyProvider.
+        Cursor enforceCursor = mContentResolver.query(URI_ENFORCE_MANAGED,
+            null, null, null, null);
+        assertNotNull(enforceCursor);
+        assertEquals(1, enforceCursor.getCount());
+        enforceCursor.moveToFirst();
+        assertEquals(0, enforceCursor.getInt(0));
+
+        // Verify URL_FILTERED query only returns non-DPC record.
+        final String[] testProjection =
+        {
+            Carriers._ID,
+            Carriers.OWNED_BY
+        };
+        final String selection = Carriers.NUMERIC + "=?";
+        final String[] selectionArgs = { numeric };
+        final Cursor cursorNotEnforced = mContentResolver.query(URI_FILTERED,
+            testProjection, selection, selectionArgs, null);
+        assertNotNull(cursorNotEnforced);
+        assertEquals(1, cursorNotEnforced.getCount());
+        cursorNotEnforced.moveToFirst();
+        assertEquals(othersRecordId, cursorNotEnforced.getInt(0));
+        assertEquals(Carriers.OWNED_BY_OTHERS, cursorNotEnforced.getInt(1));
+
+        // Verify that URL_FILTERED_ID cannot get DPC record.
+        Cursor cursorNotEnforcedDpc = mContentResolver.query(Uri.withAppendedPath(URI_FILTERED,
+                Integer.toString(dpcRecordId)), null, null, null, null);
+        assertNotNull(cursorNotEnforcedDpc);
+        assertTrue(cursorNotEnforcedDpc.getCount() == 0);
+        // Verify that URL_FILTERED_ID can get non-DPC record.
+        Cursor cursorNotEnforcedOthers = mContentResolver.query(Uri.withAppendedPath(URI_FILTERED,
+                Integer.toString(othersRecordId)), null, null, null, null);
+        assertNotNull(cursorNotEnforcedOthers);
+        assertTrue(cursorNotEnforcedOthers.getCount() == 1);
+
+        // Set enforced = true.
+        enforceManagedValue.put(ENFORCED_KEY, true);
+        Log.d(TAG, "testEnforceManagedUri Updating enforced = true: "
+                + enforceManagedValue);
+        mContentResolver.update(URI_ENFORCE_MANAGED, enforceManagedValue, "", new String[]{});
+
+        // Verify that enforced is set to true in TelephonyProvider.
+        enforceCursor = mContentResolver.query(URI_ENFORCE_MANAGED,
+            null, null, null, null);
+        assertNotNull(enforceCursor);
+        assertEquals(1, enforceCursor.getCount());
+        enforceCursor.moveToFirst();
+        assertEquals(1, enforceCursor.getInt(0));
+
+        // Verify URL_FILTERED query only returns DPC record.
+        final Cursor cursorEnforced = mContentResolver.query(URI_FILTERED,
+                testProjection, selection, selectionArgs, null);
+        assertNotNull(cursorEnforced);
+        assertEquals(1, cursorEnforced.getCount());
+        cursorEnforced.moveToFirst();
+        assertEquals(dpcRecordId, cursorEnforced.getInt(0));
+        assertEquals(Carriers.OWNED_BY_DPC, cursorEnforced.getInt(1));
+
+        // Verify that URL_FILTERED_ID can get DPC record.
+        cursorNotEnforcedDpc = mContentResolver.query(Uri.withAppendedPath(URI_FILTERED,
+                Integer.toString(dpcRecordId)), null, null, null, null);
+        assertNotNull(cursorNotEnforcedDpc);
+        assertTrue(cursorNotEnforcedDpc.getCount() == 1);
+        // Verify that URL_FILTERED_ID cannot get non-DPC record.
+        cursorNotEnforcedOthers = mContentResolver.query(Uri.withAppendedPath(URI_FILTERED,
+                Integer.toString(othersRecordId)), null, null, null, null);
+        assertNotNull(cursorNotEnforcedOthers);
+        assertTrue(cursorNotEnforcedOthers.getCount() == 0);
+
+        // Delete testing records.
+        int numRowsDeleted = mContentResolver.delete(URI_TELEPHONY, selection, selectionArgs);
+        assertEquals(1, numRowsDeleted);
+
+        numRowsDeleted = mContentResolver.delete(
+                ContentUris.withAppendedId(URI_DPC, dpcRecordId), "", null);
+        assertEquals(1, numRowsDeleted);
+    }
+
+    private Cursor queryFullTestApnRecord(Uri uri, String numeric) {
+        final String selection = Carriers.NUMERIC + "=?";
+        String[] selectionArgs = { numeric };
+        final String[] testProjection =
+                {
+                        Carriers._ID,
+                        Carriers.APN,
+                        Carriers.NAME,
+                        Carriers.CURRENT,
+                        Carriers.OWNED_BY,
+                };
+        return mContentResolver.query(uri, testProjection, selection, selectionArgs, null);
+    }
+
+    @Test
+    @SmallTest
+    /**
+     * Test URL_TELEPHONY cannot insert, query, update or delete DPC records.
+     */
+    public void testTelephonyUriDpcRecordAccessControl() {
+        mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
+
+        final int current = 1;
+        final String numeric = "123456789";
+        final String selection = Carriers.NUMERIC + "=?";
+        final String[] selectionArgs = { numeric };
+
+        // Insert DPC record.
+        final String dpcRecordApn = "exampleApnNameDPC";
+        final String dpcRecordName = "exampleNameDPC";
+        final int dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
+                current, numeric);
+
+        // Insert non-DPC record.
+        final String othersRecordApn = "exampleApnNameOTHERS";
+        final String othersRecordName = "exampleNameDPOTHERS";
+        final int othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
+                current, numeric);
+
+        // Verify URL_TELEPHONY query only returns non-DPC record.
+        final Cursor cursorTelephony = queryFullTestApnRecord(URI_TELEPHONY, numeric);
+        assertNotNull(cursorTelephony);
+        assertEquals(1, cursorTelephony.getCount());
+        cursorTelephony.moveToFirst();
+        assertApnEquals(cursorTelephony, othersRecordId, othersRecordApn, othersRecordName,
+                current, Carriers.OWNED_BY_OTHERS);
+
+        // Verify URI_TELEPHONY updates only non-DPC records.
+        ContentValues contentValuesOthersUpdate = new ContentValues();
+        final String othersRecordUpdatedApn = "exampleApnNameOTHERSUpdated";
+        final String othersRecordUpdatedName = "exampleNameOTHERSpdated";
+        contentValuesOthersUpdate.put(Carriers.APN, othersRecordUpdatedApn);
+        contentValuesOthersUpdate.put(Carriers.NAME, othersRecordUpdatedName);
+
+        final int updateCount = mContentResolver.update(URI_TELEPHONY, contentValuesOthersUpdate,
+                selection, selectionArgs);
+        assertEquals(1, updateCount);
+        final Cursor cursorNonDPCUpdate = queryFullTestApnRecord(URI_TELEPHONY, numeric);
+        final Cursor cursorDPCUpdate = queryFullTestApnRecord(URI_DPC, numeric);
+
+        // Verify that non-DPC records are updated.
+        assertNotNull(cursorNonDPCUpdate);
+        assertEquals(1, cursorNonDPCUpdate.getCount());
+        cursorNonDPCUpdate.moveToFirst();
+        assertApnEquals(cursorNonDPCUpdate, othersRecordId, othersRecordUpdatedApn,
+                othersRecordUpdatedName);
+
+        // Verify that DPC records are not updated.
+        assertNotNull(cursorDPCUpdate);
+        assertEquals(1, cursorDPCUpdate.getCount());
+        cursorDPCUpdate.moveToFirst();
+        assertApnEquals(cursorDPCUpdate, dpcRecordId, dpcRecordApn, dpcRecordName);
+
+        // Verify URI_TELEPHONY deletes only non-DPC records.
+        int numRowsDeleted = mContentResolver.delete(URI_TELEPHONY, selection, selectionArgs);
+        assertEquals(1, numRowsDeleted);
+        final Cursor cursorTelephonyRemaining = queryFullTestApnRecord(URI_TELEPHONY, numeric);
+        assertNotNull(cursorTelephonyRemaining);
+        assertEquals(0, cursorTelephonyRemaining.getCount());
+        final Cursor cursorDPCDeleted = queryFullTestApnRecord(URI_DPC, numeric);
+        assertNotNull(cursorDPCDeleted);
+        assertEquals(1, cursorDPCDeleted.getCount());
+
+        // Delete remaining test records.
+        numRowsDeleted = mContentResolver.delete(
+                ContentUris.withAppendedId(URI_DPC, dpcRecordId), "", null);
+        assertEquals(1, numRowsDeleted);
+    }
+
+    /**
+     * Test URL_DPC cannot insert or query non-DPC records.
+     * Test URL_DPC_ID cannot update or delete non-DPC records.
+     */
+    @Test
+    @SmallTest
+    public void testDpcUri() {
+        int dpcRecordId = 0, othersRecordId = 0;
+        try {
+            mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
+
+            final int current = 1;
+            final String numeric = "123456789";
+
+            // Insert DPC record.
+            final String dpcRecordApn = "exampleApnNameDPC";
+            final String dpcRecordName = "exampleNameDPC";
+            dpcRecordId = insertApnRecord(URI_DPC, dpcRecordApn, dpcRecordName,
+                    current, numeric);
+
+            // Insert non-DPC record.
+            final String othersRecordApn = "exampleApnNameOTHERS";
+            final String othersRecordName = "exampleNameDPOTHERS";
+            othersRecordId = insertApnRecord(URI_TELEPHONY, othersRecordApn, othersRecordName,
+                    current, numeric);
+
+            Log.d(TAG, "testDPCIdUri Id for inserted DPC record: " + dpcRecordId);
+            Log.d(TAG, "testDPCIdUri Id for inserted non-DPC record: " + othersRecordId);
+
+            // Verify that URI_DPC query only returns DPC records.
+            final Cursor cursorDPC = queryFullTestApnRecord(URI_DPC, numeric);
+            assertNotNull(cursorDPC);
+            assertEquals(1, cursorDPC.getCount());
+            cursorDPC.moveToFirst();
+            assertApnEquals(cursorDPC, dpcRecordId, dpcRecordApn, dpcRecordName, current,
+                    Carriers.OWNED_BY_DPC);
+
+            // Verify that URI_DPC_ID updates only DPC records.
+            ContentValues contentValuesDpcUpdate = new ContentValues();
+            final String dpcRecordUpdatedApn = "exampleApnNameDPCUpdated";
+            final String dpcRecordUpdatedName = "exampleNameDPCUpdated";
+            contentValuesDpcUpdate.put(Carriers.APN, dpcRecordUpdatedApn);
+            contentValuesDpcUpdate.put(Carriers.NAME, dpcRecordUpdatedName);
+            final int updateCount = mContentResolver.update(
+                    ContentUris.withAppendedId(URI_DPC, dpcRecordId),
+                    contentValuesDpcUpdate, null, null);
+            assertEquals(1, updateCount);
+            final Cursor cursorNonDPCUpdate = queryFullTestApnRecord(URI_TELEPHONY, numeric);
+            final Cursor cursorDPCUpdate = queryFullTestApnRecord(URI_DPC, numeric);
+
+            // Verify that non-DPC records are not updated.
+            assertNotNull(cursorNonDPCUpdate);
+            assertEquals(1, cursorNonDPCUpdate.getCount());
+            cursorNonDPCUpdate.moveToFirst();
+            assertApnEquals(cursorNonDPCUpdate, othersRecordId, othersRecordApn, othersRecordName);
+
+            // Verify that DPC records are updated.
+            assertNotNull(cursorDPCUpdate);
+            assertEquals(1, cursorDPCUpdate.getCount());
+            cursorDPCUpdate.moveToFirst();
+            assertApnEquals(cursorDPCUpdate, dpcRecordId, dpcRecordUpdatedApn,
+                    dpcRecordUpdatedName);
+
+            // Test URI_DPC_ID deletes only DPC records.
+            int numRowsDeleted = mContentResolver.delete(
+                    ContentUris.withAppendedId(URI_DPC, dpcRecordId), null, null);
+            assertEquals(1, numRowsDeleted);
+            numRowsDeleted = mContentResolver.delete(
+                    ContentUris.withAppendedId(URI_DPC, dpcRecordId), null, null);
+            assertEquals(0, numRowsDeleted);
+
+        } finally {
+            // Delete remaining test records.
+            int numRowsDeleted = mContentResolver.delete(
+                    ContentUris.withAppendedId(URI_TELEPHONY, othersRecordId), null, null);
+            assertEquals(1, numRowsDeleted);
+        }
+    }
+
+    private void assertApnEquals(Cursor cursor, Object... values) {
+        assertTrue(values.length <= cursor.getColumnCount());
+        for (int i = 0; i < values.length; i ++) {
+            if (values[i] instanceof Integer) {
+                assertEquals(values[i], cursor.getInt(i));
+            } else if (values[i] instanceof String) {
+                assertEquals(values[i], cursor.getString(i));
+            } else {
+                fail("values input type not correct");
+            }
+        }
+    }
+
+    /**
+     * Test URL_DPC does not change database on conflict for insert and update.
+     */
+    @Test
+    @SmallTest
+    public void testDpcUriOnConflict() {
+        int dpcRecordId1 = 0, dpcRecordId2 = 0;
+        try {
+            mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID);
+
+            final int current = 1;
+            final String numeric = "123456789";
+
+            // Insert DPC record 1.
+            final String dpcRecordApn1 = "exampleApnNameDPC";
+            final String dpcRecordName = "exampleNameDPC";
+            dpcRecordId1 = insertApnRecord(URI_DPC, dpcRecordApn1, dpcRecordName,
+                    current, numeric);
+            Log.d(TAG, "testDpcUriOnConflict Id for DPC record 1: " + dpcRecordId1);
+
+            // Insert conflicting DPC record.
+            final String dpcRecordNameConflict = "exampleNameDPCConflict";
+            final int dpcRecordIdConflict = insertApnRecord(URI_DPC, dpcRecordApn1,
+                    dpcRecordNameConflict, current, numeric);
+
+            // Verity that conflicting DPC record is not inserted.
+            assertEquals(-1, dpcRecordIdConflict);
+            // Verify that APN 1 is not replaced or updated.
+            Cursor cursorDPC1 = queryFullTestApnRecord(URI_DPC, numeric);
+            assertNotNull(cursorDPC1);
+            assertEquals(1, cursorDPC1.getCount());
+            cursorDPC1.moveToFirst();
+            assertApnEquals(cursorDPC1, dpcRecordId1, dpcRecordApn1, dpcRecordName, current,
+                    Carriers.OWNED_BY_DPC);
+
+            // Insert DPC record 2.
+            final String dpcRecordApn2 = "exampleApnNameDPC2";
+            dpcRecordId2 = insertApnRecord(URI_DPC, dpcRecordApn2, dpcRecordName,
+                    current, numeric);
+            Log.d(TAG, "testDpcUriOnConflict Id for DPC record 2: " + dpcRecordId2);
+
+            // Update DPC record 2 to the values of DPC record 1.
+            ContentValues contentValuesDpcUpdate = new ContentValues();
+            contentValuesDpcUpdate.put(Carriers.APN, dpcRecordApn1);
+            contentValuesDpcUpdate.put(Carriers.NAME, dpcRecordNameConflict);
+            final int updateCount = mContentResolver.update(
+                    ContentUris.withAppendedId(URI_DPC, dpcRecordId2),
+                    contentValuesDpcUpdate, null, null);
+
+            // Verify that database is not updated.
+            assertEquals(0, updateCount);
+            Cursor cursorDPC2 = queryFullTestApnRecord(URI_DPC, numeric);
+            assertNotNull(cursorDPC2);
+            assertEquals(2, cursorDPC2.getCount());
+            cursorDPC2.moveToFirst();
+            assertApnEquals(cursorDPC2, dpcRecordId1, dpcRecordApn1, dpcRecordName, current,
+                    Carriers.OWNED_BY_DPC);
+            cursorDPC2.moveToNext();
+            assertApnEquals(cursorDPC2, dpcRecordId2, dpcRecordApn2, dpcRecordName, current,
+                    Carriers.OWNED_BY_DPC);
+        } finally {
+            // Delete test records.
+            int numRowsDeleted = mContentResolver.delete(
+                    ContentUris.withAppendedId(URI_DPC, dpcRecordId1), null, null);
+            assertEquals(1, numRowsDeleted);
+            numRowsDeleted = mContentResolver.delete(
+                    ContentUris.withAppendedId(URI_DPC, dpcRecordId2), null, null);
+            assertEquals(1, numRowsDeleted);
+        }
+    }
+
+    /**
+     * Verify that SecurityException is thrown if URL_DPC, URL_FILTERED and
+     * URL_ENFORCE_MANAGED is accessed from neither SYSTEM_UID nor PHONE_UID.
+     */
+    @Test
+    @SmallTest
+    public void testAccessUrlDpcThrowSecurityExceptionFromOtherUid() {
+        mTelephonyProviderTestable.fakeCallingUid(Process.SYSTEM_UID + 123456);
+
+        // Test insert().
+        ContentValues contentValuesDPC = new ContentValues();
+        try {
+            mContentResolver.insert(URI_DPC, contentValuesDPC);
+            assertFalse("SecurityException should be thrown when URI_DPC is called from"
+                    + " neither SYSTEM_UID nor PHONE_UID", true);
+        } catch (SecurityException e) {
+            // Should catch SecurityException.
+        }
+
+        // Test query().
+        try {
+            mContentResolver.query(URI_DPC,
+                    new String[]{}, "", new String[]{}, null);
+            assertFalse("SecurityException should be thrown when URI_DPC is called from"
+                    + " neither SYSTEM_UID nor PHONE_UID", true);
+        } catch (SecurityException e) {
+            // Should catch SecurityException.
+        }
+        try {
+            mContentResolver.query(URI_ENFORCE_MANAGED,
+            new String[]{}, "", new String[]{}, null);
+            assertFalse("SecurityException should be thrown when URI_ENFORCE_MANAGED is "
+                    + "called from neither SYSTEM_UID nor PHONE_UID", true);
+        } catch (SecurityException e) {
+            // Should catch SecurityException.
+        }
+
+        // Test update().
+        ContentValues contentValuesDPCUpdate = new ContentValues();
+        try {
+            mContentResolver.update(
+                    Uri.parse(URI_DPC + "/1"),
+                    contentValuesDPCUpdate, "", new String[]{});
+            assertFalse("SecurityException should be thrown when URI_DPC is called"
+                    + " from neither SYSTEM_UID nor PHONE_UID", true);
+        } catch (SecurityException e) {
+            // Should catch SecurityException.
+        }
+        try {
+            mContentResolver.update(URI_ENFORCE_MANAGED, contentValuesDPCUpdate,
+                    "", new String[]{});
+            assertFalse("SecurityException should be thrown when URI_DPC is called"
+                    + " from neither SYSTEM_UID nor PHONE_UID", true);
+        } catch (SecurityException e) {
+            // Should catch SecurityException.
+        }
+
+        // Test delete().
+        try {
+            mContentResolver.delete(
+                    Uri.parse(URI_DPC + "/0"), "", new String[]{});
+            assertFalse("SecurityException should be thrown when URI_DPC is called"
+                    + " from neither SYSTEM_UID nor PHONE_UID", true);
+        } catch (SecurityException e) {
+            // Should catch SecurityException.
+        }
+    }
+
+    /**
+     * Verify that user/carrier edited/deleted APNs have priority in the EDITED field over
+     * insertions which set EDITED=UNEDITED. In these cases instead of merging the APNs using the
+     * new APN's value we keep the old value.
+     */
+    @Test
+    @SmallTest
+    public void testPreserveEdited() {
+        preserveEditedValueInMerge(Carriers.USER_EDITED);
+    }
+
+    @Test
+    @SmallTest
+    public void testPreserveUserDeleted() {
+        preserveDeletedValueInMerge(Carriers.USER_DELETED);
+    }
+
+    @Test
+    @SmallTest
+    public void testPreserveUserDeletedButPresentInXml() {
+        preserveDeletedValueInMerge(Carriers.USER_DELETED_BUT_PRESENT_IN_XML);
+    }
+
+    @Test
+    @SmallTest
+    public void testPreserveCarrierEdited() {
+        preserveEditedValueInMerge(Carriers.CARRIER_EDITED);
+    }
+
+    @Test
+    @SmallTest
+    public void testPreserveCarrierDeleted() {
+        preserveDeletedValueInMerge(Carriers.CARRIER_DELETED);
+    }
+
+    @Test
+    @SmallTest
+    public void testPreserveCarrierDeletedButPresentInXml() {
+        preserveDeletedValueInMerge(Carriers.CARRIER_DELETED_BUT_PRESENT_IN_XML);
+    }
+
+    private void preserveEditedValueInMerge(int value) {
+        // insert user deleted APN
+        String carrierName1 = "carrier1";
+        String numeric1 = "123234";
+        String mcc1 = "123";
+        String mnc1 = "234";
+        ContentValues editedValue = new ContentValues();
+        editedValue.put(Carriers.NAME, carrierName1);
+        editedValue.put(Carriers.NUMERIC, numeric1);
+        editedValue.put(Carriers.MCC, mcc1);
+        editedValue.put(Carriers.MNC, mnc1);
+        editedValue.put(Carriers.EDITED, value);
+        assertNotNull(mContentResolver.insert(URI_TELEPHONY, editedValue));
+
+        Cursor cur = mContentResolver.query(URI_TELEPHONY, null, null, null, null);
+        assertEquals(1, cur.getCount());
+
+        // insert APN that conflicts with edited APN
+        String carrierName2 = "carrier2";
+        ContentValues values = new ContentValues();
+        values.put(Carriers.NAME, carrierName2);
+        values.put(Carriers.NUMERIC, numeric1);
+        values.put(Carriers.MCC, mcc1);
+        values.put(Carriers.MNC, mnc1);
+        values.put(Carriers.EDITED, Carriers.UNEDITED);
+        mContentResolver.insert(URI_TELEPHONY, values);
+
+        String[] testProjection = {
+            Carriers.NAME,
+            Carriers.APN,
+            Carriers.EDITED,
+            Carriers.TYPE,
+            Carriers.PROTOCOL,
+            Carriers.BEARER_BITMASK,
+        };
+        final int indexOfName = 0;
+        final int indexOfEdited = 2;
+
+        // Assert that the conflicting APN is merged into the existing user-edited APN, so only 1
+        // APN exists in the db
+        cur = mContentResolver.query(URI_TELEPHONY, testProjection, null, null, null);
+        assertEquals(1, cur.getCount());
+        cur.moveToFirst();
+        assertEquals(carrierName2, cur.getString(indexOfName));
+        assertEquals(value, cur.getInt(indexOfEdited));
+    }
+
+    private void preserveDeletedValueInMerge(int value) {
+        // insert user deleted APN
+        String carrierName1 = "carrier1";
+        String numeric1 = "123234";
+        String mcc1 = "123";
+        String mnc1 = "234";
+        ContentValues editedValue = new ContentValues();
+        editedValue.put(Carriers.NAME, carrierName1);
+        editedValue.put(Carriers.NUMERIC, numeric1);
+        editedValue.put(Carriers.MCC, mcc1);
+        editedValue.put(Carriers.MNC, mnc1);
+        editedValue.put(Carriers.EDITED, value);
+        assertNotNull(mContentResolver.insert(URI_TELEPHONY, editedValue));
+
+        // insert APN that conflicts with edited APN
+        String carrierName2 = "carrier2";
+        ContentValues values = new ContentValues();
+        values.put(Carriers.NAME, carrierName2);
+        values.put(Carriers.NUMERIC, numeric1);
+        values.put(Carriers.MCC, mcc1);
+        values.put(Carriers.MNC, mnc1);
+        values.put(Carriers.EDITED, Carriers.UNEDITED);
+        mContentResolver.insert(URI_TELEPHONY, values);
+
+        String[] testProjection = {
+            Carriers.NAME,
+            Carriers.APN,
+            Carriers.EDITED,
+            Carriers.TYPE,
+            Carriers.PROTOCOL,
+            Carriers.BEARER_BITMASK,
+        };
+        final int indexOfEdited = 2;
+
+        // Assert that the conflicting APN is merged into the existing user-deleted APN.
+        // Entries marked deleted will not show up in queries so we verify that no APNs can
+        // be seen
+        Cursor cur = mContentResolver.query(URI_TELEPHONY, testProjection, null, null, null);
+        assertEquals(0, cur.getCount());
+    }
+
+    /**
+     * Test URL_PREFERAPN_USING_SUBID works correctly.
+     */
+    @Test
+    @SmallTest
+    public void testQueryPreferredApn() {
+        // create APNs
+        ContentValues preferredValues = new ContentValues();
+        final String preferredApn = "preferredApn";
+        final String preferredName = "preferredName";
+        preferredValues.put(Carriers.APN, preferredApn);
+        preferredValues.put(Carriers.NAME, preferredName);
+        preferredValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+        ContentValues otherValues = new ContentValues();
+        final String otherApn = "otherApnName";
+        final String otherName = "otherName";
+        otherValues.put(Carriers.APN, otherApn);
+        otherValues.put(Carriers.NAME, otherName);
+        otherValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+
+        // insert APNs
+        // TODO if using URL_TELEPHONY, SubscriptionManager.getDefaultSubscriptionId() returns -1
+        Log.d(TAG, "testQueryPreferredApn: Bulk inserting contentValues=" + preferredValues + ", "
+                + otherValues);
+        Uri uri = mContentResolver.insert(CONTENT_URI_WITH_SUBID, preferredValues);
+        mContentResolver.insert(CONTENT_URI_WITH_SUBID, otherValues);
+        final String preferredApnIdString = uri.getLastPathSegment();
+        final long preferredApnId = Long.parseLong(preferredApnIdString);
+        Log.d(TAG, "testQueryPreferredApn: preferredApnString=" + preferredApnIdString);
+
+        // set preferred apn
+        preferredValues.put(COLUMN_APN_ID, preferredApnIdString);
+        mContentResolver.insert(URL_PREFERAPN_USING_SUBID, preferredValues);
+
+        // query preferred APN
+        final String[] testProjection = { Carriers.APN, Carriers.NAME };
+        Cursor cursor = mContentResolver.query(
+                URL_PREFERAPN_USING_SUBID, testProjection, null, null, null);
+
+        // verify that preferred apn was set and retreived
+        assertEquals(1, cursor.getCount());
+        cursor.moveToFirst();
+        assertEquals(preferredApn, cursor.getString(0));
+        assertEquals(preferredName, cursor.getString(1));
+    }
+
+    /**
+     *  Test that APN_SET_ID works correctly.
+     */
+    @Test
+    @SmallTest
+    public void testApnSetId() {
+        // create APNs
+        ContentValues values1 = new ContentValues();
+        final String apn = "apnName";
+        final String apnName = "name";
+        values1.put(Carriers.APN, apn);
+        values1.put(Carriers.NAME, apnName);
+        values1.put(Carriers.NUMERIC, TEST_OPERATOR);
+
+        ContentValues values2 = new ContentValues();
+        final String otherApn = "otherApnName";
+        final String otherName = "otherName";
+        values2.put(Carriers.APN, otherApn);
+        values2.put(Carriers.NAME, otherName);
+        values2.put(Carriers.NUMERIC, TEST_OPERATOR);
+        values2.put(Carriers.APN_SET_ID, 1);
+
+        // insert APNs
+        // TODO if using URL_TELEPHONY, SubscriptionManager.getDefaultSubscriptionId() returns -1
+        Log.d(TAG, "testApnSetId: inserting contentValues=" + values1 + ", " + values2);
+        mContentResolver.insert(CONTENT_URI_WITH_SUBID, values1);
+        mContentResolver.insert(CONTENT_URI_WITH_SUBID, values2);
+
+        // query APN with default APN_SET_ID
+        final String[] testProjection = { Carriers.NAME };
+        Cursor cursor = mContentResolver.query(Carriers.CONTENT_URI, testProjection,
+                Carriers.APN_SET_ID + "=?", new String[] { "0" }, null);
+        assertEquals(1, cursor.getCount());
+        cursor.moveToFirst();
+        assertEquals(apnName, cursor.getString(0));
+
+        // query APN with APN_SET_ID=1
+        cursor = mContentResolver.query(Carriers.CONTENT_URI, testProjection,
+                Carriers.APN_SET_ID + "=?", new String[] { "1" }, null);
+        assertEquals(1, cursor.getCount());
+        cursor.moveToFirst();
+        assertEquals(otherName, cursor.getString(0));
+    }
+
+    /**
+     *  Test that querying with the PREFERAPNSET url yields all APNs in the preferred set.
+     */
+    @Test
+    @SmallTest
+    public void testPreferApnSetUrl() {
+        // create APNs
+        ContentValues values1 = new ContentValues();
+        final String apn = "apnName";
+        final String apnName = "name";
+        values1.put(Carriers.APN, apn);
+        values1.put(Carriers.NAME, apnName);
+        values1.put(Carriers.NUMERIC, TEST_OPERATOR);
+
+        ContentValues values2 = new ContentValues();
+        final String apn2 = "otherApnName";
+        final String name2 = "name2";
+        values2.put(Carriers.APN, apn2);
+        values2.put(Carriers.NAME, name2);
+        values2.put(Carriers.NUMERIC, TEST_OPERATOR);
+        values2.put(Carriers.APN_SET_ID, 1);
+
+        ContentValues values3 = new ContentValues();
+        final String apn3 = "thirdApnName";
+        final String name3 = "name3";
+        values3.put(Carriers.APN, apn3);
+        values3.put(Carriers.NAME, name3);
+        values3.put(Carriers.NUMERIC, TEST_OPERATOR);
+        values3.put(Carriers.APN_SET_ID, 1);
+
+        // insert APNs
+        // we explicitly include subid, as SubscriptionManager.getDefaultSubscriptionId() returns -1
+        Log.d(TAG, "testPreferApnSetUrl: inserting contentValues=" + values1 + ", " + values2
+                + ", " + values3);
+        mContentResolver.insert(CONTENT_URI_WITH_SUBID, values1);
+        mContentResolver.insert(CONTENT_URI_WITH_SUBID, values2);
+        Uri uri = mContentResolver.insert(CONTENT_URI_WITH_SUBID, values3);
+
+        // before there's a preferred APN set, assert that all APNs are returned
+        final String[] testProjection = { Carriers.NAME };
+        Cursor cursor = mContentResolver.query(
+                Uri.withAppendedPath(Carriers.CONTENT_URI, "preferapnset/subId/" + TEST_SUBID),
+                testProjection, null, null, null);
+        assertEquals(3, cursor.getCount());
+
+        // set the APN from values3 (apn_set_id = 1) to the preferred APN
+        final String preferredApnIdString = uri.getLastPathSegment();
+        final long preferredApnId = Long.parseLong(preferredApnIdString);
+        ContentValues prefer = new ContentValues();
+        prefer.put("apn_id", preferredApnId);
+        int count = mContentResolver.update(URL_PREFERAPN_USING_SUBID, prefer, null, null);
+        assertEquals(1, count);
+
+        // query APN with PREFERAPNSET url
+        // explicitly include SUB_ID, as SubscriptionManager.getDefaultSubscriptionId() returns -1
+        cursor = mContentResolver.query(
+                Uri.withAppendedPath(Carriers.CONTENT_URI, "preferapnset/subId/" + TEST_SUBID),
+                testProjection, null, null, null);
+        assertEquals(2, cursor.getCount());
+        cursor.moveToFirst();
+        assertEquals(name2, cursor.getString(0));
+        cursor.moveToNext();
+        assertEquals(name3, cursor.getString(0));
+    }
+
+    /**
+     * Test URL_RESTOREAPN_USING_SUBID works correctly.
+     */
+    @Test
+    @SmallTest
+    public void testRestoreDefaultApn() {
+        // setup for multi-SIM
+        TelephonyManager telephonyManager =
+                (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(2).when(telephonyManager).getPhoneCount();
+
+        // create APN to be deleted (including MVNO values)
+        ContentValues targetValues = new ContentValues();
+        targetValues.put(Carriers.APN, "apnName");
+        targetValues.put(Carriers.NAME, "name");
+        targetValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+        targetValues.put(Carriers.MVNO_TYPE, "spn");
+        targetValues.put(Carriers.MVNO_MATCH_DATA, TelephonyProviderTestable.TEST_SPN);
+        // create other operator APN (sama MCCMNC)
+        ContentValues otherValues = new ContentValues();
+        final String otherApn = "otherApnName";
+        final String otherName = "otherName";
+        final String otherMvnoTyp = "spn";
+        final String otherMvnoMatchData = "testOtherOperator";
+        otherValues.put(Carriers.APN, otherApn);
+        otherValues.put(Carriers.NAME, otherName);
+        otherValues.put(Carriers.NUMERIC, TEST_OPERATOR);
+        otherValues.put(Carriers.MVNO_TYPE, otherMvnoTyp);
+        otherValues.put(Carriers.MVNO_MATCH_DATA, otherMvnoMatchData);
+
+        // insert APNs
+        Log.d(TAG, "testRestoreDefaultApn: Bulk inserting contentValues=" + targetValues + ", "
+                + otherValues);
+        ContentValues[] values = new ContentValues[]{ targetValues, otherValues };
+        mContentResolver.bulkInsert(Carriers.CONTENT_URI, values);
+
+        // restore to default
+        mContentResolver.delete(URL_RESTOREAPN_USING_SUBID, null, null);
+
+        // get values in table
+        final String[] testProjection =
+        {
+            Carriers.APN,
+            Carriers.NAME,
+            Carriers.MVNO_TYPE,
+            Carriers.MVNO_MATCH_DATA,
+        };
+        // verify that deleted result match results of query
+        Cursor cursor = mContentResolver.query(
+                Carriers.CONTENT_URI, testProjection, null, null, null);
+        assertEquals(1, cursor.getCount());
+        cursor.moveToFirst();
+        assertEquals(otherApn, cursor.getString(0));
+        assertEquals(otherName, cursor.getString(1));
+        assertEquals(otherMvnoTyp, cursor.getString(2));
+        assertEquals(otherMvnoMatchData, cursor.getString(3));
+
+        // create APN to be deleted (not include MVNO values)
+        ContentValues targetValues2 = new ContentValues();
+        targetValues2.put(Carriers.APN, "apnName");
+        targetValues2.put(Carriers.NAME, "name");
+        targetValues2.put(Carriers.NUMERIC, TEST_OPERATOR);
+
+        // insert APN
+        mContentResolver.insert(Carriers.CONTENT_URI, targetValues2);
+
+        // restore to default
+        mContentResolver.delete(URL_RESTOREAPN_USING_SUBID, null, null);
+
+        // verify that deleted result match results of query
+        cursor = mContentResolver.query(Carriers.CONTENT_URI, testProjection, null, null, null);
+        assertEquals(1, cursor.getCount());
+        cursor.moveToFirst();
+        assertEquals(otherApn, cursor.getString(0));
+        assertEquals(otherName, cursor.getString(1));
+        assertEquals(otherMvnoTyp, cursor.getString(2));
+        assertEquals(otherMvnoMatchData, cursor.getString(3));
+
+        // setup for single-SIM
+        doReturn(1).when(telephonyManager).getPhoneCount();
+
+        // restore to default
+        mContentResolver.delete(URL_RESTOREAPN_USING_SUBID, null, null);
+
+        // verify that deleted values are gone
+        cursor = mContentResolver.query(
+                Carriers.CONTENT_URI, testProjection, null, null, null);
+        assertEquals(0, cursor.getCount());
+        assertEquals(3, notifyChangeRestoreCount);
+    }
 }
diff --git a/tests/src/com/android/providers/telephony/TelephonyProviderTestable.java b/tests/src/com/android/providers/telephony/TelephonyProviderTestable.java
index c3924c3..0a12831 100644
--- a/tests/src/com/android/providers/telephony/TelephonyProviderTestable.java
+++ b/tests/src/com/android/providers/telephony/TelephonyProviderTestable.java
@@ -19,14 +19,19 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.provider.Telephony;
+import android.support.test.InstrumentationRegistry;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 import android.util.Log;
 
 import java.util.List;
 import java.util.ArrayList;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.uicc.IccRecords;
 import com.android.providers.telephony.TelephonyProvider;
 import static android.provider.Telephony.Carriers.*;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 
 /**
  * A subclass of TelephonyProvider used for testing on an in-memory database
@@ -34,12 +39,26 @@
 public class TelephonyProviderTestable extends TelephonyProvider {
     private static final String TAG = "TelephonyProviderTestable";
 
+    @VisibleForTesting
+    public static final String TEST_SPN = "testspn";
+
     private InMemoryTelephonyProviderDbHelper mDbHelper;
+    private MockInjector mMockInjector;
+
+    public TelephonyProviderTestable() {
+        this(new MockInjector());
+    }
+
+    private TelephonyProviderTestable(MockInjector mockInjector) {
+        super(mockInjector);
+        mMockInjector = mockInjector;
+    }
 
     @Override
     public boolean onCreate() {
         Log.d(TAG, "onCreate called: mDbHelper = new InMemoryTelephonyProviderDbHelper()");
         mDbHelper = new InMemoryTelephonyProviderDbHelper();
+        s_apnSourceServiceExists = false;
         return true;
     }
 
@@ -71,6 +90,18 @@
         return false;
     }
 
+    @Override
+    IccRecords getIccRecords(int subId) {
+        Log.d(TAG, "getIccRecords called");
+        IccRecords iccRecords = mock(IccRecords.class);
+        doReturn(TEST_SPN).when(iccRecords).getServiceProviderName();
+        return iccRecords;
+    }
+
+    public void fakeCallingUid(int uid) {
+        mMockInjector.fakeCallingUid(uid);
+    }
+
     /**
      * An in memory DB for TelephonyProviderTestable to use
      */
@@ -78,7 +109,7 @@
 
 
         public InMemoryTelephonyProviderDbHelper() {
-            super(null,      // no context is needed for in-memory db
+            super(InstrumentationRegistry.getTargetContext(),
                     null,    // db file name is null for in-memory db
                     null,    // CursorFactory is null by default
                     1);      // db version is no-op for tests
@@ -93,7 +124,7 @@
 
             // set up the siminfo table
             Log.d(TAG, "InMemoryTelephonyProviderDbHelper onCreate creating the siminfo table");
-            db.execSQL(CREATE_SIMINFO_TABLE_STRING);
+            db.execSQL(getStringForSimInfoTableCreation("siminfo"));
         }
 
         @Override
@@ -102,4 +133,17 @@
             return;
         }
     }
+
+    static class MockInjector extends Injector {
+        private int callingUid = 0;
+
+        @Override
+        int binderGetCallingUid() {
+            return callingUid;
+        }
+
+        void fakeCallingUid(int uid) {
+            callingUid = uid;
+        }
+    }
 }