[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;
+ }
+ }
}