[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: 70ee872f10 -s ours
am skip reason: subject contains skip directive
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/services/Telephony/+/25442154
Change-Id: Ibb73bf6b9e002de898e71fa32508ba20a87ccad7
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index dc35c5d..7ab0990 100644
--- a/Android.bp
+++ b/Android.bp
@@ -41,9 +41,12 @@
"com.android.phone.common-lib",
"guava",
"PlatformProperties",
+ "modules-utils-fastxmlserializer",
"modules-utils-os",
"nist-sip",
- "service-entitlement"
+ "service-entitlement",
+ "telephony_flags_core_java_lib",
+ "android.permission.flags-aconfig-java",
],
srcs: [
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8d03ed7..eef01fa 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -279,7 +279,7 @@
<activity android:name="GsmUmtsCallForwardOptions"
android:label="@string/labelCF"
android:configChanges="orientation|screenSize|keyboardHidden"
- android:exported="true"
+ android:exported="false"
android:theme="@style/CallSettingsWithoutDividerTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -289,7 +289,7 @@
<activity android:name="CdmaCallForwardOptions"
android:label="@string/labelCF"
android:configChanges="orientation|screenSize|keyboardHidden"
- android:exported="true"
+ android:exported="false"
android:theme="@style/CallSettingsWithoutDividerTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -299,7 +299,7 @@
<activity android:name="GsmUmtsCallBarringOptions"
android:label="@string/labelCallBarring"
android:configChanges="orientation|screenSize|keyboardHidden"
- android:exported="true"
+ android:exported="false"
android:theme="@style/DialerSettingsLight">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -309,7 +309,7 @@
<activity android:name="GsmUmtsAdditionalCallOptions"
android:label="@string/labelGSMMore"
android:configChanges="orientation|screenSize|keyboardHidden"
- android:exported="true"
+ android:exported="false"
android:theme="@style/CallSettingsWithoutDividerTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/OWNERS b/OWNERS
index 0fed2f0..53b9401 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,17 +1,5 @@
-breadley@google.com
-fionaxu@google.com
-jackyu@google.com
-rgreenwalt@google.com
-tgunn@google.com
-sarahchin@google.com
-xiaotonj@google.com
-huiwang@google.com
-jayachandranc@google.com
-chinmayd@google.com
-amruthr@google.com
-sasindran@google.com
-tjstuart@google.com
-pmadapurmath@google.com
-grantmenke@google.com
+include platform/frameworks/opt/telephony:/OWNERS
per-file *SimPhonebookProvider* = file:platform/packages/apps/Contacts:/OWNERS
+
+per-file config.xml=hwangoo@google.com,forestchoi@google.com,avinashmp@google.com,mkoon@google.com,seheele@google.com,radhikaagrawal@google.com
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 3831b6b..04a8efb 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -9,7 +9,8 @@
]
},
{
- "name": "CarrierAppIntegrationTestCases"
+ "name": "CarrierAppIntegrationTestCases",
+ "keywords": ["internal"]
},
{
"name": "CtsSimRestrictedApisTestCases",
diff --git a/ecc/input/OWNERS b/ecc/input/OWNERS
index 5685875..2ed2f3f 100644
--- a/ecc/input/OWNERS
+++ b/ecc/input/OWNERS
@@ -1,4 +1,5 @@
set noparent
tgunn@google.com
-chinmayd@google.com
\ No newline at end of file
+breadley@google.com
+rgreenwalt@google.com
\ No newline at end of file
diff --git a/ecc/input/eccdata.txt b/ecc/input/eccdata.txt
index 7252480..fe11383 100644
--- a/ecc/input/eccdata.txt
+++ b/ecc/input/eccdata.txt
@@ -906,6 +906,16 @@
types: TYPE_UNSPECIFIED
routing: NORMAL
}
+ eccs {
+ phone_number: "028"
+ types: TYPE_UNSPECIFIED
+ routing: NORMAL
+ }
+ eccs {
+ phone_number: "116000"
+ types: TYPE_UNSPECIFIED
+ routing: NORMAL
+ }
ecc_fallback: "112"
}
countries {
@@ -1372,6 +1382,13 @@
types: AMBULANCE
types: FIRE
}
+ eccs {
+ phone_number: "100"
+ types: POLICE
+ types: AMBULANCE
+ types: FIRE
+ routing: NORMAL
+ }
ecc_fallback: "112"
}
countries {
diff --git a/ecc/output/OWNERS b/ecc/output/OWNERS
index 5685875..2ed2f3f 100644
--- a/ecc/output/OWNERS
+++ b/ecc/output/OWNERS
@@ -1,4 +1,5 @@
set noparent
tgunn@google.com
-chinmayd@google.com
\ No newline at end of file
+breadley@google.com
+rgreenwalt@google.com
\ No newline at end of file
diff --git a/ecc/output/eccdata b/ecc/output/eccdata
index fc86961..55d8151 100644
--- a/ecc/output/eccdata
+++ b/ecc/output/eccdata
Binary files differ
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index c451e65..dab1dfb 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Sub-ID van verstekdata-SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Aflaaibandwydte (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Oplaaibandwydte (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fisieke LTE-kanaalopstelling:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Fisieke kanaalopstellings:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Herlaaikoers van selinligting:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alle selmetingsinligting:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Datadiens:"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 112441b..95437d5 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"የነባሪ ውሂብ ሲም SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL መተላለፊያ ይዘት (ኪቢ/ሴ)፡"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"የUL መተላለፊያ ይዘት (ኪቢ/ሴ)፡"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"የLTE አካላዊ ሰርጥ ውቅረት:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"የአካላዊ ሰርጥ ውቅረቶች፦"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"የሕዋስ መረጃ እድሳት ፍጥነት፡"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ሁሉም የሕዋስ መለኪያ መረጃ፡"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"የውሂብ አገልግሎት:"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 986e6b6..54eeb24 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"المعرّف الفرعي لشريحة SIM التلقائية للبيانات:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"معدّل نقل بيانات DL (كيلوبت في الثانية):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"معدّل نقل بيانات UL (كيلوبت في الثانية):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"ضبط قناة LTE Physical:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"إعدادات القنوات:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"معدّل إعادة تحميل المعلومات الخلوية:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"جميع معلومات القياس الخلوية:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"خدمة البيانات:"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 87ccace..b68f32b 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ডিফ’ল্ট ডেটা ছিমৰ ছাবআইডি:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL বেণ্ডৱিথ (কেবিপিএছ):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL বেণ্ডৱিথ (কেবিপিএছ):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ফিজিকেল চেনেলৰ কনফিগাৰেশ্বন:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"ফিজিকেল চেনেল কনফিগাৰেশ্বন:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"চেল তথ্য ৰিফ্ৰেশ্বৰ হাৰ:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"সকলো চেল পৰিমাপৰ তথ্য:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"ডেটা সেৱা:"</string>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index b31c670..38a8f9f 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Defolt data SIM üçün alt Id:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL Buraxılışı (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Buraxılışı (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Fiziki Kanal Konfiqurasiyası:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Fiziki Kanal Konfiqurasiyaları:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobil məlumatın yenilənmə göstəricisi:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Operatorun bütün mobil ölçü məlumatı:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Data Xidməti:"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 3474c39..69a0f7b 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubID podrazumevanog SIM-a za podatke:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL propusni opseg (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL propusni opseg (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracija LTE fizičkog kanala:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfiguracije fizičkog kanala:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Učestalost osvežavanja informacija o predajniku:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Sve informacije o merenju za predajnik:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Usluga prenosa podataka:"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 33e26a1..0f7f46a 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubID стандартнай SIM-карты для перадачы даных:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Прапускная здольнасць канала спампоўвання (кбіт/с):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Прапускная здольнасць канала запампоўвання (кбіт/с):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Канфігурацыя фізічнага канала LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Канфігурацыі фізічнага канала:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Частата абнаўлення даных сотавай сеткі:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Усе паказчыкі сотавай сеткі:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Сэрвіс перадачы даных:"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index cf06d50..97f086f 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Идентификационен подномер на SIM картата за данни по подразбиране:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Пропускателна способност при изтегляне (кб/сек):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Пропускателна способност при качване (кб/сек):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфигурация на физическия канал на LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Конфигурации на физическия канал:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Честота на опресняване на информацията за клетките:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Цялата измервателна информация за клетките:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Услуга за данни:"</string>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index b519003..f1fefbc 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ডিফল্ট ডেটা সিমের SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"ডিএল ব্যান্ডউইথ (কেবিপিএস):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"ইউএল ব্যান্ডউইথ (কেবিপিএস):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ফিজিক্যাল চ্যানেল কনফিগারেশন:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"ফিজিক্যাল চ্যানেল কনফিগারেশন:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"সেল তথ্যে রিফ্রেশ রেট:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"সমস্ত সেল পরিমাপ তথ্য:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"ডেটা পরিষেবা:"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 22c5af4..6675ae7 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Pomoćni ID za zadani SIM za prijenos podataka:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL propusnost (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL propusnost (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracija LTE fizičkog kanala:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfiguracije fizičkih kanala:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Interval osvježavanja informacija o ćeliji:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Sve informacije o mjerenju ćelije:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Prijenos podataka:"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index cf1c3a8..6557918 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Subidentificador de la SIM de dades predeterminada:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Amplada de banda de baixada (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Amplada de banda de pujada (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuració del canal físic de LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Configuracions del canal físic:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Freqüència d\'actualització de la informació del mòbil:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Tota la informació de mesures del mòbil:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Servei de dades:"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 520c0de..660da5e 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId výchozí datové SIM karty:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Rychlost stahování (kB/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Rychlost nahrávání (kB/s):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurace fyzického kanálu LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfigurace fyzického kanálu:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Interval obnovení informací o mobilní síti:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Všechny údaje o měření mobilní sítě:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Datová služba:"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index ee33fae..a9dd327 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Under-id for standard-SIM-kort til data:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Båndbredde til download (kB/sek.):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Båndbredde til upload (kB/sek.):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fysisk kanalkonfiguration for LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Fysiske kanalkonfigurationer:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Opdateringsfrekvens for celleoplysninger:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alle oplysninger om cellemåling:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Datatjeneste:"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 722b227..39b16ce 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Unter-ID der standardmäßigen Daten-SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-Bandbreite (kbit/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-Bandbreite (kbit/s):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguration des physischen LTE-Kanals:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfiguration des physischen Kanals:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Aktualisierungsrate der Mobiltelefoninformationen:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alle Informationen zu Zellenmesswerten:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Datendienst:"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index e2c6854..875ae61 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId προεπιλεγμένης SIM δεδομένων:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Εύρος ζώνης DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Εύρος ζώνης UL (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Διαμόρφωση φυσικού καναλιού LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Διαμορφώσεις φυσικού καναλιού:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Ρυθμός ανανέωσης στοιχείων κινητής τηλεφωνίας:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Όλα τα στοιχεία μετρήσεων κινητής τηλεφωνίας:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Υπηρεσία δεδομένων:"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 2d81593..9a7861f 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL bandwidth (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL bandwidth (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE physical channel configuration:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Physical channel configurations:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobile info refresh rate:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All mobile measurement info:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Data service:"</string>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index e7a6f1b..81942d0 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL Bandwidth (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Bandwidth (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Physical Channel Configuration:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Physical Channel Configurations:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Cell Info Refresh Rate:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All Cell Measurement Info:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Data Service:"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 2d81593..9a7861f 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL bandwidth (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL bandwidth (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE physical channel configuration:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Physical channel configurations:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobile info refresh rate:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All mobile measurement info:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Data service:"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 2d81593..9a7861f 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL bandwidth (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL bandwidth (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE physical channel configuration:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Physical channel configurations:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobile info refresh rate:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All mobile measurement info:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Data service:"</string>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index 319986a..d275cc4 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL Bandwidth (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Bandwidth (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Physical Channel Configuration:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Physical Channel Configurations:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Cell Info Refresh Rate:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All Cell Measurement Info:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Data Service:"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index aa4aab1..2a25ded 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ID secundario de SIM de datos predeterminada:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Ancho de banda de descarga (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Ancho de banda de carga (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuración del canal físico de LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Parámetros de configuración de canales físicos:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frecuencia de actualización de datos del celular:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Información sobre las dimensiones del celular:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Servicio de datos:"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index ee17505..26d5631 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ID secundario de la SIM de datos predeterminada:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Ancho de banda de bajada (Kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Ancho de banda de subida (Kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuración del canal físico de LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Configuraciones del canal físico:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frecuencia de actualización de la información del teléfono:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Información sobre las dimensiones de los teléfonos:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Servicio de datos:"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index d306e21..60c4d40 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Andmete vaike-SIM-kaardi alam-ID:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-i ribalaius (kbit/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-i ribalaius (kbit/s):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE füüsilise kanali konfiguratsioon:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Füüsilise kanali seadistused:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Kärje teabe värskendamissagedus:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Kõik kärje mõõteandmed:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Andmesideteenus:"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 9e4b8a7..4790caa 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Datu-konexioetarako SIM lehenetsiaren azpiIDa:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Deskargatzeko banda-zabalera (Kb/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Kargen banda-zabalera (Kb/s):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE kanal fisikoaren konfigurazioa:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Kanal fisikoen konfigurazioa:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Sare mugikorraren informazioa eguneratzeko maiztasuna:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Sare mugikorraren neurketa guztien informazioa:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Datu-zerbitzua:"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 2ff5455..c52cb86 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId مربوط به سیمکارت داده پیشفرض:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"پهنای باند DL (کیلوبیت بر ثانیه):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"پهنای باند UL (کیلوبیت بر ثانیه):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"پیکربندی کانال فیزیکی LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"پیکربندیهای کانال فیزیکی:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"نرخ بازآوری اطلاعات شبکه همراه:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"همه اطلاعات اندازهگیری شبکه همراه:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"سرویس داده:"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 9cf2479..f24af53 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Oletusarvoisen data-SIM-kortin alitunnus:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-kaistanleveys (kt/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-kaistanleveys (kt/s):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fyysisen LTE-kanavan kokoonpano:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Fyysisen kanavan määritykset:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Matkapuhelintietojen päivitysaikaväli:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Matkapuhelimen kaikki mittaustiedot:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Datapalvelu:"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 05e4cfc..95e6ae9 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Sous-identifiant de la carte SIM par défaut :"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bande passante de téléchargement (kb/s) :"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bande passante de téléversement (kb/s) :"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuration du canal physique LTE :"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Configurations des canaux physiques :"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Taux d\'actualisation des données de la cellule :"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Données des mesures de toutes les cellules :"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Service de données :"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 704a5cb..85a5a93 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Sous-identifiant SIM par défaut pour les données :"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bande passante de téléchargement (kbit/s) :"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bande passante d\'importation (kbit/s) :"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuration de la chaîne physique LTE :"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Configurations des canaux physiques :"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Fréquence d\'actualisation des informations mobiles :"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Toutes les informations mobiles liées aux mesures :"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Service de données :"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 8ce562c..5ce9ea3 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Código de identificación secundario da SIM de datos predeterminada:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Largura de banda de descarga (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Largura de banda de carga (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuración de canle física de LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Configuración da canle física:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Taxa de actualización da información para móbiles:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Toda a información de medición para móbiles:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Servizo de datos:"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 6b10ddc..99606a0 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ડિફૉલ્ટ ડેટા સિમનું SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL બૅન્ડવિડ્થ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL બૅન્ડવિડ્થ (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ભૌતિક ચૅનલની ગોઠવણી:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"ચૅનલનું ભૌતિક કન્ફિગ્યુરેશન:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"સેલ માહિતી રિફ્રેશ થવાનો રેટ:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"તમામ સેલ માપ માહિતી:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"ડેટા સેવા:"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 9f45e0b..5d03fe8 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"डिफ़ॉल्ट डेटा सिम का सब-आईडी:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"डीएल बैंडविड्थ (केबीपीएस):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"यूएल बैंडविड्थ (केबीपीएस):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"एलटीई की फ़िज़िकल चैनल कॉन्फ़िगरेशन:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"फ़िज़िकल चैनल के कॉन्फ़िगरेशन:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"सेल की जानकारी रीफ़्रेश होने की दर:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"सभी सेल के माप की पूरी जानकारी:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"डेटा सेवा:"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 692c18d..790b6be 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SUBID zadanog SIM-a za podatkovni promet:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL propusnost (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL propusnost (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracija LTE fizičkog kanala:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfiguracije fizičkog kanala:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Stopa osvježavanja informacija u ćeliji:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Sve informacije ćelija o mjerenju:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Podatkovna usluga:"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index a0226d1..54c112b 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Alapértelmezett adatok SIM-alazonosítója:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Letöltési sávszélesség (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Feltöltési sávszélesség (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE fizikai csatorna konfigurációja:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Fizikai csatorna konfigurációi:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Cellainformáció frissítési gyakorisága:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Minden cellamérési információ:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Adatszolgáltatás:"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 8de0ae2..8e68a06 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SIM քարտի հավելյալ ID կանխադրված բջջային ինտերնետի համար՝"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL թողունակությունը (կբ/վ)՝"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL թողունակությունը (կբ/վ)՝"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ֆիզիկական ալիքի կարգավորում՝"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Ֆիզիկական ալիքի կազմաձևեր՝"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Բջիջի տվյալների թարմացման հաճախականությունը՝"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Բոլոր բջիջների չափման տվյալները՝"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Տվյալների ծառայություն՝"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index d950f84..25e1414 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId SIM data default:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bandwidth DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bandwidth UL (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurasi Saluran Fisik LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfigurasi Saluran Fisik:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Rasio Pembaruan Info Sel"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Semua Info Pengukuran Sel:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Layanan Data:"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 589503f..123519e 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Undirauðkenni sjálfgefins SIM-korts fyrir gögn:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Niðurhalsbandvídd (kb/sek.):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Upphleðslubandvídd (kb/sek.):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE-rásarstilling:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Áþreifanleg stilling stöðva:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Endurnýjunartíðni loftnetaupplýsinga:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Allar mælingarupplýsingar loftneta:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Gagnaþjónusta:"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 68a5335..2b8e870 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ID secondario della SIM dati predefinita:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Larghezza di banda DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Larghezza di banda UL (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configurazione canale fisico LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Configurazioni dei canali fisici:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frequenza di aggiornamento delle informazioni sulle celle:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Informazioni sulla misurazione di tutte le celle:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Servizio dati:"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 16fab20..a51c72d 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -877,7 +877,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"תת-מזהה של כרטיס ה-SIM עם חבילת גלישה המוגדר כברירת מחדל:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"רוחב פס DL (ב-kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"רוחב פס UL (ב-kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"תצורת ערוץ פיזי של LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"ההגדרות האישיות של הערוץ הפיזי"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"קצב רענון של מידע סלולרי:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"כל המידע של מדידה סלולרית:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"שירות נתונים:"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 13ed54d..4127de8 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"デフォルトのデータ SIM の SUBID:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL 帯域幅(kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL 帯域幅(kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE の物理チャネル設定:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"物理チャネルの構成:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"セル情報の更新間隔:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"すべてのセルの測定情報:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"データサービス:"</string>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 586858d..f4ca82e 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"მონაცემების ნაგულისხმევი SIM-ის subId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-არხის გამტარუნარიანობა (კბიტ/წმ):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-არხის გამტარუნარიანობა (კბიტ/წმ):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ფიზიკური არხის კონფიგურაცია:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"არხის ფიზიკური კონფიგურაცია:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ფიჭური ინფორმაციის განახლების სიხშირე:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"სრული ინფორმაცია ფიჭური ქსელის შესახებ:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"მობილური ინტერნეტის სერვისი:"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index a10c8f2..72e9c7f 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Әдепкі деректер SIM картасының қосалқы идентификаторы:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL өткізу мүмкіндігі (кбит/сек):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL өткізу мүмкіндігі (кбит/сек):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE физикалық арна конфигурациясы:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Физикалық арна конфигурациялары:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Ұялы желі туралы ақпаратты жаңарту жиілігі:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Барлық ұялы желі өлшемдері туралы ақпарат:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Деректер қызметі:"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index cc8ac7d..d42deb0 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"លេខសម្គាល់រងរបស់ស៊ីមទិន្នន័យលំនាំដើម៖"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"កម្រិតបញ្ជូន DL (kbps) ៖"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"កម្រិតបញ្ជូន UL (kbps) ៖"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"ការកំណត់រចនាសម្ព័ន្ធបណ្ដាញរូបវ័ន្ត LTE ៖"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"ការកំណត់រចនាសម្ព័ន្ធបណ្ដាញរូបវន្ត៖"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"អត្រាផ្ទុកឡើងវិញនៃព័ត៌មានទូរសព្ទចល័ត៖"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ព័ត៌មានវាស់ទូរសព្ទចល័តទាំងអស់៖"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"សេវាកម្មទិន្នន័យ៖"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index dc25d7c..fe39ede 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ಡೀಫಾಲ್ಟ್ ಡೇಟಾ ಸಿಮ್ನ ವಿಷಯಐಡಿ:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ಬ್ಯಾಂಡ್ವಿಡ್ತ್ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL ಬ್ಯಾಂಡ್ವಿಡ್ತ್ (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ಭೌತಿಕ ಚಾನೆಲ್ ಕಾನ್ಫಿಗರೇಶನ್:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"ಭೌತಿಕ ಚಾನಲ್ ಕಾನ್ಫಿಗರೇಶನ್ಗಳು:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ಸೆಲ್ ಮಾಹಿತಿ ರಿಫ್ರೆಶ್ ದರ:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ಎಲ್ಲಾ ಸೆಲ್ ಮಾಪನ ಮಾಹಿತಿ:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"ಡೇಟಾ ಸೇವೆ:"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index affc995..6b403d9 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"기본 데이터 SIM의 subId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL 대역폭(kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL 대역폭(kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE 물리적 채널 구성:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"물리적 채널 구성:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"셀 정보 새로고침 빈도:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"모든 셀 측정 정보:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"데이터 서비스:"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index fd21eac..3fca1ed 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Демейки оператордун SIM картасынын көз салуу идентификатору:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL өткөрүү жөндөмдүүлүгү (кб/сек.):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL өткөрүү жөндөмдүүлүгү (кб/сек.):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE физикалык каналынын конфигурациясы:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Физикалык каналдын конфигурациялары:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Уюлдук маалыматты жаңылоо ылдамдыгы:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Уюлдук чен-өлчөм маалыматтары:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Мобилдик туташуу кызматы:"</string>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 378b6a4..10ddb89 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId ຂອງຊິມອິນເຕີເນັດເລີ່ມຕົ້ນ:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"ແບນວິດ DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"ແບນວິດ UL (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"ການຕັ້ງຄ່າຊ່ອງ LTE ກາຍະພາບ:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"ການຕັ້ງຄ່າຊ່ອງທາງກາຍະພາບ:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ອັດຕາການໂຫຼດຄືນໃໝ່ຂອງຂໍ້ມູນມືຖື:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ຂໍ້ມູນການວັດແທກມືຖືທັງໝົດ:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"ບໍລິການຂໍ້ມູນ:"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index b765788..9e1a340 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Numatytųjų duomenų SIM kortelės papildomas ID:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL pralaidumas (Kb/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL pralaidumas (Kb/s):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE fizinio kanalo konfigūracija:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Fizinių kanalų konfigūracijos:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobiliojo ryšio informacijos atnaujinimo dažnis:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Visų mobiliųjų ryšių įvertinimo informacija:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Duomenų paslauga:"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 20a8ec9..f8bef4a 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Noklusējuma datu SIM kartes papildu ID:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL joslas platums (kb/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL joslas platums (kb/s):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE fiziskā kanāla konfigurācija:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Fiziskā kanāla konfigurācijas:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobilā tīkla informācijas atsvaidzināšanas biežums:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Visa mobilā tīkla mērījumu informācija:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Datu pakalpojums:"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 480fe90..0ab1b47 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SUBID на стандардната SIM за мобилен интернет:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Брзина на пренос при преземање (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Брзина на пренос при прикачување (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфигурација на физички канал на LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Конфигурации на физички канали:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Стапка на освежување на информациите за мобилниот:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Сите информации за мерењата на мобилниот:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Услуга за мобилен интернет:"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 1820338..b0785bb 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ഡിഫോൾട്ട് ഡാറ്റാ സിമ്മിന്റെ ഉപഐഡി:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ബാൻഡ്വിഡ്ത് (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL ബാൻഡ്വിഡ്ത് (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ഫിസിക്കൽ ചാനൽ കോൺഫിഗറേഷൻ:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"ഫിസിക്കൽ ചാനൽ കോൺഫിഗറേഷനുകൾ:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"സെൽ വിവരങ്ങൾ പുതുക്കിയെടുക്കൽ നിരക്ക്:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"എല്ലാ സെൽ അളവ് വിവരങ്ങളും:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"ഡാറ്റ സേവനം:"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 08e60d1..712042a 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Өгөгдмөл дата SIM-н SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DLзурвасын өргөн (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Мессежийн өргөн (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Сувгийн бодит тохиргоо:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Биет сувгийн тохируулга:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Үүрэн мэдээлэл сэргээх тариф:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Бүх үүрэн хэмжилтийн мэдээлэл:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Дата үйлчилгээ:"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index eda6e6e..76dee50 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"डीफॉल्ट डेटा सिम SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL बँडविड्थ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL बँडविड्थ (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE फिजिकल चॅनल कॉंफिगरेशन:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"प्रत्यक्ष चॅनलची कॉंफिगरेशन:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"सेल माहिती रिफ्रेश रेट:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"सर्व सेल परिमाण माहिती:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"डेटा सर्व्हिस:"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 979ad44..18b47c2 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId SIM data lalai:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Lebar Jalur DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Lebar Jalur UL (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurasi Saluran Fizikal LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfigurasi Saluran Fizikal:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Kadar Muat Semula Maklumat Selular:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Semua Maklumat Ukuran Selular:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Perkhidmatan Data:"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 7025487..8576e1f 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"မူရင်း ဒေတာဆင်းမ်ကဒ်အတွက် Id အခွဲ −"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL မြန်နှုန်း (kbps)−"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL မြန်နှုန်း (kbps)−"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ရုပ်ပိုင်းဆိုင်ရာ ချန်နယ်စီစဉ်သတ်မှတ်မှု−"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"ရုပ်ပိုင်းဆိုင်ရာ ချန်နယ်စီစဉ်သတ်မှတ်ချက်များ-"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ဆဲလ်လူလာ အချက်အလက် ရယူမှုနှုန်း −"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ဆဲလ်လူလာတိုင်းတာမှု အချက်အလက် အားလုံး −"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"ဒေတာ ဝန်ဆောင်မှု −"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 14b25d9..fb8a4fe 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Under-ID for standard-SIM-kort for data:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Båndbredde for nedlasting (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Båndbredde for opplasting (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurering av fysisk LTE-kanal:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfigurasjoner for fysiske kanaler:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Oppdateringsfrekvens for celleinformasjon:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All informasjon for cellemåling:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Datatjeneste:"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 8ef3956..1b399ab 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"डिफल्ट डेटा SIM को SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ब्यान्डविथ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL व्यान्डविथ (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE को भौतिक च्यानलको कन्फिगरेसन:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"भौतिक च्यानलका कन्फिगुरेसनहरू:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"सेलसम्बन्धी जानकारीलाई पुनः ताजा गरिने दर:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"सेलको मापनसम्बन्धी सबै जानकारी:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"डेटा सम्बन्धी सेवा:"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 96c99c7..da89764 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId van standaard simkaart voor data:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL-bandbreedte (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL-bandbreedte (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fysieke LTE-kanaalconfiguratie:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Configuraties voor fysieke kanalen:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Vernieuwingsfrequentie van mobiele data:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alle mobiele meetgegevens:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Gegevensservice:"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index d8277c1..5eea570 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ଡିଫଲ୍ଟ ଡାଟା SIMର SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ବ୍ୟାଣ୍ଡୱିଡଥ୍ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL ବ୍ୟାଣ୍ଡୱିଡଥ୍ (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ଫିଜିକାଲ୍ ଚ୍ୟାନେଲ୍ କନ୍ଫିଗରେସନ୍:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"ଫିଜିକାଲ ଚେନେଲ କନଫିଗରେସନଗୁଡ଼ିକ:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ସେଲ୍ ସୂଚନା ରିଫ୍ରେସ୍ ଦର:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ସମସ୍ତ ସେଲ୍ ପରିମାପ ସୂଚନା:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"ଡାଟା ସେବା:"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 33ed1bd..8dd6abd 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਡਾਟਾ ਸਿਮ ਦਾ SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL ਬੈਂਡਵਿਡਥ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL ਬੈਂਡਵਿਡਥ (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ਭੌਤਿਕ ਚੈਨਲ ਸੰਰੂਪਣ:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"ਭੌਤਿਕ ਚੈਨਲ ਸੰਰੂਪਣ:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"ਸੈੱਲ ਦੀ ਜਾਣਕਾਰੀ ਦੀ ਰਿਫ੍ਰੈਸ਼ ਦਰ:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ਸਾਰੀ ਸੈੱਲ ਮਾਪ ਜਾਣਕਾਰੀ:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"ਡਾਟਾ ਸੇਵਾ:"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 9e4927e..18ff3b1 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Identyfikator domyślnej karty SIM do transmisji danych:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Przepustowość kanału DL (kb/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Przepustowość kanału UL (kb/s):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracja kanału fizycznego LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfiguracje kanału fizycznego:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Częstotliwość odświeżania informacji o sieci komórkowej:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Wszystkie informacje pomiarowe z sieci komórkowej:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Usługa transmisji danych:"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index cb028c9..10fb31a 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubID do SIM de dados predefinido:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Largura de banda de transferência (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Largura de banda de carregamento (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuração do canal físico LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Configurações do canal físico:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Taxa de atualização das informações da célula:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Todas as informações de medição de células:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Serviço de dados:"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 78cda63..02288b9 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Subcódigo do chip de dados padrão:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Largura de banda DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Largura de banda UL (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuração do canal físico de LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Configurações do canal físico:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Taxa de atualização das informações do celular:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Todas as informações de medição do celular:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Serviço de dados:"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index e48fcaa..94cf9d4 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId pentru SIM-ul de date prestabilit:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Lățime de bandă de descărcare (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Lățime de bandă de încărcare (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configurarea canalului fizic LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Configurațiile canalului fizic:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Rata de actualizare a informațiilor despre celulă:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Toate informațiile de măsurare despre celulă:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Serviciu de date:"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index dbf6842..ec534c6 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Доп. идентификатор SIM-карты для мобильного Интернета по умолчанию:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Пропускная способность DL-канала (кбит/c):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Пропускная способность UL-канала (кбит/с):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфигурация физического канала LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Конфигурации физического канала:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Частота обновления данных о сетях:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Статистика сети:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Сервис для передачи данных:"</string>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 4206329..22f0a1c 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"පෙරනිමි දත්ත SIM පතේ උප හැඳුනුම:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL කලාප පළල (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL කලාප පළල (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE භෞතික නාලිකා වින්යාසය:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"භෞතික නාලිකා වින්යාස කිරීම්:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"සෙල් තොරතුරු නැවුම් කිරීමේ අනුපාතය:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"සියලු සෙල් මිනුම් තොරතුරු:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"දත්ත සේවාව:"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 26e66ca..623f3c0 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Podradený identifikátor predvolenej dátovej SIM karty:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Rýchlosť pripojenia DL (kB/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Rýchlosť pripojenia UL (kB/s):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurácia fyzického kanála LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfigurácie fyzického kanála:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frekvencia obnovenia informácií o mobilnej sieti:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Všetky informácie o meraní mobilnej siete:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Dátová služba:"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 693a0e3..1f86b13 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ID naročnine privzete kartice SIM za prenos podatkov:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Pasovna širina za prenos (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Pasovna širina za nalaganje (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfiguracija fizičnega kanala LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Fizične konfiguracije kanalov:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frekvenca osveževanja podatkov o celici:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Vsi podatki o meritvah celice:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Podatkovna storitev:"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 3a9307a..0d4d021 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ID-ja dytësore e kartës SIM të parazgjedhur të të dhënave:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Gjerësia e bandës DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Gjerësia e bandës UL (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Konfigurimi i kanalit fizik LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfigurimet e kanalit fizik:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Shpejtësia e rifreskimit të informacioneve të rrjetit celular"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Të gjitha informacionet e matjes së rrjetit celular:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Shërbimi i të dhënave:"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 81073b0..d25009f 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubID подразумеваног SIM-а за податке:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL пропусни опсег (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL пропусни опсег (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфигурација LTE физичког канала:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Конфигурације физичког канала:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Учесталост освежавања информација о предајнику:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Све информације о мерењу за предајник:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Услуга преноса података:"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 2b25ed6..19ce90f 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId för standarddata på SIM-kortet:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bandbredd för nedladdning (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bandbredd för uppladdning (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Fysisk kanalkonfiguration för LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfigurationer för fysiska kanaler:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Frekvens för uppdatering av mastinformation:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alla information om mastmätning:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Datatjänst:"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 9239d02..2cbcafa 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId ya SIM chaguomsingi ya data:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Kipimo Data cha DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Kipimo Data cha UL (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Mipangilio ya Kituo Halisi cha LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Mipangilio ya Kituo Halisi:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Kasi ya Kuonyesha Upya Maelezo ya Simu:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Maelezo Yote ya Vipimo vya Simu:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Huduma ya Data:"</string>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index c2cf5f4..620d4c0 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"இயல்பான டேட்டா சிம்மின் துணை ஐடி:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL இணைய வேகம் (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL இணைய வேகம் (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE ஃபிசிக்கல் சேனல் உள்ளமைவு:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"சேனல் உள்ளமைவுகள்:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"மொபைல் தகவலின் புதுப்பிப்பு விகிதம்:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"அனைத்து மொபைல் அளவீட்டுத் தகவல்:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"டேட்டா சேவை:"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index f0f50bb..45417a6 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ఆటోమేటిక్ డేటా SIM యొక్క SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL బ్యాండ్విడ్త్ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL బ్యాండ్విడ్త్ (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE భౌతిక ఛానెల్ కాన్ఫిగరేషన్:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"ఫిజికల్ ఛానెల్ కాన్ఫిగరేషన్లు:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"సెల్ సమాచార రిఫ్రెష్ సగటు:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"మొత్తం సెల్ పరిమాణ సమాచారం:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"డేటా సేవ:"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index c9dd1c3..1ada10d 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId ของซิมอินเทอร์เน็ตเริ่มต้น:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"แบนด์วิดท์ดาวน์โหลด (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"แบนด์วิดท์อัปโหลด (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"การกำหนดค่าแชเนลทางกายภาพของ LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"การกำหนดค่าแชแนลทางกายภาพ:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"อัตราการรีเฟรชข้อมูลมือถือ:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"ข้อมูลการวัดเครือข่ายมือถือทั้งหมด:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"บริการข้อมูล:"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 94dec21..81d5bd3 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"SubId ng default na data SIM:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL Bandwidth (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Bandwidth (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuration ng LTE Physical Channel:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Mga Configuration ng Physical Channel:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Rate ng Pag-refresh ng Impormasyon ng Cell:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Impormasyon ng Pagsukat sa Lahat ng Cell:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Serbisyo ng Data:"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 4c176ce..40eb5e7 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Varsayılan veri SIM\'inin alt kimliği:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"İndirme Bant Genişliği (kb/sn.):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Yükleme Bant Genişliği (kb/sn.):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Fiziksel Kanal Yapılandırması:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Fiziksel Kanal Yapılandırmaları:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Hücre Bilgilerini Yenileme Hızı:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Tüm Hücre Ölçümü Bilgileri:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Veri Hizmeti:"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index d9e8d8c..345d8e7 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Субідентифікатор SIM-карти для даних за умовчанням:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Пропускна спроможність DL (кбіт/с):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Пропускна спроможність UL (кбіт/с):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Конфігурація фізичного каналу LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Конфігурації фізичного каналу:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Частота оновлення даних про мобільний зв\'язок:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Усі дані про показники мобільного зв\'язку:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Мобільний Інтернет:"</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 71a2373..520f493 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"ڈیفالٹ ڈیٹا SIM کی SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL بینڈ وڈتھ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL بینڈ وڈتھ (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE فزيکل چینل کنفیگریشن:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"چینل کی طبعی کنفیگریشنز:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"سیل کی معلومات ریفریش کرنے کی شرح:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"سیل پیمائش کی تمام معلومات:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"ڈیٹا سروس:"</string>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 2adc7ba..19d5563 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Mobil internet uchun birlamchi SIM kartaning qoʻshimcha identifikatori:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Axborot uzatish tezligi (kbit/s):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL kanalining axborot uzatish tezligi (kbit/s):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE jismoniy kanal konfiguratsiyasi:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Tashqi kanal konfiguratsiyalari:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Tarmoq haqidagi axborotning yangilanish darajasi:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Tarmoq statistikasi:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Mobil internet xizmati:"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index a4a0e35..ebaf17f 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"Mã phụ của SIM dữ liệu mặc định:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Băng thông DL (kb/giây):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Băng thông UL (kb/giây):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Cấu hình kênh LTE thực:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Cấu hình của kênh thực tế:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Tốc độ làm mới thông tin mạng di động:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Toàn bộ thông tin về số đo mạng di động:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Dịch vụ dữ liệu:"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 4aebfe8..f439c6b 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"默认数据 SIM 卡的 SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL 带宽 (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL 带宽 (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE 物理信道配置:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"实体频道配置:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"移动网络信息刷新频率:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"所有移动网络测量信息:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"数据服务:"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index c5eef28..0fadc35 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"預設數據 SIM 卡的子 ID:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"下載頻寬 (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"上載頻寬 (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE 實體渠道設定:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"實體頻道設定:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"發射站資料重新整理頻率:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"所有發射站量度資料:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"數據服務:"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 52a8814..c2aa76c 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"預設資料 SIM 卡的子 ID:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"下行頻寬 (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"上行頻寬 (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE 實體通道設定:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"實體頻道設定:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"行動網路資訊重新整理頻率:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"所有行動網路測量資訊:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"數據服務:"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 51a33ac..452a3c8 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -876,7 +876,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"I-SubId ye-SIM yedatha yokuzenzakalela:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Umkhawulokudonsa we-DL (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Umkhawulokudonsa we-UL (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Ukulungiselelwa okuphathekayo kwesiteshi se-LTE:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"Ukucushwa Kwesiteshi Esiphathekayo:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Isilinganiso sokuqalisa kabusha solwazi lweseli:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Ulwazi lwesilinganiso seseli:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Isevisi yedatha:"</string>
diff --git a/res/values/config.xml b/res/values/config.xml
index ba65302..939faa7 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -318,6 +318,18 @@
<string-array name="thermal_mitigation_allowlisted_packages" translatable="false">
</string-array>
+ <!-- Array of countries that active SIM is needed for emergency calls. Values should be
+ ISO3166 country codes in lowercase. -->
+ <string-array name="config_countries_require_sim_for_emergency" translatable="false">
+ <!-- b/177967010 -->
+ <item>jp</item>
+ <!-- b/230443699 -->
+ <item>in</item>
+ <item>sg</item>
+ <!-- b/198393826 -->
+ <item>de</item>
+ </string-array>
+
<!-- Flag specifying whether the AOSP domain selection is enabled or
the device should fallback to the modem based domain selection architecture. -->
<bool name="config_enable_aosp_domain_selection">false</bool>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b32b030..61143c9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2101,7 +2101,7 @@
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_ul_kbps">UL Bandwidth (kbps):</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="radio_info_phy_chan_config">LTE Physical Channel Configuration:</string>
+ <string name="radio_info_phy_chan_config">Physical Channel Configurations:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_cell_info_refresh_rate">Cell Info Refresh Rate:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
diff --git a/src/com/android/phone/CallNotifier.java b/src/com/android/phone/CallNotifier.java
index 73b61b6..daf3aa2 100644
--- a/src/com/android/phone/CallNotifier.java
+++ b/src/com/android/phone/CallNotifier.java
@@ -489,7 +489,7 @@
public void updatePhoneStateListeners(boolean isRefresh, int updateType, int subIdToUpdate) {
List<SubscriptionInfo> subInfos = SubscriptionManagerService.getInstance()
.getActiveSubscriptionInfoList(mApplication.getOpPackageName(),
- mApplication.getAttributionTag());
+ mApplication.getAttributionTag(), true/*isForAllProfile*/);
// Sort sub id list based on slot id, so that CFI/MWI notifications will be updated for
// slot 0 first then slot 1. This is needed to ensure that when CFI or MWI is enabled for
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index fa85f27..3eafb24 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -39,6 +39,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.PermissionEnforcer;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
@@ -67,8 +68,8 @@
import com.android.internal.telephony.TelephonyPermissions;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.util.ArrayUtils;
+import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.telephony.Rlog;
import java.io.File;
import java.io.FileDescriptor;
@@ -78,12 +79,19 @@
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
import java.util.Objects;
import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
* CarrierConfigLoader binds to privileged carrier apps to fetch carrier config overlays.
@@ -91,6 +99,9 @@
public class CarrierConfigLoader extends ICarrierConfigLoader.Stub {
private static final String LOG_TAG = "CarrierConfigLoader";
+ private static final SimpleDateFormat TIME_FORMAT =
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
+
// Package name for platform carrier config app, bundled with system image.
@NonNull private final String mPlatformCarrierConfigPackage;
@@ -129,7 +140,7 @@
// Broadcast receiver for system events
@NonNull
private final BroadcastReceiver mSystemBroadcastReceiver = new ConfigLoaderBroadcastReceiver();
- @NonNull private final LocalLog mCarrierConfigLoadingLog = new LocalLog(100);
+ @NonNull private final LocalLog mCarrierConfigLoadingLog = new LocalLog(256);
// Number of phone instances (active modem count)
private int mNumPhones;
@@ -228,7 +239,7 @@
@Override
public void handleMessage(@NonNull Message msg) {
final int phoneId = msg.arg1;
- logdWithLocalLog("mHandler: " + eventToString(msg.what) + " phoneId: " + phoneId);
+ logd(eventToString(msg.what) + " phoneId: " + phoneId);
if (!SubscriptionManager.isValidPhoneId(phoneId)
&& msg.what != EVENT_MULTI_SIM_CONFIG_CHANGED) {
return;
@@ -276,19 +287,11 @@
PersistableBundle config = restoreConfigFromXml(
mPlatformCarrierConfigPackage, OVERRIDE_PACKAGE_ADDITION, phoneId);
if (config != null) {
- logd("Loaded persistent override config from XML. package="
- + mPlatformCarrierConfigPackage
- + " phoneId=" + phoneId);
mPersistentOverrideConfigs[phoneId] = config;
}
config = restoreConfigFromXml(mPlatformCarrierConfigPackage, "", phoneId);
if (config != null) {
- logd(
- "Loaded config from XML. package="
- + mPlatformCarrierConfigPackage
- + " phoneId="
- + phoneId);
mConfigFromDefaultApp[phoneId] = config;
Message newMsg = obtainMessage(EVENT_FETCH_DEFAULT_DONE, phoneId, -1);
newMsg.getData().putBoolean("loaded_from_xml", true);
@@ -363,10 +366,10 @@
carrierService.getCarrierConfig(phoneId, carrierId, resultReceiver);
logdWithLocalLog("Fetch config for default app: "
+ mPlatformCarrierConfigPackage
- + " carrierid: " + carrierId.toString());
+ + ", carrierId=" + carrierId.getSpecificCarrierId());
} catch (RemoteException e) {
loge("Failed to get carrier config from default app: " +
- mPlatformCarrierConfigPackage + " err: " + e.toString());
+ mPlatformCarrierConfigPackage + " err: " + e);
unbindIfBound(mContext, conn, phoneId);
break; // So we don't set a timeout.
}
@@ -418,11 +421,6 @@
final PersistableBundle config =
restoreConfigFromXml(carrierPackageName, "", phoneId);
if (config != null) {
- logd(
- "Loaded config from XML. package="
- + carrierPackageName
- + " phoneId="
- + phoneId);
mConfigFromCarrierApp[phoneId] = config;
Message newMsg = obtainMessage(EVENT_FETCH_CARRIER_DONE, phoneId, -1);
newMsg.getData().putBoolean("loaded_from_xml", true);
@@ -503,9 +501,9 @@
carrierService.getCarrierConfig(phoneId, carrierId, resultReceiver);
logdWithLocalLog("Fetch config for carrier app: "
+ getCarrierPackageForPhoneId(phoneId)
- + " carrierid: " + carrierId.toString());
+ + ", carrierId=" + carrierId.getSpecificCarrierId());
} catch (RemoteException e) {
- loge("Failed to get carrier config: " + e.toString());
+ loge("Failed to get carrier config: " + e);
unbindIfBound(mContext, conn, phoneId);
break; // So we don't set a timeout.
}
@@ -577,8 +575,6 @@
restoreNoSimConfigFromXml(mPlatformCarrierConfigPackage);
if (config != null) {
- logd("Loaded no SIM config from XML. package="
- + mPlatformCarrierConfigPackage);
mNoSimConfig = config;
sendMessage(
obtainMessage(
@@ -673,7 +669,7 @@
+ mPlatformCarrierConfigPackage);
} catch (RemoteException e) {
loge("Failed to get no sim carrier config from default app: " +
- mPlatformCarrierConfigPackage + " err: " + e.toString());
+ mPlatformCarrierConfigPackage + " err: " + e);
unbindIfBoundForNoSimConfig(mContext, conn, phoneId);
break; // So we don't set a timeout.
}
@@ -695,6 +691,7 @@
*/
@VisibleForTesting
/* package */ CarrierConfigLoader(@NonNull Context context, @NonNull Looper looper) {
+ super(PermissionEnforcer.fromContext(context));
mContext = context;
mPlatformCarrierConfigPackage =
mContext.getString(R.string.platform_carrier_config_package);
@@ -1003,7 +1000,7 @@
int phoneId, @Nullable CarrierIdentifier carrierId, @NonNull PersistableBundle config,
boolean isNoSimConfig) {
if (packageName == null) {
- loge("Cannot save config with null packageName");
+ loge("Cannot save config with null packageName. phoneId=" + phoneId);
return;
}
@@ -1013,7 +1010,7 @@
} else {
if (TelephonyManager.getSimStateForSlotIndex(phoneId)
!= TelephonyManager.SIM_STATE_LOADED) {
- loge("Skip save config because SIM records are not loaded.");
+ loge("Skip saving config because SIM records are not loaded. phoneId=" + phoneId);
return;
}
@@ -1021,7 +1018,7 @@
final int cid = carrierId != null ? carrierId.getSpecificCarrierId()
: TelephonyManager.UNKNOWN_CARRIER_ID;
if (iccid == null) {
- loge("Cannot save config with null iccid.");
+ loge("Cannot save config with null iccid. phoneId=" + phoneId);
return;
}
fileName = getFilenameForConfig(packageName, extraString, iccid, cid);
@@ -1038,12 +1035,12 @@
final String version = getPackageVersion(packageName);
if (version == null) {
- loge("Failed to get package version for: " + packageName);
+ loge("Failed to get package version for: " + packageName + ", phoneId=" + phoneId);
return;
}
- logdWithLocalLog(
- "Save config to xml, packagename: " + packageName + " phoneId: " + phoneId);
+ logdWithLocalLog("Save carrier config to cache. phoneId=" + phoneId
+ + ", xml=" + getFilePathForLogging(fileName) + ", version=" + version);
FileOutputStream outFile = null;
try {
@@ -1104,52 +1101,52 @@
} else {
if (TelephonyManager.getSimStateForSlotIndex(phoneId)
!= TelephonyManager.SIM_STATE_LOADED) {
- loge("Skip restore config because SIM records are not loaded.");
+ loge("Skip restore config because SIM records are not loaded. phoneId=" + phoneId);
return null;
}
iccid = getIccIdForPhoneId(phoneId);
final int cid = getSpecificCarrierIdForPhoneId(phoneId);
if (iccid == null) {
- loge("Cannot restore config with null iccid.");
+ loge("Cannot restore config with null iccid. phoneId=" + phoneId);
return null;
}
fileName = getFilenameForConfig(packageName, extraString, iccid, cid);
}
PersistableBundle restoredBundle = null;
- File file = null;
- FileInputStream inFile = null;
- try {
- file = new File(mContext.getFilesDir(),fileName);
- inFile = new FileInputStream(file);
+ File file = new File(mContext.getFilesDir(), fileName);
+ String filePath = file.getPath();
+ String savedVersion = null;
+ try (FileInputStream inFile = new FileInputStream(file)) {
restoredBundle = PersistableBundle.readFromStream(inFile);
- String savedVersion = restoredBundle.getString(KEY_VERSION);
+ savedVersion = restoredBundle.getString(KEY_VERSION);
restoredBundle.remove(KEY_VERSION);
if (!version.equals(savedVersion)) {
- loge("Saved version mismatch: " + version + " vs " + savedVersion);
+ loge("Saved version mismatch: " + version + " vs " + savedVersion
+ + ", phoneId=" + phoneId);
restoredBundle = null;
}
-
- inFile.close();
} catch (FileNotFoundException e) {
// Missing file is normal occurrence that might occur with a new sim or when restoring
// an override file during boot and should not be treated as an error.
- if (file != null) {
- if (isNoSimConfig) {
- logd("File not found: " + file.getPath());
- } else {
- String filePath = file.getPath();
- filePath = getFilePathForLogging(filePath, iccid);
- logd("File not found : " + filePath);
- }
+ if (isNoSimConfig) {
+ logd("File not found: " + file.getPath() + ", phoneId=" + phoneId);
+ } else {
+ logd("File not found : " + getFilePathForLogging(filePath, iccid)
+ + ", phoneId=" + phoneId);
}
} catch (IOException e) {
loge(e.toString());
}
+ if (restoredBundle != null) {
+ logdWithLocalLog("Restored carrier config from cache. phoneId=" + phoneId + ", xml="
+ + getFilePathForLogging(fileName) + ", version=" + savedVersion
+ + ", modified time=" + getFileTime(filePath));
+ }
return restoredBundle;
}
@@ -1159,7 +1156,7 @@
@NonNull
private String getFilePathForLogging(@Nullable String filePath, @Nullable String iccid) {
// If loggable then return with actual file path
- if (Rlog.isLoggable(LOG_TAG, Log.VERBOSE)) {
+ if (TelephonyUtils.IS_DEBUGGABLE) {
return filePath;
}
String path = filePath;
@@ -1203,7 +1200,7 @@
});
if (packageFiles == null || packageFiles.length < 1) return false;
for (File f : packageFiles) {
- logd("Deleting " + getFilePathForLogging(f.getName()));
+ logdWithLocalLog("Deleting " + getFilePathForLogging(f.getName()));
f.delete();
}
return true;
@@ -1408,11 +1405,11 @@
return configSubset;
}
+ @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@Override
public void overrideConfig(int subscriptionId, @Nullable PersistableBundle overrides,
boolean persistent) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.MODIFY_PHONE_STATE, null);
+ overrideConfig_enforcePermission();
int phoneId = SubscriptionManager.getPhoneId(subscriptionId);
if (!SubscriptionManager.isValidPhoneId(phoneId)) {
logd("Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId);
@@ -1440,6 +1437,8 @@
fileToDelete.delete();
}
}
+ logdWithLocalLog("overrideConfig: subId=" + subscriptionId + ", persistent="
+ + persistent + ", overrides=" + overrides);
updateSubscriptionDatabase(phoneId);
});
}
@@ -1469,6 +1468,9 @@
"Invalid phoneId " + phoneId + " for subId " + subscriptionId);
}
+ logdWithLocalLog("Notified carrier config changed. phoneId=" + phoneId
+ + ", subId=" + subscriptionId);
+
// This method should block until deleting has completed, so that an error which prevents us
// from clearing the cache is passed back to the carrier app. With the files successfully
// deleted, this can return and we will eventually bind to the carrier app.
@@ -1478,11 +1480,11 @@
updateConfigForPhoneId(phoneId);
}
+ @android.annotation.EnforcePermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@Override
public void updateConfigForPhoneId(int phoneId, @NonNull String simState) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.MODIFY_PHONE_STATE, null);
- logdWithLocalLog("Update config for phoneId: " + phoneId + " simState: " + simState);
+ updateConfigForPhoneId_enforcePermission();
+ logdWithLocalLog("Update config for phoneId=" + phoneId + " simState=" + simState);
if (!SubscriptionManager.isValidPhoneId(phoneId)) {
throw new IllegalArgumentException("Invalid phoneId: " + phoneId);
}
@@ -1502,12 +1504,11 @@
}
}
+ @android.annotation.EnforcePermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@Override
@NonNull
public String getDefaultCarrierServicePackageName() {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
- "getDefaultCarrierServicePackageName");
+ getDefaultCarrierServicePackageName_enforcePermission();
return mPlatformCarrierConfigPackage;
}
@@ -1573,6 +1574,27 @@
}
/**
+ * Get the file time in readable format.
+ *
+ * @param filePath The full file path.
+ *
+ * @return The time in string format.
+ */
+ @Nullable
+ private String getFileTime(@NonNull String filePath) {
+ String formattedModifiedTime = null;
+ try {
+ // Convert the modified time to a readable format
+ formattedModifiedTime = TIME_FORMAT.format(Files.readAttributes(Paths.get(filePath),
+ BasicFileAttributes.class).lastModifiedTime().toMillis());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return formattedModifiedTime;
+ }
+
+ /**
* If {@code args} contains {@link #DUMP_ARG_REQUESTING_PACKAGE} and a following package name,
* we'll also call {@link IBinder#dump} on the default carrier service (if bound) and the
* specified carrier service (if bound). Typically, this is done for connectivity bug reports
@@ -1613,8 +1635,20 @@
}
printConfig(mNoSimConfig, indentPW, "mNoSimConfig");
- indentPW.println("CarrierConfigLoadingLog=");
+ indentPW.println("mNumPhones=" + mNumPhones);
+ indentPW.println("mPlatformCarrierConfigPackage=" + mPlatformCarrierConfigPackage);
+ indentPW.println("mServiceConnection=[" + Stream.of(mServiceConnection)
+ .map(c -> c != null ? c.pkgName : null)
+ .collect(Collectors.joining(", ")) + "]");
+ indentPW.println("mServiceBoundForNoSimConfig="
+ + Arrays.toString(mServiceBoundForNoSimConfig));
+ indentPW.println("mHasSentConfigChange=" + Arrays.toString(mHasSentConfigChange));
+ indentPW.println("mFromSystemUnlocked=" + Arrays.toString(mFromSystemUnlocked));
+ indentPW.println();
+ indentPW.println("CarrierConfigLoader local log=");
+ indentPW.increaseIndent();
mCarrierConfigLoadingLog.dump(fd, indentPW, args);
+ indentPW.decreaseIndent();
if (requestingPackage != null) {
logd("Including default and requesting package " + requestingPackage
@@ -1626,6 +1660,16 @@
dumpCarrierServiceIfBound(fd, indentPW, "Requesting package", requestingPackage,
true /* considerCarrierPrivileges */);
}
+
+ indentPW.println();
+ indentPW.println("Cached config files:");
+ indentPW.increaseIndent();
+ for (File f : mContext.getFilesDir().listFiles((FilenameFilter) (d, filename)
+ -> filename.startsWith("carrierconfig-"))) {
+ indentPW.println(getFilePathForLogging(f.getName()) + ", modified time="
+ + getFileTime(f.getAbsolutePath()));
+ }
+ indentPW.decreaseIndent();
}
private void printConfig(@NonNull PersistableBundle configApp,
diff --git a/src/com/android/phone/CdmaCallOptions.java b/src/com/android/phone/CdmaCallOptions.java
index 6145870..4f94b58 100644
--- a/src/com/android/phone/CdmaCallOptions.java
+++ b/src/com/android/phone/CdmaCallOptions.java
@@ -16,8 +16,10 @@
package com.android.phone;
+import android.content.Context;
import android.os.Bundle;
import android.os.PersistableBundle;
+import android.os.UserManager;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.telephony.CarrierConfigManager;
@@ -30,6 +32,7 @@
import android.view.MenuItem;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.flags.Flags;
public class CdmaCallOptions extends TimeConsumingPreferenceActivity {
private static final String LOG_TAG = "CdmaCallOptions";
@@ -78,9 +81,21 @@
buttonVoicePrivacy.setEnabled(false);
}
+ // If mobile network configs are restricted, then hide the mCallForwardingPref and
+ // mCallWaitingPref.
+ UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
+ boolean mobileNetworkConfigsRestricted =
+ userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
+ if (Flags.ensureAccessToCallSettingsIsRestricted() && mobileNetworkConfigsRestricted) {
+ Log.i(LOG_TAG, "Mobile network configs are restricted, hiding CDMA call forwarding "
+ + "and CDMA call waiting options.");
+ }
+
mCallForwardingPref = getPreferenceScreen().findPreference(CALL_FORWARDING_KEY);
if (carrierConfig != null && carrierConfig.getBoolean(
- CarrierConfigManager.KEY_CALL_FORWARDING_VISIBILITY_BOOL)) {
+ CarrierConfigManager.KEY_CALL_FORWARDING_VISIBILITY_BOOL) &&
+ (!mobileNetworkConfigsRestricted ||
+ !Flags.ensureAccessToCallSettingsIsRestricted())) {
mCallForwardingPref.setIntent(
subInfoHelper.getIntent(CdmaCallForwardOptions.class));
} else {
@@ -91,7 +106,9 @@
mCallWaitingPref = (CdmaCallWaitingPreference) getPreferenceScreen()
.findPreference(CALL_WAITING_KEY);
if (carrierConfig == null || !carrierConfig.getBoolean(
- CarrierConfigManager.KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL)) {
+ CarrierConfigManager.KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL) ||
+ (Flags.ensureAccessToCallSettingsIsRestricted() &&
+ mobileNetworkConfigsRestricted)) {
getPreferenceScreen().removePreference(mCallWaitingPref);
mCallWaitingPref = null;
}
diff --git a/src/com/android/phone/GsmUmtsCallOptions.java b/src/com/android/phone/GsmUmtsCallOptions.java
index 51d1b66..be5295d 100644
--- a/src/com/android/phone/GsmUmtsCallOptions.java
+++ b/src/com/android/phone/GsmUmtsCallOptions.java
@@ -16,16 +16,20 @@
package com.android.phone;
+import android.content.Context;
import android.os.Bundle;
import android.os.PersistableBundle;
+import android.os.UserManager;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
+import android.util.Log;
import android.view.MenuItem;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.flags.Flags;
public class GsmUmtsCallOptions extends PreferenceActivity {
private static final String LOG_TAG = "GsmUmtsCallOptions";
@@ -79,10 +83,23 @@
isAirplaneModeOff = PhoneGlobals.AIRPLANE_ON != airplaneMode;
}
+ // If mobile network configs are restricted, then hide the GsmUmtsCallForwardOptions,
+ // GsmUmtsAdditionalCallOptions, and GsmUmtsCallBarringOptions.
+ UserManager userManager = (UserManager) subInfoHelper.getPhone().getContext()
+ .getSystemService(Context.USER_SERVICE);
+ boolean mobileNetworkConfigsRestricted =
+ userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
+ if (Flags.ensureAccessToCallSettingsIsRestricted() && mobileNetworkConfigsRestricted) {
+ Log.i(LOG_TAG, "Mobile network configs are restricted, hiding GSM call "
+ + "forwarding, additional call settings, and call options.");
+ }
+
Preference callForwardingPref = prefScreen.findPreference(CALL_FORWARDING_KEY);
if (callForwardingPref != null) {
if (b != null && b.getBoolean(
- CarrierConfigManager.KEY_CALL_FORWARDING_VISIBILITY_BOOL)) {
+ CarrierConfigManager.KEY_CALL_FORWARDING_VISIBILITY_BOOL) &&
+ (!Flags.ensureAccessToCallSettingsIsRestricted() ||
+ !mobileNetworkConfigsRestricted)) {
callForwardingPref.setIntent(
subInfoHelper.getIntent(GsmUmtsCallForwardOptions.class));
callForwardingPref.setEnabled(isAirplaneModeOff);
@@ -97,7 +114,9 @@
if (b != null && (b.getBoolean(
CarrierConfigManager.KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL)
|| b.getBoolean(
- CarrierConfigManager.KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL))) {
+ CarrierConfigManager.KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL)) &&
+ (!Flags.ensureAccessToCallSettingsIsRestricted() ||
+ !mobileNetworkConfigsRestricted)) {
additionalGsmSettingsPref.setIntent(
subInfoHelper.getIntent(GsmUmtsAdditionalCallOptions.class));
additionalGsmSettingsPref.setEnabled(isAirplaneModeOff);
@@ -108,7 +127,9 @@
Preference callBarringPref = prefScreen.findPreference(CALL_BARRING_KEY);
if (callBarringPref != null) {
- if (b != null && b.getBoolean(CarrierConfigManager.KEY_CALL_BARRING_VISIBILITY_BOOL)) {
+ if (b != null && b.getBoolean(CarrierConfigManager.KEY_CALL_BARRING_VISIBILITY_BOOL) &&
+ (!Flags.ensureAccessToCallSettingsIsRestricted() ||
+ !mobileNetworkConfigsRestricted)) {
callBarringPref.setIntent(subInfoHelper.getIntent(GsmUmtsCallBarringOptions.class));
callBarringPref.setEnabled(isAirplaneModeOff);
} else {
diff --git a/src/com/android/phone/IccNetworkDepersonalizationPanel.java b/src/com/android/phone/IccNetworkDepersonalizationPanel.java
index a4ec8a4..7099476 100644
--- a/src/com/android/phone/IccNetworkDepersonalizationPanel.java
+++ b/src/com/android/phone/IccNetworkDepersonalizationPanel.java
@@ -112,7 +112,7 @@
}
public static void dialogDismiss(int phoneId) {
- if (phoneId >= sShowingDialog.length) {
+ if (phoneId >= sShowingDialog.length || !SubscriptionManager.isValidPhoneId(phoneId)) {
Log.e(TAG, "[IccNetworkDepersonalizationPanel] - dismiss; invalid phoneId " + phoneId);
return;
}
diff --git a/src/com/android/phone/ImsProvisioningController.java b/src/com/android/phone/ImsProvisioningController.java
index a62980e..b2e34ae 100644
--- a/src/com/android/phone/ImsProvisioningController.java
+++ b/src/com/android/phone/ImsProvisioningController.java
@@ -839,7 +839,7 @@
mSubscriptionManager = mApp.getSystemService(SubscriptionManager.class);
mTelephonyRegistryManager = mApp.getSystemService(TelephonyRegistryManager.class);
mTelephonyRegistryManager.addOnSubscriptionsChangedListener(
- mSubChangedListener, mSubChangedListener.getHandlerExecutor());
+ mSubChangedListener, mHandler::post);
mImsProvisioningLoader = imsProvisioningLoader;
PhoneConfigurationManager.registerForMultiSimConfigChange(mHandler,
diff --git a/src/com/android/phone/ImsStateCallbackController.java b/src/com/android/phone/ImsStateCallbackController.java
index edad754..019c1ca 100644
--- a/src/com/android/phone/ImsStateCallbackController.java
+++ b/src/com/android/phone/ImsStateCallbackController.java
@@ -739,7 +739,7 @@
updateFeatureControllerSize(numSlots);
mTelephonyRegistryManager.addOnSubscriptionsChangedListener(
- mSubChangedListener, mSubChangedListener.getHandlerExecutor());
+ mSubChangedListener, mHandler::post);
PhoneConfigurationManager.registerForMultiSimConfigChange(mHandler,
EVENT_MSIM_CONFIGURATION_CHANGE, null);
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index b28bd5c..3cd9a8b 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -64,6 +64,8 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.TelephonyCapabilities;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.FeatureFlagsImpl;
import com.android.internal.telephony.util.NotificationChannelController;
import com.android.phone.settings.VoicemailSettingsActivity;
@@ -146,6 +148,9 @@
// maps each subId to selected network operator name.
private SparseArray<String> mSelectedNetworkOperatorName = new SparseArray<>();
+ // feature flags
+ private final FeatureFlags mFeatureFlags;
+
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -177,6 +182,7 @@
mSubscriptionManager = SubscriptionManager.from(mContext);
mTelecomManager = app.getSystemService(TelecomManager.class);
mTelephonyManager = (TelephonyManager) app.getSystemService(Context.TELEPHONY_SERVICE);
+ mFeatureFlags = new FeatureFlagsImpl();
}
/**
@@ -409,7 +415,22 @@
}
}
} else {
- cancelAsUser(Integer.toString(subId) /* tag */, VOICEMAIL_NOTIFICATION, UserHandle.ALL);
+ UserHandle subAssociatedUserHandle =
+ mSubscriptionManager.getSubscriptionUserHandle(subId);
+ List<UserHandle> users = getUsersExcludeDying();
+ for (UserHandle userHandle : users) {
+ boolean isManagedUser = mUserManager.isManagedProfile(userHandle.getIdentifier());
+ if (!hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, userHandle)
+ && (userHandle.equals(subAssociatedUserHandle)
+ || (subAssociatedUserHandle == null && !isManagedUser))
+ && !maybeSendVoicemailNotificationUsingDefaultDialer(phone, 0, null, null,
+ false, userHandle, isRefresh)) {
+ cancelAsUser(
+ Integer.toString(subId) /* tag */,
+ VOICEMAIL_NOTIFICATION,
+ userHandle);
+ }
+ }
}
}
@@ -813,10 +834,73 @@
* @param subId The subscription ID
*/
void updateNetworkSelection(int serviceState, int subId) {
+ if (!mFeatureFlags.dismissNetworkSelectionNotificationOnSimDisable()) {
+ updateNetworkSelectionForFeatureDisabled(serviceState, subId);
+ return;
+ }
+
+ // for dismissNetworkSelectionNotificationOnSimDisable feature enabled.
int phoneId = SubscriptionManager.getPhoneId(subId);
Phone phone = SubscriptionManager.isValidPhoneId(phoneId) ?
PhoneFactory.getPhone(phoneId) : PhoneFactory.getDefaultPhone();
if (TelephonyCapabilities.supportsNetworkSelection(phone)) {
+ if (SubscriptionManager.isValidSubscriptionId(subId)
+ && mSubscriptionManager.isActiveSubId(subId)) {
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+ String selectedNetworkOperatorName =
+ sp.getString(Phone.NETWORK_SELECTION_NAME_KEY + subId, "");
+ // get the shared preference of network_selection.
+ // empty is auto mode, otherwise it is the operator alpha name
+ // in case there is no operator name, check the operator numeric
+ if (TextUtils.isEmpty(selectedNetworkOperatorName)) {
+ selectedNetworkOperatorName =
+ sp.getString(Phone.NETWORK_SELECTION_KEY + subId, "");
+ }
+ boolean isManualSelection;
+ // if restoring manual selection is controlled by framework, then get network
+ // selection from shared preference, otherwise get from real network indicators.
+ boolean restoreSelection = !mContext.getResources().getBoolean(
+ com.android.internal.R.bool.skip_restoring_network_selection);
+ if (restoreSelection) {
+ isManualSelection = !TextUtils.isEmpty(selectedNetworkOperatorName);
+ } else {
+ isManualSelection = phone.getServiceStateTracker().mSS.getIsManualSelection();
+ }
+
+ if (DBG) {
+ log("updateNetworkSelection()..." + "state = " + serviceState + " new network "
+ + (isManualSelection ? selectedNetworkOperatorName : ""));
+ }
+
+ if (isManualSelection) {
+ mSelectedNetworkOperatorName.put(subId, selectedNetworkOperatorName);
+ shouldShowNotification(serviceState, subId);
+ } else {
+ dismissNetworkSelectionNotification(subId);
+ clearUpNetworkSelectionNotificationParam(subId);
+ }
+ } else {
+ if (DBG) {
+ log("updateNetworkSelection()... state = " + serviceState
+ + " not updating network due to invalid subId " + subId);
+ }
+ dismissNetworkSelectionNotificationForInactiveSubId();
+ }
+ }
+ }
+
+ /**
+ * Update notification about no service of user selected operator.
+ * For dismissNetworkSelectionNotificationOnSimDisable feature disabled.
+ *
+ * @param serviceState Phone service state
+ * @param subId The subscription ID
+ */
+ private void updateNetworkSelectionForFeatureDisabled(int serviceState, int subId) {
+ int phoneId = SubscriptionManager.getPhoneId(subId);
+ Phone phone = SubscriptionManager.isValidPhoneId(phoneId)
+ ? PhoneFactory.getPhone(phoneId) : PhoneFactory.getDefaultPhone();
+ if (TelephonyCapabilities.supportsNetworkSelection(phone)) {
if (SubscriptionManager.isValidSubscriptionId(subId)) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
String selectedNetworkOperatorName =
@@ -866,7 +950,10 @@
}
}
- private void dismissNetworkSelectionNotificationForInactiveSubId() {
+ /**
+ * Dismiss the network selection "no service" notification for all inactive subscriptions.
+ */
+ public void dismissNetworkSelectionNotificationForInactiveSubId() {
for (int i = 0; i < mSelectedUnavailableNotify.size(); i++) {
int subId = mSelectedUnavailableNotify.keyAt(i);
if (!mSubscriptionManager.isActiveSubId(subId)) {
@@ -876,15 +963,6 @@
}
}
- /* package */ void postTransientNotification(int notifyId, CharSequence msg) {
- if (mToast != null) {
- mToast.cancel();
- }
-
- mToast = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
- mToast.show();
- }
-
private void log(String msg) {
Log.d(LOG_TAG, msg);
}
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 7a61dd1..483a706 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -71,6 +71,8 @@
import com.android.internal.telephony.data.DataEvaluation.DataDisallowedReason;
import com.android.internal.telephony.domainselection.DomainSelectionResolver;
import com.android.internal.telephony.emergency.EmergencyStateTracker;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.FeatureFlagsImpl;
import com.android.internal.telephony.ims.ImsResolver;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
@@ -181,6 +183,22 @@
/** @hide */
@Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"ROAMING_NOTIFICATION_REASON_"},
+ value = {
+ ROAMING_NOTIFICATION_REASON_DATA_SETTING_CHANGED,
+ ROAMING_NOTIFICATION_REASON_DATA_ROAMING_SETTING_CHANGED,
+ ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED,
+ ROAMING_NOTIFICATION_REASON_SERVICE_STATE_CHANGED,
+ ROAMING_NOTIFICATION_REASON_DEFAULT_DATA_SUBS_CHANGED})
+ public @interface RoamingNotificationReason {}
+ private static final int ROAMING_NOTIFICATION_REASON_DATA_SETTING_CHANGED = 0;
+ private static final int ROAMING_NOTIFICATION_REASON_DATA_ROAMING_SETTING_CHANGED = 1;
+ private static final int ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED = 2;
+ private static final int ROAMING_NOTIFICATION_REASON_SERVICE_STATE_CHANGED = 3;
+ private static final int ROAMING_NOTIFICATION_REASON_DEFAULT_DATA_SUBS_CHANGED = 4;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"ROAMING_NOTIFICATION_"},
value = {
ROAMING_NOTIFICATION_NO_NOTIFICATION,
@@ -193,8 +211,18 @@
private static final int ROAMING_NOTIFICATION_DISCONNECTED = 2;
@RoamingNotification
+ private int mCurrentRoamingNotification = ROAMING_NOTIFICATION_NO_NOTIFICATION;
+
+ /**
+ * Reasons that have already shown notification to prevent duplicate shows for the same reason.
+ */
+ private ArraySet<String> mShownNotificationReasons = new ArraySet<>();
+
+ // For reorganize_roaming_notification feature disabled.
+ @RoamingNotification
private int mPrevRoamingNotification = ROAMING_NOTIFICATION_NO_NOTIFICATION;
+ // For reorganize_roaming_notification feature disabled.
/** Operator numerics for which we've shown is-roaming notifications. **/
private ArraySet<String> mPrevRoamingOperatorNumerics = new ArraySet<>();
@@ -221,6 +249,8 @@
// fine or coarse location since we only use ServiceState for
private PhoneAppCallback[] mTelephonyCallbacks;
+ private FeatureFlags mFeatureFlags;
+
private class PhoneAppCallback extends TelephonyCallback implements
TelephonyCallback.ServiceStateListener {
private final int mSubId;
@@ -333,17 +363,20 @@
break;
case EVENT_SIM_STATE_CHANGED:
- // Marks the event where the SIM goes into ready state.
- // Right now, this is only used for the PUK-unlocking
- // process.
EventSimStateChangedBag bag = (EventSimStateChangedBag)msg.obj;
+ // Dismiss the "No services" notification if the SIM is removed.
+ if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(bag.mIccStatus)) {
+ notificationMgr.dismissNetworkSelectionNotificationForInactiveSubId();
+ }
+
+ // Marks the event where the SIM goes into ready state.
+ // Right now, this is only used for the PUK-unlocking process.
if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(bag.mIccStatus)
|| IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(bag.mIccStatus)
|| IccCardConstants.INTENT_VALUE_ICC_NOT_READY.equals(bag.mIccStatus)
|| IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(bag.mIccStatus)) {
- // when the right event is triggered and there
- // are UI objects in the foreground, we close
- // them to display the lock panel.
+ // When the right event is triggered and there are UI objects in the
+ // foreground, we close them to display the lock panel.
if (mPUKEntryActivity != null) {
Log.i(LOG_TAG, "Dismiss puk entry activity");
mPUKEntryActivity.finish();
@@ -363,8 +396,19 @@
//TODO: handle message here;
break;
case EVENT_DATA_ROAMING_SETTINGS_CHANGED:
+ if (mFeatureFlags.reorganizeRoamingNotification()) {
+ updateDataRoamingStatus(
+ ROAMING_NOTIFICATION_REASON_DATA_ROAMING_SETTING_CHANGED);
+ } else {
+ updateDataRoamingStatusForFeatureDisabled(null);
+ }
+ break;
case EVENT_MOBILE_DATA_SETTINGS_CHANGED:
- updateDataRoamingStatus();
+ if (mFeatureFlags.reorganizeRoamingNotification()) {
+ updateDataRoamingStatus(ROAMING_NOTIFICATION_REASON_DATA_SETTING_CHANGED);
+ } else {
+ updateDataRoamingStatusForFeatureDisabled(null);
+ }
break;
case EVENT_CARRIER_CONFIG_CHANGED:
int subId = (Integer) msg.obj;
@@ -455,7 +499,8 @@
getResources().getBoolean(R.bool.config_enable_aosp_domain_selection));
// Initialize the telephony framework
- PhoneFactory.makeDefaultPhones(this);
+ mFeatureFlags = new FeatureFlagsImpl();
+ PhoneFactory.makeDefaultPhones(this, mFeatureFlags);
// Initialize the DomainSelectionResolver after creating the Phone instance
// to check the Radio HAL version.
@@ -513,7 +558,7 @@
// Create the SatelliteController singleton, which acts as a backend service for
// {@link android.telephony.satellite.SatelliteManager}.
- SatelliteController.make(this);
+ SatelliteController.make(this, mFeatureFlags);
// Create an instance of CdmaPhoneCallState and initialize it to IDLE
cdmaPhoneCallState = new CdmaPhoneCallState();
@@ -528,7 +573,7 @@
mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
- phoneMgr = PhoneInterfaceManager.init(this);
+ phoneMgr = PhoneInterfaceManager.init(this, mFeatureFlags);
imsRcsController = ImsRcsController.init(this);
@@ -573,6 +618,17 @@
intentFilter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
registerReceiver(mReceiver, intentFilter);
+ if (mFeatureFlags.loadDdsOnCreate()) {
+ int defaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId();
+ if (SubscriptionManager.isValidSubscriptionId(defaultDataSubId)) {
+ if (VDBG) {
+ Log.v(LOG_TAG, "Loaded initial default data sub: " + defaultDataSubId);
+ }
+ mDefaultDataSubId = defaultDataSubId;
+ registerSettingsObserver();
+ updateDataRoamingStatus(ROAMING_NOTIFICATION_REASON_DEFAULT_DATA_SUBS_CHANGED);
+ }
+ }
PhoneConfigurationManager.registerForMultiSimConfigChange(
mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
@@ -728,13 +784,14 @@
}
private void handleAirplaneModeChange(boolean isAirplaneNewlyOn) {
+ Log.i(LOG_TAG, "handleAirplaneModeChange: isAirplaneNewlyOn=" + isAirplaneNewlyOn);
int cellState =
Settings.Global.getInt(
getContentResolver(), Settings.Global.CELL_ON, PhoneConstants.CELL_ON_FLAG);
switch (cellState) {
case PhoneConstants.CELL_OFF_FLAG:
- // Airplane mode does not affect the cell radio if user
- // has turned it off.
+ // Airplane mode does not affect the cell radio if user has turned it off.
+ Log.i(LOG_TAG, "Ignore airplane mode change due to cell off.");
break;
case PhoneConstants.CELL_ON_FLAG:
maybeTurnCellOff(isAirplaneNewlyOn);
@@ -774,7 +831,11 @@
/** Clear fields on power off radio **/
private void clearCacheOnRadioOff() {
// Re-show is-roaming notifications after APM mode
- mPrevRoamingOperatorNumerics.clear();
+ if (mFeatureFlags.reorganizeRoamingNotification()) {
+ mShownNotificationReasons.clear();
+ } else {
+ mPrevRoamingOperatorNumerics.clear();
+ }
}
private void setRadioPowerOn() {
@@ -805,12 +866,16 @@
} else {
Log.i(LOG_TAG, "Ignoring airplane mode: settings prevent cell radio power off");
}
+ } else {
+ Log.i(LOG_TAG, "Ignoring airplane mode: not newly on");
}
}
private void maybeTurnCellOn(boolean isAirplaneNewlyOn) {
if (!isAirplaneNewlyOn) {
setRadioPowerOn();
+ } else {
+ Log.i(LOG_TAG, "Ignoring airplane mode off: radio is already on.");
}
}
@@ -867,7 +932,11 @@
} else if (action.equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
// Roaming status could be overridden by carrier config, so we need to update it.
if (VDBG) Log.v(LOG_TAG, "carrier config changed.");
- updateDataRoamingStatus();
+ if (mFeatureFlags.reorganizeRoamingNotification()) {
+ updateDataRoamingStatus(ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED);
+ } else {
+ updateDataRoamingStatusForFeatureDisabled(null);
+ }
updateLimitedSimFunctionForDualSim();
int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
@@ -882,7 +951,12 @@
registerSettingsObserver();
Phone phone = getPhone(mDefaultDataSubId);
if (phone != null) {
- updateDataRoamingStatus();
+ if (mFeatureFlags.reorganizeRoamingNotification()) {
+ updateDataRoamingStatus(
+ ROAMING_NOTIFICATION_REASON_DEFAULT_DATA_SUBS_CHANGED);
+ } else {
+ updateDataRoamingStatusForFeatureDisabled(null);
+ }
}
}
}
@@ -898,7 +972,11 @@
+ mDefaultDataSubId + ", ss roaming=" + serviceState.getDataRoaming());
}
if (subId == mDefaultDataSubId) {
- updateDataRoamingStatus(serviceState.getOperatorNumeric());
+ if (mFeatureFlags.reorganizeRoamingNotification()) {
+ updateDataRoamingStatus(ROAMING_NOTIFICATION_REASON_SERVICE_STATE_CHANGED);
+ } else {
+ updateDataRoamingStatusForFeatureDisabled(serviceState.getOperatorNumeric());
+ }
}
}
@@ -906,11 +984,146 @@
* When roaming, if mobile data cannot be established due to data roaming not enabled, we need
* to notify the user so they can enable it through settings. Vise versa if the condition
* changes, we need to dismiss the notification.
+ * @param reason to inform which event is called for notification update.
*/
- private void updateDataRoamingStatus() {
- updateDataRoamingStatus(null /*roamingOperatorNumeric*/);
+ private void updateDataRoamingStatus(@RoamingNotificationReason int reason) {
+ if (VDBG) Log.v(LOG_TAG, "updateDataRoamingStatus");
+ Phone phone = getPhone(mDefaultDataSubId);
+ if (phone == null) {
+ Log.w(LOG_TAG, "Can't get phone with sub id = " + mDefaultDataSubId);
+ return;
+ }
+
+ ServiceState serviceState = phone.getServiceState();
+ String roamingNumeric = serviceState.getOperatorNumeric();
+ String roamingNumericReason = "RoamingNumeric=" + roamingNumeric;
+ String callingReason = "CallingReason=" + reason;
+ boolean dataIsNowRoaming = serviceState.getDataRoaming();
+ boolean dataAllowed;
+ boolean notAllowedDueToRoamingOff;
+ List<DataDisallowedReason> reasons = phone.getDataNetworkController()
+ .getInternetDataDisallowedReasons();
+ dataAllowed = reasons.isEmpty();
+ notAllowedDueToRoamingOff = (reasons.size() == 1
+ && reasons.contains(DataDisallowedReason.ROAMING_DISABLED));
+ StringBuilder sb = new StringBuilder("updateDataRoamingStatus");
+ sb.append(" dataAllowed=").append(dataAllowed);
+ sb.append(", reasons=").append(reasons);
+ sb.append(", dataIsNowRoaming=").append(dataIsNowRoaming);
+ sb.append(", ").append(roamingNumericReason);
+ sb.append(", ").append(callingReason);
+ mDataRoamingNotifLog.log(sb.toString());
+ if (VDBG) {
+ Log.v(LOG_TAG, sb.toString());
+ }
+
+ // Determine if a given roaming numeric has never been shown.
+ boolean shownInThisNumeric = false;
+ if (reason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED
+ || reason == ROAMING_NOTIFICATION_REASON_SERVICE_STATE_CHANGED) {
+ shownInThisNumeric = mShownNotificationReasons.contains(roamingNumericReason);
+ }
+ // Determine if a notification has never been shown by given calling reason.
+ boolean shownForThisReason = mShownNotificationReasons.contains(callingReason);
+
+ if (!dataAllowed && notAllowedDueToRoamingOff) {
+ if (!shownInThisNumeric && roamingNumeric != null) {
+ mShownNotificationReasons.add(roamingNumericReason);
+ }
+ if (!shownForThisReason
+ && reason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED) {
+ mShownNotificationReasons.add(callingReason);
+ }
+ // No need to show it again if we never cancelled it explicitly.
+ if (getCurrentRoamingNotification() == ROAMING_NOTIFICATION_DISCONNECTED) {
+ return;
+ }
+
+ // If the only reason of no data is data roaming disabled, then we notify the user
+ // so the user can turn on data roaming.
+ if (!shownInThisNumeric && !shownForThisReason) {
+ updateDataRoamingNotification(ROAMING_NOTIFICATION_DISCONNECTED);
+ } else {
+ // Don't show roaming notification if we've already shown for this MccMnc
+ Log.d(LOG_TAG, "Skip roaming disconnected notification since already"
+ + " shownInThisNumeric=" + shownInThisNumeric
+ + " shownForThisReason=" + shownForThisReason);
+ // Dismiss notification if the other notification is shown.
+ if (getCurrentRoamingNotification() != ROAMING_NOTIFICATION_NO_NOTIFICATION) {
+ updateDataRoamingNotification(ROAMING_NOTIFICATION_NO_NOTIFICATION);
+ }
+ }
+ } else if (dataAllowed && dataIsNowRoaming) {
+ if (!shownInThisNumeric && roamingNumeric != null) {
+ mShownNotificationReasons.add(roamingNumericReason);
+ }
+ if (!shownForThisReason
+ && reason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED) {
+ mShownNotificationReasons.add(callingReason);
+ }
+ boolean isShowRoamingNotificationEnabled = getCarrierConfigForSubId(mDefaultDataSubId)
+ .getBoolean(CarrierConfigManager
+ .KEY_SHOW_DATA_CONNECTED_ROAMING_NOTIFICATION_BOOL);
+ // No need to show it again if we never cancelled it explicitly.
+ if (getCurrentRoamingNotification() == ROAMING_NOTIFICATION_CONNECTED) {
+ return;
+ }
+
+ // Inform users that roaming charges may apply.
+ if (!shownInThisNumeric && !shownForThisReason && isShowRoamingNotificationEnabled) {
+ updateDataRoamingNotification(ROAMING_NOTIFICATION_CONNECTED);
+ } else {
+ // Don't show roaming notification if we've already shown for this MccMnc or
+ // disabled from carrier config.
+ Log.d(LOG_TAG, "Skip roaming connected notification since already"
+ + " shownInThisNumeric:" + shownInThisNumeric
+ + " shownForThisReason:" + shownForThisReason
+ + " isShowRoamingNotificationEnabled:" + isShowRoamingNotificationEnabled);
+ // Dismiss notification if the other notification is shown.
+ if (getCurrentRoamingNotification() != ROAMING_NOTIFICATION_NO_NOTIFICATION) {
+ updateDataRoamingNotification(ROAMING_NOTIFICATION_NO_NOTIFICATION);
+ }
+ }
+ } else if (getCurrentRoamingNotification() != ROAMING_NOTIFICATION_NO_NOTIFICATION) {
+ // Otherwise we either 1) we are not roaming or 2) roaming is off but ROAMING_DISABLED
+ // is not the only data disable reason. In this case we dismiss the notification we
+ // showed earlier.
+ updateDataRoamingNotification(ROAMING_NOTIFICATION_NO_NOTIFICATION);
+ }
}
+ private void updateDataRoamingNotification(@RoamingNotification int roamingNotification) {
+ int event;
+ switch (roamingNotification) {
+ case ROAMING_NOTIFICATION_NO_NOTIFICATION:
+ Log.d(LOG_TAG, "Dismiss roaming notification");
+ mDataRoamingNotifLog.log("Hide roaming.");
+ event = EVENT_DATA_ROAMING_OK;
+ break;
+ case ROAMING_NOTIFICATION_CONNECTED:
+ Log.d(LOG_TAG, "Show roaming connected notification");
+ mDataRoamingNotifLog.log("Show roaming on.");
+ event = EVENT_DATA_ROAMING_CONNECTED;
+ break;
+ case ROAMING_NOTIFICATION_DISCONNECTED:
+ Log.d(LOG_TAG, "Show roaming disconnected notification");
+ mDataRoamingNotifLog.log("Show roaming off.");
+ event = EVENT_DATA_ROAMING_DISCONNECTED;
+ break;
+ default:
+ Log.d(LOG_TAG, "Should never reach here.");
+ mDataRoamingNotifLog.log("Should never reach here.");
+ return;
+ }
+ mCurrentRoamingNotification = roamingNotification;
+ mHandler.obtainMessage(event, mDefaultDataSubId, 0).sendToTarget();
+ }
+
+ private @RoamingNotification int getCurrentRoamingNotification() {
+ return mCurrentRoamingNotification;
+ }
+
+ // For reorganize_roaming_notification feature disabled.
/**
* When roaming, if mobile data cannot be established due to data roaming not enabled, we need
* to notify the user so they can enable it through settings. Vise versa if the condition
@@ -918,8 +1131,9 @@
* @param roamingOperatorNumeric The operator numeric for the current roaming. {@code null} if
* the current roaming operator numeric didn't change.
*/
- private void updateDataRoamingStatus(@Nullable String roamingOperatorNumeric) {
- if (VDBG) Log.v(LOG_TAG, "updateDataRoamingStatus");
+ private void updateDataRoamingStatusForFeatureDisabled(
+ @Nullable String roamingOperatorNumeric) {
+ if (VDBG) Log.v(LOG_TAG, "updateDataRoamingStatusForFeatureDisabled");
Phone phone = getPhone(mDefaultDataSubId);
if (phone == null) {
Log.w(LOG_TAG, "Can't get phone with sub id = " + mDefaultDataSubId);
@@ -1086,10 +1300,22 @@
IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
pw.println("------- PhoneGlobals -------");
pw.increaseIndent();
- pw.println("mPrevRoamingNotification=" + mPrevRoamingNotification);
+ pw.println("FeatureFlags:");
+ pw.increaseIndent();
+ pw.println("loadDdsOnCreate=" + mFeatureFlags.loadDdsOnCreate());
+ pw.println("reorganizeRoamingNotification="
+ + mFeatureFlags.reorganizeRoamingNotification());
+ pw.println("dismissNetworkSelectionNotificationOnSimDisable="
+ + mFeatureFlags.dismissNetworkSelectionNotificationOnSimDisable());
+ pw.decreaseIndent();
+ if (mFeatureFlags.reorganizeRoamingNotification()) {
+ pw.println("mCurrentRoamingNotification=" + mCurrentRoamingNotification);
+ } else {
+ pw.println("mPrevRoamingNotification=" + mPrevRoamingNotification);
+ }
pw.println("mDefaultDataSubId=" + mDefaultDataSubId);
- pw.println("mDataRoamingNotifLog:");
pw.println("isSmsCapable=" + TelephonyManager.from(this).isSmsCapable());
+ pw.println("mDataRoamingNotifLog:");
pw.increaseIndent();
mDataRoamingNotifLog.dump(fd, pw, args);
pw.decreaseIndent();
@@ -1127,7 +1353,11 @@
mDomainSelectionService.dump(fd, pw, args);
}
pw.decreaseIndent();
- pw.println("mPrevRoamingOperatorNumerics:" + mPrevRoamingOperatorNumerics);
+ if (mFeatureFlags.reorganizeRoamingNotification()) {
+ pw.println("mShownNotificationReasons=" + mShownNotificationReasons);
+ } else {
+ pw.println("mPrevRoamingOperatorNumerics:" + mPrevRoamingOperatorNumerics);
+ }
pw.println("------- End PhoneGlobals -------");
}
}
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 0107b1c..1937658 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -17,6 +17,7 @@
package com.android.phone;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.permission.flags.Flags.opEnableMobileDataByUser;
import static android.telephony.TelephonyManager.HAL_SERVICE_NETWORK;
import static android.telephony.TelephonyManager.HAL_SERVICE_RADIO;
@@ -146,6 +147,8 @@
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsConfigImplBase;
import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.satellite.INtnSignalStrengthCallback;
+import android.telephony.satellite.ISatelliteCapabilitiesCallback;
import android.telephony.satellite.ISatelliteDatagramCallback;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
import android.telephony.satellite.ISatelliteStateCallback;
@@ -208,6 +211,7 @@
import com.android.internal.telephony.domainselection.DomainSelectionResolver;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.euicc.EuiccConnector;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.ims.ImsResolver;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
@@ -296,8 +300,6 @@
private static final int EVENT_GET_ALLOWED_NETWORK_TYPES_BITMASK_DONE = 22;
private static final int CMD_SEND_ENVELOPE = 25;
private static final int EVENT_SEND_ENVELOPE_DONE = 26;
- private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
- private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
private static final int CMD_EXCHANGE_SIM_IO = 31;
@@ -403,6 +405,7 @@
private static List<String> sThermalMitigationAllowlistedPackages = new ArrayList<>();
private final PhoneGlobals mApp;
+ private final FeatureFlags mFeatureFlags;
private final CallManager mCM;
private final ImsResolver mImsResolver;
@@ -1154,19 +1157,6 @@
handleNullReturnEvent(msg, "setAllowedNetworkTypesForReason");
break;
- case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
- request = (MainThreadRequest)msg.obj;
- onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
- defaultPhone.invokeOemRilRequestRaw((byte[]) request.argument, onCompleted);
- break;
-
- case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
- ar = (AsyncResult)msg.obj;
- request = (MainThreadRequest)ar.userObj;
- request.result = ar;
- notifyRequester(request);
- break;
-
case CMD_SET_VOICEMAIL_NUMBER:
request = (MainThreadRequest) msg.obj;
onCompleted = obtainMessage(EVENT_SET_VOICEMAIL_NUMBER_DONE, request);
@@ -2226,8 +2216,8 @@
onCompleted = obtainMessage(EVENT_PURCHASE_PREMIUM_CAPABILITY_DONE, request);
PurchasePremiumCapabilityArgument arg =
(PurchasePremiumCapabilityArgument) request.argument;
- SlicePurchaseController.getInstance(request.phone).purchasePremiumCapability(
- arg.capability, onCompleted);
+ SlicePurchaseController.getInstance(request.phone, mFeatureFlags)
+ .purchasePremiumCapability(arg.capability, onCompleted);
break;
}
@@ -2440,10 +2430,10 @@
* Initialize the singleton PhoneInterfaceManager instance.
* This is only done once, at startup, from PhoneApp.onCreate().
*/
- /* package */ static PhoneInterfaceManager init(PhoneGlobals app) {
+ /* package */ static PhoneInterfaceManager init(PhoneGlobals app, FeatureFlags featureFlags) {
synchronized (PhoneInterfaceManager.class) {
if (sInstance == null) {
- sInstance = new PhoneInterfaceManager(app);
+ sInstance = new PhoneInterfaceManager(app, featureFlags);
} else {
Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
}
@@ -2452,8 +2442,9 @@
}
/** Private constructor; @see init() */
- private PhoneInterfaceManager(PhoneGlobals app) {
+ private PhoneInterfaceManager(PhoneGlobals app, FeatureFlags featureFlags) {
mApp = app;
+ mFeatureFlags = featureFlags;
mCM = PhoneGlobals.getInstance().mCM;
mImsResolver = ImsResolver.getInstance();
mSatelliteController = SatelliteController.getInstance();
@@ -2745,6 +2736,9 @@
* If PUK is null, unlock SIM card with PIN
*
* If PUK is not null, unlock SIM card with PUK and set PIN code
+ *
+ * Besides, since it is reused in class level, the thread's looper will be stopped to avoid
+ * its thread leak.
*/
synchronized int[] unlockSim(String puk, String pin) {
@@ -2780,6 +2774,8 @@
if (mResult == PhoneConstants.PIN_RESULT_SUCCESS && pin.length() > 0) {
UiccController.getInstance().getPinStorage().storePin(pin, mPhoneId);
}
+ // This instance is no longer reused, so quit its thread's looper.
+ mHandler.getLooper().quitSafely();
return resultArray;
}
@@ -3031,14 +3027,15 @@
+ ",reason=" + reason + ",callingPackage=" + getCurrentPackageName());
final long identity = Binder.clearCallingIdentity();
try {
- final Phone phone = getPhoneFromSubIdOrDefault(subId);
- if (phone != null) {
+ boolean result = false;
+ for (Phone phone : PhoneFactory.getPhones()) {
+ result = true;
phone.setRadioPowerForReason(false, reason);
- return true;
- } else {
- loge("requestRadioPowerOffForReason: phone is null");
- return false;
}
+ if (!result) {
+ loge("requestRadioPowerOffForReason: no phone exists");
+ }
+ return result;
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -3058,14 +3055,15 @@
final long identity = Binder.clearCallingIdentity();
try {
- final Phone phone = getPhoneFromSubIdOrDefault(subId);
- if (phone != null) {
+ boolean result = false;
+ for (Phone phone : PhoneFactory.getPhones()) {
+ result = true;
phone.setRadioPowerForReason(true, reason);
- return true;
- } else {
- loge("clearRadioPowerOffForReason: phone is null");
- return false;
}
+ if (!result) {
+ loge("clearRadioPowerOffForReason: no phone exists");
+ }
+ return result;
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -7518,39 +7516,6 @@
}
@Override
- @Deprecated
- public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
- enforceModifyPermission();
-
- int returnValue = 0;
- try {
- AsyncResult result = (AsyncResult) sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
- if(result.exception == null) {
- if (result.result != null) {
- byte[] responseData = (byte[])(result.result);
- if(responseData.length > oemResp.length) {
- Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
- responseData.length + "bytes. Buffer Size is " +
- oemResp.length + "bytes.");
- }
- System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
- returnValue = responseData.length;
- }
- } else {
- CommandException ex = (CommandException) result.exception;
- returnValue = ex.getCommandError().ordinal();
- if(returnValue > 0) returnValue *= -1;
- }
- } catch (RuntimeException e) {
- Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
- returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
- if(returnValue > 0) returnValue *= -1;
- }
-
- return returnValue;
- }
-
- @Override
public int getRadioAccessFamily(int phoneId, String callingPackage) {
int raf = RadioAccessFamily.RAF_UNKNOWN;
Phone phone = PhoneFactory.getPhone(phoneId);
@@ -8086,7 +8051,7 @@
*/
private List<SubscriptionInfo> getActiveSubscriptionInfoListPrivileged() {
return getSubscriptionManagerService().getActiveSubscriptionInfoList(
- mApp.getOpPackageName(), mApp.getAttributionTag());
+ mApp.getOpPackageName(), mApp.getAttributionTag(), true/*isForAllProfile*/);
}
private ActivityStatsTechSpecificInfo[] mLastModemActivitySpecificInfo = null;
@@ -8865,6 +8830,12 @@
enforceModifyPermission();
}
+ if (reason == TelephonyManager.DATA_ENABLED_REASON_USER && enabled
+ && null != callingPackage && opEnableMobileDataByUser()) {
+ mAppOps.noteOp(AppOpsManager.OPSTR_ENABLE_MOBILE_DATA_BY_USER, Binder.getCallingUid(),
+ callingPackage, null, null);
+ }
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subId);
@@ -9526,10 +9497,6 @@
TelephonyPermissions.enforceShellOnly(
Binder.getCallingUid(), "setCarrierServicePackageOverride");
- // Verify that the callingPackage belongs to the calling UID
- mApp.getSystemService(AppOpsManager.class)
- .checkPackage(Binder.getCallingUid(), callingPackage);
-
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -11586,7 +11553,7 @@
}
final long identity = Binder.clearCallingIdentity();
try {
- return SlicePurchaseController.getInstance(phone)
+ return SlicePurchaseController.getInstance(phone, mFeatureFlags)
.isPremiumCapabilityAvailableForPurchase(capability);
} finally {
Binder.restoreCallingIdentity(identity);
@@ -12276,13 +12243,13 @@
* @param subId The subId of the subscription to register for provision state changed.
* @param callback The callback to handle the satellite provision state changed event.
*
- * @return The {@link SatelliteManager.SatelliteError} result of the operation.
+ * @return The {@link SatelliteManager.SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have the required permission.
*/
@Override
- @SatelliteManager.SatelliteError public int registerForSatelliteProvisionStateChanged(int subId,
- @NonNull ISatelliteProvisionStateCallback callback) {
+ @SatelliteManager.SatelliteResult public int registerForSatelliteProvisionStateChanged(
+ int subId, @NonNull ISatelliteProvisionStateCallback callback) {
enforceSatelliteCommunicationPermission("registerForSatelliteProvisionStateChanged");
return mSatelliteController.registerForSatelliteProvisionStateChanged(subId, callback);
}
@@ -12326,12 +12293,12 @@
* @param subId The subId of the subscription to register for satellite modem state changed.
* @param callback The callback to handle the satellite modem state changed event.
*
- * @return The {@link SatelliteManager.SatelliteError} result of the operation.
+ * @return The {@link SatelliteManager.SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have the required permission.
*/
@Override
- @SatelliteManager.SatelliteError public int registerForSatelliteModemStateChanged(int subId,
+ @SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged(int subId,
@NonNull ISatelliteStateCallback callback) {
enforceSatelliteCommunicationPermission("registerForSatelliteModemStateChanged");
return mSatelliteController.registerForSatelliteModemStateChanged(subId, callback);
@@ -12360,12 +12327,12 @@
* @param subId The subId of the subscription to register for incoming satellite datagrams.
* @param callback The callback to handle incoming datagrams over satellite.
*
- * @return The {@link SatelliteManager.SatelliteError} result of the operation.
+ * @return The {@link SatelliteManager.SatelliteResult} result of the operation.
*
* @throws SecurityException if the caller doesn't have the required permission.
*/
@Override
- @SatelliteManager.SatelliteError public int registerForSatelliteDatagram(int subId,
+ @SatelliteManager.SatelliteResult public int registerForSatelliteDatagram(int subId,
@NonNull ISatelliteDatagramCallback callback) {
enforceSatelliteCommunicationPermission("registerForSatelliteDatagram");
return mSatelliteController.registerForSatelliteDatagram(subId, callback);
@@ -12396,7 +12363,7 @@
* {@link SatelliteDatagramCallback#onSatelliteDatagramReceived(long, SatelliteDatagram, int, Consumer)})}
*
* @param subId The subId of the subscription used for receiving datagrams.
- * @param callback The callback to get {@link SatelliteManager.SatelliteError} of the request.
+ * @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request.
*
* @throws SecurityException if the caller doesn't have required permission.
*/
@@ -12420,7 +12387,7 @@
* Datagram will be passed down to modem without any encoding or encryption.
* @param needFullScreenPointingUI this is used to indicate pointingUI app to open in
* full screen mode.
- * @param callback The callback to get {@link SatelliteManager.SatelliteError} of the request.
+ * @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request.
*
* @throws SecurityException if the caller doesn't have required permission.
*/
@@ -12479,9 +12446,188 @@
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- public void onDeviceAlignedWithSatellite(int subId, @NonNull boolean isAligned) {
+ public void setDeviceAlignedWithSatellite(int subId, @NonNull boolean isAligned) {
enforceSatelliteCommunicationPermission("informDeviceAlignedToSatellite");
- mSatelliteController.onDeviceAlignedWithSatellite(subId, isAligned);
+ mSatelliteController.setDeviceAlignedWithSatellite(subId, isAligned);
+ }
+
+ /**
+ * Add a restriction reason for disallowing carrier supported satellite plmn scan and attach
+ * by modem.
+ *
+ * @param subId The subId of the subscription to request for.
+ * @param reason Reason for disallowing satellite communication for carrier.
+ * @param callback Listener for the {@link SatelliteManager.SatelliteError} result of the
+ * operation.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ */
+ public void addSatelliteAttachRestrictionForCarrier(int subId,
+ @SatelliteManager.SatelliteCommunicationRestrictionReason int reason,
+ @NonNull IIntegerConsumer callback) {
+ enforceSatelliteCommunicationPermission("addSatelliteAttachRestrictionForCarrier");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mSatelliteController.addSatelliteAttachRestrictionForCarrier(subId, reason, callback);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Remove a restriction reason for disallowing carrier supported satellite plmn scan and attach
+ * by modem.
+ *
+ * @param subId The subId of the subscription to request for.
+ * @param reason Reason for disallowing satellite communication.
+ * @param callback Listener for the {@link SatelliteManager.SatelliteError} result of the
+ * operation.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ */
+ public void removeSatelliteAttachRestrictionForCarrier(int subId,
+ @SatelliteManager.SatelliteCommunicationRestrictionReason int reason,
+ @NonNull IIntegerConsumer callback) {
+ enforceSatelliteCommunicationPermission("removeSatelliteAttachRestrictionForCarrier");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mSatelliteController.removeSatelliteAttachRestrictionForCarrier(subId, reason,
+ callback);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Get reasons for disallowing satellite communication, as requested by
+ * {@link #addSatelliteAttachRestrictionForCarrier(int, int, IIntegerConsumer)}.
+ *
+ * @param subId The subId of the subscription to request for.
+ *
+ * @return Integer array of reasons for disallowing satellite communication.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ public @NonNull int[] getSatelliteAttachRestrictionReasonsForCarrier(
+ int subId) {
+ enforceSatelliteCommunicationPermission("getSatelliteAttachRestrictionReasonsForCarrier");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Set<Integer> reasonSet =
+ mSatelliteController.getSatelliteAttachRestrictionReasonsForCarrier(subId);
+ return reasonSet.stream().mapToInt(i->i).toArray();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Request to get the signal strength of the satellite connection.
+ *
+ * @param subId The subId of the subscription to request for.
+ * @param result Result receiver to get the error code of the request and the current signal
+ * strength of the satellite connection.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ */
+ @Override
+ public void requestNtnSignalStrength(int subId, @NonNull ResultReceiver result) {
+ enforceSatelliteCommunicationPermission("requestNtnSignalStrength");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mSatelliteController.requestNtnSignalStrength(subId, result);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Registers for NTN signal strength changed from satellite modem.
+ *
+ * @param subId The subId of the subscription to request for.
+ * @param callback The callback to handle the NTN signal strength changed event.
+ *
+ * @return The {@link SatelliteManager.SatelliteResult} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ @SatelliteManager.SatelliteResult public int registerForNtnSignalStrengthChanged(
+ int subId, @NonNull INtnSignalStrengthCallback callback) {
+ enforceSatelliteCommunicationPermission("registerForNtnSignalStrengthChanged");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return mSatelliteController.registerForNtnSignalStrengthChanged(subId, callback);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Unregisters for NTN signal strength changed from satellite modem.
+ * If callback was not registered before, the request will be ignored.
+ *
+ * @param subId The subId of the subscription to unregister for listening NTN signal strength
+ * changed event.
+ * @param callback The callback that was passed to
+ * {@link #registerForNtnSignalStrengthChanged(int, INtnSignalStrengthCallback)}
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void unregisterForNtnSignalStrengthChanged(
+ int subId, @NonNull INtnSignalStrengthCallback callback) {
+ enforceSatelliteCommunicationPermission("unregisterForNtnSignalStrengthChanged");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mSatelliteController.unregisterForNtnSignalStrengthChanged(subId, callback);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Registers for satellite capabilities change event from the satellite service.
+ *
+ * @param subId The subId of the subscription to request for.
+ * @param callback The callback to handle the satellite capabilities changed event.
+ *
+ * @return The {@link SatelliteManager.SatelliteResult} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ */
+ @Override
+ @SatelliteManager.SatelliteResult public int registerForSatelliteCapabilitiesChanged(
+ int subId, @NonNull ISatelliteCapabilitiesCallback callback) {
+ enforceSatelliteCommunicationPermission("registerForSatelliteCapabilitiesChanged");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return mSatelliteController.registerForSatelliteCapabilitiesChanged(subId, callback);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Unregisters for satellite capabilities change event from the satellite service.
+ * If callback was not registered before, the request will be ignored.
+ *
+ * @param subId The subId of the subscription to unregister for satellite capabilities change.
+ * @param callback The callback that was passed to.
+ * {@link #registerForSatelliteCapabilitiesChanged(int, ISatelliteCapabilitiesCallback)}.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ */
+ @Override
+ public void unregisterForSatelliteCapabilitiesChanged(
+ int subId, @NonNull ISatelliteCapabilitiesCallback callback) {
+ enforceSatelliteCommunicationPermission("unregisterForSatelliteCapabilitiesChanged");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mSatelliteController.unregisterForSatelliteCapabilitiesChanged(subId, callback);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
/**
@@ -12574,6 +12720,56 @@
}
/**
+ * This API can be used in only testing to override connectivity status in monitoring emergency
+ * calls and sending EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer.
+ *
+ * @param handoverType The type of handover from emergency call to satellite messaging. Use one
+ * of the following values to enable the override:
+ * 0 - EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS
+ * 1 - EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911
+ * To disable the override, use -1 for handoverType.
+ * @param delaySeconds The event EVENT_DISPLAY_EMERGENCY_MESSAGE will be sent to Dialer
+ * delaySeconds after the emergency call starts.
+ * @return {@code true} if the handover type is set successfully, {@code false} otherwise.
+ */
+ public boolean setEmergencyCallToSatelliteHandoverType(int handoverType, int delaySeconds) {
+ Log.d(LOG_TAG, "setEmergencyCallToSatelliteHandoverType - " + handoverType);
+ TelephonyPermissions.enforceShellOnly(
+ Binder.getCallingUid(), "setEmergencyCallToSatelliteHandoverType");
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ "setEmergencyCallToSatelliteHandoverType");
+ return mSatelliteController.setEmergencyCallToSatelliteHandoverType(
+ handoverType, delaySeconds);
+ }
+
+ /**
+ * This API can be used by only CTS to override the cached value for the device overlay config
+ * value : config_send_satellite_datagram_to_modem_in_demo_mode, which determines whether
+ * outgoing satellite datagrams should be sent to modem in demo mode.
+ *
+ * @param shouldSendToModemInDemoMode Whether send datagram in demo mode should be sent to
+ * satellite modem or not.
+ *
+ * @return {@code true} if the operation is successful, {@code false} otherwise.
+ */
+ public boolean setShouldSendDatagramToModemInDemoMode(boolean shouldSendToModemInDemoMode) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ Log.d(LOG_TAG, "shouldSendDatagramToModemInDemoMode: oemEnabledSatelliteFlag is "
+ + "disabled");
+ return false;
+ }
+ Log.d(LOG_TAG, "setShouldSendDatagramToModemInDemoMode");
+ TelephonyPermissions.enforceShellOnly(
+ Binder.getCallingUid(), "setShouldSendDatagramToModemInDemoMode");
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ "setShouldSendDatagramToModemInDemoMode");
+ return mSatelliteController.setShouldSendDatagramToModemInDemoMode(
+ shouldSendToModemInDemoMode);
+ }
+
+ /**
* Check whether the caller (or self, if not processing an IPC) can read device identifiers.
*
* <p>This method behaves in one of the following ways:
diff --git a/src/com/android/phone/PhoneUtils.java b/src/com/android/phone/PhoneUtils.java
index 4826d2b..0c8a9c7 100644
--- a/src/com/android/phone/PhoneUtils.java
+++ b/src/com/android/phone/PhoneUtils.java
@@ -703,8 +703,12 @@
}
public static PhoneAccountHandle makePstnPhoneAccountHandle(Phone phone) {
- return makePstnPhoneAccountHandleWithPrefix(phone, "",
- false, phone.getUserHandle());
+ if (phone == null) {
+ return null;
+ } else {
+ return makePstnPhoneAccountHandleWithPrefix(phone, "",
+ false, phone.getUserHandle());
+ }
}
public static PhoneAccountHandle makePstnPhoneAccountHandleWithPrefix(
diff --git a/src/com/android/phone/RcsProvisioningMonitor.java b/src/com/android/phone/RcsProvisioningMonitor.java
index a948d08..87a2869 100644
--- a/src/com/android/phone/RcsProvisioningMonitor.java
+++ b/src/com/android/phone/RcsProvisioningMonitor.java
@@ -524,7 +524,7 @@
filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
mPhone.registerReceiver(mReceiver, filter);
mTelephonyRegistryManager.addOnSubscriptionsChangedListener(
- mSubChangedListener, mSubChangedListener.getHandlerExecutor());
+ mSubChangedListener, mHandler::post);
mDmaChangedListener.register();
//initialize configs for all active sub
onSubChanged();
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 498e1ea..5986a7c 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -189,6 +189,10 @@
"set-satellite-pointing-ui-class-name";
private static final String SET_SATELLITE_DEVICE_ALIGNED_TIMEOUT_DURATION =
"set-satellite-device-aligned-timeout-duration";
+ private static final String SET_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE =
+ "set-emergency-call-to-satellite-handover-type";
+ private static final String SET_SHOULD_SEND_DATAGRAM_TO_MODEM_IN_DEMO_MODE =
+ "set-should-send-datagram-to-modem-in-demo-mode";
private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
+ "'*', '#' or '+') needs to be specified after -a in the command ";
@@ -380,6 +384,10 @@
return handleSetSatellitePointingUiClassNameCommand();
case SET_SATELLITE_DEVICE_ALIGNED_TIMEOUT_DURATION:
return handleSettSatelliteDeviceAlignedTimeoutDuration();
+ case SET_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE:
+ return handleSetEmergencyCallToSatelliteHandoverType();
+ case SET_SHOULD_SEND_DATAGRAM_TO_MODEM_IN_DEMO_MODE:
+ return handleSetShouldSendDatagramToModemInDemoMode();
default: {
return handleDefaultCommands(cmd);
}
@@ -779,6 +787,14 @@
pw.println(" launch. If no option is specified, it will launch the default.");
pw.println(" -c: the satellite pointing UI app class name that Telephony will");
pw.println(" launch.");
+ pw.println(" set-emergency-call-to-satellite-handover-type [-t HANDOVER_TYPE ");
+ pw.println(" -d DELAY_SECONDS] Override connectivity status in monitoring emergency ");
+ pw.println(" call and sending EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer.");
+ pw.println(" Options are:");
+ pw.println(" -t: the emergency call to satellite handover type.");
+ pw.println(" If no option is specified, override is disabled.");
+ pw.println(" -d: the delay in seconds in sending EVENT_DISPLAY_EMERGENCY_MESSAGE.");
+ pw.println(" If no option is specified, there is no delay in sending the event.");
}
private void onHelpImei() {
@@ -3217,6 +3233,55 @@
return 0;
}
+ private int handleSetEmergencyCallToSatelliteHandoverType() {
+ PrintWriter errPw = getErrPrintWriter();
+ int handoverType = -1;
+ int delaySeconds = 0;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-t": {
+ try {
+ handoverType = Integer.parseInt(getNextArgRequired());
+ } catch (NumberFormatException e) {
+ errPw.println("SetEmergencyCallToSatelliteHandoverType: require an integer"
+ + " for handoverType");
+ return -1;
+ }
+ break;
+ }
+ case "-d": {
+ try {
+ delaySeconds = Integer.parseInt(getNextArgRequired());
+ } catch (NumberFormatException e) {
+ errPw.println("SetEmergencyCallToSatelliteHandoverType: require an integer"
+ + " for delaySeconds");
+ return -1;
+ }
+ break;
+ }
+ }
+ }
+ Log.d(LOG_TAG, "handleSetEmergencyCallToSatelliteHandoverType: handoverType="
+ + handoverType + ", delaySeconds=" + delaySeconds);
+
+ try {
+ boolean result =
+ mInterface.setEmergencyCallToSatelliteHandoverType(handoverType, delaySeconds);
+ if (VDBG) {
+ Log.v(LOG_TAG, "setEmergencyCallToSatelliteHandoverType result =" + result);
+ }
+ getOutPrintWriter().println(result);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "setEmergencyCallToSatelliteHandoverType: " + handoverType
+ + ", error = " + e.getMessage());
+ errPw.println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
+
private int handleSetSatelliteListeningTimeoutDuration() {
PrintWriter errPw = getErrPrintWriter();
long timeoutMillis = 0;
@@ -3281,6 +3346,54 @@
return 0;
}
+ private int handleSetShouldSendDatagramToModemInDemoMode() {
+ PrintWriter errPw = getErrPrintWriter();
+ String opt;
+ boolean shouldSendToDemoMode;
+
+ if ((opt = getNextArg()) == null) {
+ errPw.println(
+ "adb shell cmd phone set-should-send-datagram-to-modem-in-demo-mode :"
+ + " Invalid Argument");
+ return -1;
+ } else {
+ switch (opt) {
+ case "true": {
+ shouldSendToDemoMode = true;
+ break;
+ }
+ case "false": {
+ shouldSendToDemoMode = false;
+ break;
+ }
+ default:
+ errPw.println(
+ "adb shell cmd phone set-should-send-datagram-to-modem-in-demo-mode :"
+ + " Invalid Argument");
+ return -1;
+ }
+ }
+
+ Log.d(LOG_TAG,
+ "handleSetShouldSendDatagramToModemInDemoMode(" + shouldSendToDemoMode + ")");
+
+ try {
+ boolean result = mInterface.setShouldSendDatagramToModemInDemoMode(
+ shouldSendToDemoMode);
+ if (VDBG) {
+ Log.v(LOG_TAG, "handleSetShouldSendDatagramToModemInDemoMode returns: "
+ + result);
+ }
+ getOutPrintWriter().println(false);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "setShouldSendDatagramToModemInDemoMode(" + shouldSendToDemoMode
+ + "), error = " + e.getMessage());
+ errPw.println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
+
private int handleCarrierRestrictionStatusCommand() {
try {
String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
@@ -3377,7 +3490,7 @@
// clear-carrier-service-package-override
private int clearCarrierServicePackageOverride() {
PrintWriter errPw = getErrPrintWriter();
- int subId = getDefaultSlot();
+ int subId = SubscriptionManager.getDefaultSubscriptionId();
String opt;
while ((opt = getNextOption()) != null) {
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index 124badf..8dfb787 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -44,6 +44,7 @@
import android.os.Message;
import android.os.PersistableBundle;
import android.os.SystemProperties;
+import android.os.UserManager;
import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
import android.telephony.CellIdentityCdma;
@@ -207,6 +208,7 @@
private static final int EVENT_QUERY_SMSC_DONE = 1005;
private static final int EVENT_UPDATE_SMSC_DONE = 1006;
private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 1007;
+ private static final int EVENT_UPDATE_NR_STATS = 1008;
private static final int MENU_ITEM_VIEW_ADN = 1;
private static final int MENU_ITEM_VIEW_FDN = 2;
@@ -379,7 +381,14 @@
updateNetworkType();
updateRawRegistrationState(serviceState);
updateImsProvisionedState();
- updateNrStats(serviceState);
+
+ // Since update NR stats includes a ril message to get slicing information, it runs
+ // as blocking during the timeout period of 1 second. if ServiceStateChanged event
+ // fires consecutively, RadioInfo can run for more than 10 seconds. This can cause ANR.
+ // Therefore, send event only when there is no same event being processed.
+ if (!mHandler.hasMessages(EVENT_UPDATE_NR_STATS)) {
+ mHandler.obtainMessage(EVENT_UPDATE_NR_STATS).sendToTarget();
+ }
}
@Override
@@ -465,6 +474,10 @@
}
updatePhysicalChannelConfiguration((List<PhysicalChannelConfig>) ar.result);
break;
+ case EVENT_UPDATE_NR_STATS:
+ log("got EVENT_UPDATE_NR_STATS");
+ updateNrStats();
+ break;
default:
super.handleMessage(msg);
break;
@@ -482,6 +495,15 @@
return;
}
+ UserManager userManager =
+ (UserManager) getApplicationContext().getSystemService(Context.USER_SERVICE);
+ if (userManager != null
+ && userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
+ Log.w(TAG, "User is restricted from configuring mobile networks.");
+ finish();
+ return;
+ }
+
setContentView(R.layout.radio_info);
log("Started onCreate");
@@ -690,7 +712,7 @@
updateProperties();
updateDnsCheckState();
updateNetworkType();
- updateNrStats(null);
+ updateNrStats();
updateCellInfo(mCellInfoResult);
updateSubscriptionIds();
@@ -835,7 +857,9 @@
@Override
protected void onDestroy() {
super.onDestroy();
- mQueuedWork.shutdown();
+ if (mQueuedWork != null) {
+ mQueuedWork.shutdown();
+ }
}
// returns array of string labels for each phone index. The array index is equal to the phone
@@ -1235,15 +1259,12 @@
AccessNetworkConstants.TRANSPORT_TYPE_WLAN));
}
- private void updateNrStats(ServiceState serviceState) {
+ private void updateNrStats() {
if ((mTelephonyManager.getSupportedRadioAccessFamily()
& TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
return;
}
- ServiceState ss = serviceState;
- if (ss == null && mPhone != null) {
- ss = mPhone.getServiceState();
- }
+ ServiceState ss = (mPhone == null) ? null : mPhone.getServiceState();
if (ss != null) {
NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(
NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
@@ -1257,6 +1278,13 @@
}
mNrState.setText(NetworkRegistrationInfo.nrStateToString(ss.getNrState()));
mNrFrequency.setText(ServiceState.frequencyRangeToString(ss.getNrFrequencyRange()));
+ } else {
+ Log.e(TAG, "Clear Nr stats by null service state");
+ mEndcAvailable.setText("");
+ mDcnrRestricted.setText("");
+ mNrAvailable.setText("");
+ mNrState.setText("");
+ mNrFrequency.setText("");
}
CompletableFuture<NetworkSlicingConfig> resultFuture = new CompletableFuture<>();
diff --git a/src/com/android/phone/settings/fdn/FdnSetting.java b/src/com/android/phone/settings/fdn/FdnSetting.java
index 8f46c85..e347dec 100644
--- a/src/com/android/phone/settings/fdn/FdnSetting.java
+++ b/src/com/android/phone/settings/fdn/FdnSetting.java
@@ -19,10 +19,12 @@
import android.app.ActionBar;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
+import android.content.Context;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.UserManager;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.util.Log;
diff --git a/src/com/android/phone/slice/PremiumNetworkEntitlementApi.java b/src/com/android/phone/slice/PremiumNetworkEntitlementApi.java
index d5ef816..3bfe1a4 100644
--- a/src/com/android/phone/slice/PremiumNetworkEntitlementApi.java
+++ b/src/com/android/phone/slice/PremiumNetworkEntitlementApi.java
@@ -46,6 +46,7 @@
private static final String PROVISION_STATUS_KEY = "ProvStatus";
private static final String SERVICE_FLOW_URL_KEY = "ServiceFlow_URL";
private static final String SERVICE_FLOW_USERDATA_KEY = "ServiceFlow_UserData";
+ private static final String SERVICE_FLOW_CONTENTS_TYPE_KEY = "ServiceFlow_ContentsType";
private static final String DEFAULT_EAP_AKA_RESPONSE = "Default EAP AKA response";
/**
* UUID to report an anomaly if an unexpected error is received during entitlement check.
@@ -120,13 +121,11 @@
}
try {
JSONObject jsonAuthResponse = new JSONObject(response);
- String entitlementStatus = null;
- String provisionStatus = null;
if (jsonAuthResponse.has(ServiceEntitlement.APP_DATA_PLAN_BOOST)) {
JSONObject jsonToken = jsonAuthResponse.getJSONObject(
ServiceEntitlement.APP_DATA_PLAN_BOOST);
if (jsonToken.has(ENTITLEMENT_STATUS_KEY)) {
- entitlementStatus = jsonToken.getString(ENTITLEMENT_STATUS_KEY);
+ String entitlementStatus = jsonToken.getString(ENTITLEMENT_STATUS_KEY);
if (entitlementStatus == null) {
return null;
}
@@ -134,7 +133,7 @@
Integer.parseInt(entitlementStatus);
}
if (jsonToken.has(PROVISION_STATUS_KEY)) {
- provisionStatus = jsonToken.getString(PROVISION_STATUS_KEY);
+ String provisionStatus = jsonToken.getString(PROVISION_STATUS_KEY);
if (provisionStatus != null) {
premiumNetworkEntitlementResponse.mProvisionStatus =
Integer.parseInt(provisionStatus);
@@ -148,6 +147,10 @@
premiumNetworkEntitlementResponse.mServiceFlowUserData =
jsonToken.getString(SERVICE_FLOW_USERDATA_KEY);
}
+ if (jsonToken.has(SERVICE_FLOW_CONTENTS_TYPE_KEY)) {
+ premiumNetworkEntitlementResponse.mServiceFlowContentsType =
+ jsonToken.getString(SERVICE_FLOW_CONTENTS_TYPE_KEY);
+ }
} else {
Log.e(TAG, "queryEntitlementStatus failed with no app");
}
diff --git a/src/com/android/phone/slice/PremiumNetworkEntitlementResponse.java b/src/com/android/phone/slice/PremiumNetworkEntitlementResponse.java
index ba44581..9126244 100644
--- a/src/com/android/phone/slice/PremiumNetworkEntitlementResponse.java
+++ b/src/com/android/phone/slice/PremiumNetworkEntitlementResponse.java
@@ -25,19 +25,19 @@
*
* The relationship between entitlement status (left column) and provision status (top row)
* is defined in the table below:
- * +--------------+-----------------+-------------------+-------------------+---------------+
- * | | Not Provisioned | Provisioned | Not Available | In Progress |
- * +--------------+-----------------+-------------------+-------------------+---------------+
- * | Disabled | Check failed | Check failed | Check failed | Check failed |
- * +--------------+-----------------+-------------------+-------------------+---------------+
- * | Enabled | Carrier error | Display webview | Display webview | Carrier error |
- * +--------------+-----------------+-------------------+-------------------+---------------+
- * | Incompatible | Check failed | Check failed | Check failed | Check failed |
- * +--------------+-----------------+-------------------+-------------------+---------------+
- * | Provisioning | Carrier error | Carrier error | In Progress | In Progress |
- * +--------------+-----------------+-------------------+-------------------+---------------+
- * | Included | Carrier error | Already purchased | Already purchased | Carrier error |
- * +--------------+-----------------+-------------------+-------------------+---------------+
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
+ * | | Not Provisioned | Provisioned | Not Available | In Progress |
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
+ * | Disabled | Check failed | Check failed | Check failed | Check failed |
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
+ * | Enabled | Display webview | Already purchased | Already purchased | In progress |
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
+ * | Incompatible | Check failed | Check failed | Check failed | Check failed |
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
+ * | Provisioning | Carrier error | Carrier error | In progress | In progress |
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
+ * | Included | Carrier error | Already purchased | Already purchased | Carrier error |
+ * +--------------+-----------------+-------------------+-------------------+-----------------+
*/
public class PremiumNetworkEntitlementResponse {
public static final int PREMIUM_NETWORK_ENTITLEMENT_STATUS_DISABLED = 0;
@@ -72,13 +72,19 @@
@PremiumNetworkProvisionStatus public int mProvisionStatus;
@NonNull public String mServiceFlowURL;
@NonNull public String mServiceFlowUserData;
+ @NonNull public String mServiceFlowContentsType;
/**
- * @return {@code true} if the premium network is provisioned and {@code false} otherwise.
+ * @return {@code true} if the premium network is already purchased and {@code false} otherwise.
*/
- public boolean isProvisioned() {
- return !isInvalidResponse()
- && mEntitlementStatus == PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCLUDED;
+ public boolean isAlreadyPurchased() {
+ switch (mEntitlementStatus) {
+ case PREMIUM_NETWORK_ENTITLEMENT_STATUS_ENABLED:
+ case PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCLUDED:
+ return mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_PROVISIONED
+ || mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_NOT_AVAILABLE;
+ }
+ return false;
}
/**
@@ -86,8 +92,14 @@
* {@code false} otherwise.
*/
public boolean isProvisioningInProgress() {
- return !isInvalidResponse()
- && mEntitlementStatus == PREMIUM_NETWORK_ENTITLEMENT_STATUS_PROVISIONING;
+ switch (mEntitlementStatus) {
+ case PREMIUM_NETWORK_ENTITLEMENT_STATUS_ENABLED:
+ return mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_IN_PROGRESS;
+ case PREMIUM_NETWORK_ENTITLEMENT_STATUS_PROVISIONING:
+ return mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_IN_PROGRESS
+ || mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_NOT_AVAILABLE;
+ }
+ return false;
}
/**
@@ -108,7 +120,6 @@
*/
public boolean isInvalidResponse() {
switch (mEntitlementStatus) {
- case PREMIUM_NETWORK_ENTITLEMENT_STATUS_ENABLED:
case PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCLUDED:
return mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_NOT_PROVISIONED
|| mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_IN_PROGRESS;
@@ -123,6 +134,7 @@
@NonNull public String toString() {
return "PremiumNetworkEntitlementResponse{mEntitlementStatus=" + mEntitlementStatus
+ ", mProvisionStatus=" + mProvisionStatus + ", mServiceFlowURL=" + mServiceFlowURL
- + ", mServiceFlowUserData" + mServiceFlowUserData + "}";
+ + ", mServiceFlowUserData=" + mServiceFlowUserData + ", mServiceFlowContentsType="
+ + mServiceFlowContentsType + "}";
}
}
diff --git a/src/com/android/phone/slice/SlicePurchaseController.java b/src/com/android/phone/slice/SlicePurchaseController.java
index b1abe56..9a42e16 100644
--- a/src/com/android/phone/slice/SlicePurchaseController.java
+++ b/src/com/android/phone/slice/SlicePurchaseController.java
@@ -48,6 +48,9 @@
import android.telephony.TelephonyManager;
import android.telephony.data.NetworkSliceInfo;
import android.telephony.data.NetworkSlicingConfig;
+import android.telephony.data.RouteSelectionDescriptor;
+import android.telephony.data.TrafficDescriptor;
+import android.telephony.data.UrspRule;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.URLUtil;
@@ -55,6 +58,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.FeatureFlags;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -92,12 +96,15 @@
public static final int FAILURE_CODE_UNKNOWN = 0;
/** Performance boost purchase failed because the carrier URL is unavailable. */
public static final int FAILURE_CODE_CARRIER_URL_UNAVAILABLE = 1;
- /** Performance boost purchase failed because the server is unreachable. */
- public static final int FAILURE_CODE_SERVER_UNREACHABLE = 2;
/** Performance boost purchase failed because user authentication failed. */
- public static final int FAILURE_CODE_AUTHENTICATION_FAILED = 3;
+ public static final int FAILURE_CODE_AUTHENTICATION_FAILED = 2;
/** Performance boost purchase failed because the payment failed. */
- public static final int FAILURE_CODE_PAYMENT_FAILED = 4;
+ public static final int FAILURE_CODE_PAYMENT_FAILED = 3;
+ /**
+ * Performance boost purchase failed because the content type was specified but
+ * user data does not exist.
+ */
+ public static final int FAILURE_CODE_NO_USER_DATA = 4;
/**
* Failure codes that the carrier website can return when a premium capability purchase fails.
@@ -106,9 +113,9 @@
@IntDef(prefix = { "FAILURE_CODE_" }, value = {
FAILURE_CODE_UNKNOWN,
FAILURE_CODE_CARRIER_URL_UNAVAILABLE,
- FAILURE_CODE_SERVER_UNREACHABLE,
FAILURE_CODE_AUTHENTICATION_FAILED,
- FAILURE_CODE_PAYMENT_FAILED})
+ FAILURE_CODE_PAYMENT_FAILED,
+ FAILURE_CODE_NO_USER_DATA})
public @interface FailureCode {}
/** Value for an invalid premium capability. */
@@ -177,6 +184,12 @@
private static final String ACTION_SLICE_PURCHASE_APP_RESPONSE_NOT_DEFAULT_DATA_SUBSCRIPTION =
"com.android.phone.slice.action."
+ "SLICE_PURCHASE_APP_RESPONSE_NOT_DEFAULT_DATA_SUBSCRIPTION";
+ /**
+ * Action indicating the performance boost notification was not shown because the user
+ * disabled notifications for the application or channel.
+ */
+ private static final String ACTION_SLICE_PURCHASE_APP_RESPONSE_NOTIFICATIONS_DISABLED =
+ "com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_NOTIFICATIONS_DISABLED";
/** Action indicating the purchase request was successful. */
private static final String ACTION_SLICE_PURCHASE_APP_RESPONSE_SUCCESS =
"com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_SUCCESS";
@@ -209,6 +222,8 @@
public static final String EXTRA_CARRIER = "com.android.phone.slice.extra.CARRIER";
/** Extra for the user data received from the entitlement service to send to the webapp. */
public static final String EXTRA_USER_DATA = "com.android.phone.slice.extra.USER_DATA";
+ /** Extra for the contents type received from the entitlement service to send to the webapp. */
+ public static final String EXTRA_CONTENTS_TYPE = "com.android.phone.slice.extra.CONTENTS_TYPE";
/**
* Extra for the canceled PendingIntent that the slice purchase application can send as a
* response if the performance boost notification or WebView was canceled by the user.
@@ -242,6 +257,14 @@
public static final String EXTRA_INTENT_NOT_DEFAULT_DATA_SUBSCRIPTION =
"com.android.phone.slice.extra.INTENT_NOT_DEFAULT_DATA_SUBSCRIPTION";
/**
+ * Extra for the notifications disabled PendingIntent that the slice purchase application can
+ * send as a response if the premium capability purchase request failed because the user
+ * disabled notifications for the application or channel.
+ * Sends {@link #ACTION_SLICE_PURCHASE_APP_RESPONSE_NOTIFICATIONS_DISABLED}.
+ */
+ public static final String EXTRA_INTENT_NOTIFICATIONS_DISABLED =
+ "com.android.phone.slice.extra.INTENT_NOTIFICATIONS_DISABLED";
+ /**
* Extra for the success PendingIntent that the slice purchase application can send as a
* response if the premium capability purchase request was successful.
* Sends {@link #ACTION_SLICE_PURCHASE_APP_RESPONSE_SUCCESS}.
@@ -287,6 +310,8 @@
/** The Phone instance used to create the SlicePurchaseController. */
@NonNull private final Phone mPhone;
+ /** Feature flags to control behavior and errors. */
+ @NonNull private final FeatureFlags mFeatureFlags;
/** The set of capabilities that are pending network setup. */
@NonNull private final Set<Integer> mPendingSetupCapabilities = new HashSet<>();
/** The set of throttled capabilities. */
@@ -320,7 +345,7 @@
/**
* Create a SlicePurchaseControllerBroadcastReceiver for the given capability
*
- * @param capability The requested capability to listen to response for.
+ * @param capability The requested premium capability to listen to response for.
*/
SlicePurchaseControllerBroadcastReceiver(
@TelephonyManager.PremiumCapability int capability) {
@@ -391,6 +416,17 @@
false);
break;
}
+ case ACTION_SLICE_PURCHASE_APP_RESPONSE_NOTIFICATIONS_DISABLED: {
+ logd("Slice purchase application unable to show notification for capability: "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " because the user has disabled notifications.");
+ int error = mFeatureFlags.slicingAdditionalErrorCodes()
+ ? TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED
+ : TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED;
+ SlicePurchaseController.getInstance(phoneId)
+ .handlePurchaseResult(capability, error, true);
+ break;
+ }
case ACTION_SLICE_PURCHASE_APP_RESPONSE_SUCCESS: {
long duration = intent.getLongExtra(EXTRA_PURCHASE_DURATION, 0);
SlicePurchaseController.getInstance(phoneId).onCarrierSuccess(
@@ -417,14 +453,16 @@
* @param phone The Phone to get the SlicePurchaseController for.
* @return The static SlicePurchaseController instance.
*/
- @NonNull public static synchronized SlicePurchaseController getInstance(@NonNull Phone phone) {
+ @NonNull public static synchronized SlicePurchaseController getInstance(@NonNull Phone phone,
+ @NonNull FeatureFlags featureFlags) {
// TODO: Add listeners for multi sim setting changed (maybe carrier config changed too)
// that dismiss notifications and update SlicePurchaseController instance
int phoneId = phone.getPhoneId();
if (sInstances.get(phoneId) == null) {
HandlerThread handlerThread = new HandlerThread("SlicePurchaseController");
handlerThread.start();
- sInstances.put(phoneId, new SlicePurchaseController(phone, handlerThread.getLooper()));
+ sInstances.put(phoneId,
+ new SlicePurchaseController(phone, featureFlags, handlerThread.getLooper()));
}
return sInstances.get(phoneId);
}
@@ -444,18 +482,21 @@
* Create a SlicePurchaseController for the given phone on the given looper.
*
* @param phone The Phone to create the SlicePurchaseController for.
+ * @param featureFlags The FeatureFlags that are supported.
* @param looper The Looper to run the SlicePurchaseController on.
*/
@VisibleForTesting
- public SlicePurchaseController(@NonNull Phone phone, @NonNull Looper looper) {
+ public SlicePurchaseController(@NonNull Phone phone, @NonNull FeatureFlags featureFlags,
+ @NonNull Looper looper) {
super(looper);
mPhone = phone;
+ mFeatureFlags = featureFlags;
// TODO: Create a cached value for slicing config in DataIndication and initialize here
mPhone.mCi.registerForSlicingConfigChanged(this, EVENT_SLICING_CONFIG_CHANGED, null);
mIsSlicingUpsellEnabled = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_TELEPHONY, KEY_ENABLE_SLICING_UPSELL, false);
DeviceConfig.addOnPropertiesChangedListener(
- DeviceConfig.NAMESPACE_TELEPHONY, this::post,
+ DeviceConfig.NAMESPACE_TELEPHONY, Runnable::run,
properties -> {
if (TextUtils.equals(DeviceConfig.NAMESPACE_TELEPHONY,
properties.getNamespace())) {
@@ -475,6 +516,17 @@
mLocalDate = localDate;
}
+ /**
+ * Set the NetworkSlicingConfig to use for determining whether the premium capability was
+ * successfully set up on the carrier network.
+ *
+ * @param slicingConfig The LocalDate instance to use.
+ */
+ @VisibleForTesting
+ public void setSlicingConfig(@NonNull NetworkSlicingConfig slicingConfig) {
+ mSlicingConfig = slicingConfig;
+ }
+
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what) {
@@ -488,7 +540,8 @@
case EVENT_SLICING_CONFIG_CHANGED: {
AsyncResult ar = (AsyncResult) msg.obj;
NetworkSlicingConfig config = (NetworkSlicingConfig) ar.result;
- logd("EVENT_SLICING_CONFIG_CHANGED: from " + mSlicingConfig + " to " + config);
+ logd("EVENT_SLICING_CONFIG_CHANGED: previous= " + mSlicingConfig);
+ logd("EVENT_SLICING_CONFIG_CHANGED: current= " + config);
mSlicingConfig = config;
onSlicingConfigChanged();
break;
@@ -690,6 +743,17 @@
private void onStartSlicePurchaseApplication(
@TelephonyManager.PremiumCapability int capability) {
+ updateNotificationCounts();
+ if (mMonthlyCount >= getCarrierConfigs().getInt(
+ CarrierConfigManager.KEY_PREMIUM_CAPABILITY_MAXIMUM_MONTHLY_NOTIFICATION_COUNT_INT)
+ || mDailyCount >= getCarrierConfigs().getInt(
+ CarrierConfigManager.KEY_PREMIUM_CAPABILITY_MAXIMUM_DAILY_NOTIFICATION_COUNT_INT)) {
+ logd("Reached maximum number of performance boost notifications.");
+ handlePurchaseResult(capability,
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, false);
+ return;
+ }
+
final PremiumNetworkEntitlementApi premiumNetworkEntitlementApi =
getPremiumNetworkEntitlementApi();
PremiumNetworkEntitlementResponse premiumNetworkEntitlementResponse =
@@ -711,8 +775,8 @@
return;
}
- if (premiumNetworkEntitlementResponse.isProvisioned()) {
- logd("Entitlement Check: Already provisioned.");
+ if (premiumNetworkEntitlementResponse.isAlreadyPurchased()) {
+ logd("Entitlement Check: Already purchased/provisioned.");
handlePurchaseResult(capability,
PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED, true);
return;
@@ -725,7 +789,6 @@
return;
}
- String userData = premiumNetworkEntitlementResponse.mServiceFlowUserData;
String purchaseUrl = getPurchaseUrl(premiumNetworkEntitlementResponse);
String carrier = getSimOperator();
if (TextUtils.isEmpty(purchaseUrl) || TextUtils.isEmpty(carrier)) {
@@ -734,17 +797,6 @@
return;
}
- updateNotificationCounts();
- if (mMonthlyCount >= getCarrierConfigs().getInt(
- CarrierConfigManager.KEY_PREMIUM_CAPABILITY_MAXIMUM_MONTHLY_NOTIFICATION_COUNT_INT)
- || mDailyCount >= getCarrierConfigs().getInt(
- CarrierConfigManager.KEY_PREMIUM_CAPABILITY_MAXIMUM_DAILY_NOTIFICATION_COUNT_INT)) {
- logd("Reached maximum number of performance boost notifications.");
- handlePurchaseResult(capability,
- TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, false);
- return;
- }
-
// Start timeout for purchase completion.
long timeout = getCarrierConfigs().getLong(CarrierConfigManager
.KEY_PREMIUM_CAPABILITY_NOTIFICATION_DISPLAY_TIMEOUT_MILLIS_LONG);
@@ -761,9 +813,9 @@
intent.putExtra(EXTRA_PREMIUM_CAPABILITY, capability);
intent.putExtra(EXTRA_PURCHASE_URL, purchaseUrl);
intent.putExtra(EXTRA_CARRIER, carrier);
- if (!TextUtils.isEmpty(userData)) {
- intent.putExtra(EXTRA_USER_DATA, userData);
- }
+ intent.putExtra(EXTRA_USER_DATA, premiumNetworkEntitlementResponse.mServiceFlowUserData);
+ intent.putExtra(EXTRA_CONTENTS_TYPE,
+ premiumNetworkEntitlementResponse.mServiceFlowContentsType);
intent.putExtra(EXTRA_INTENT_CANCELED, createPendingIntent(
ACTION_SLICE_PURCHASE_APP_RESPONSE_CANCELED, capability, false));
intent.putExtra(EXTRA_INTENT_CARRIER_ERROR, createPendingIntent(
@@ -773,6 +825,8 @@
intent.putExtra(EXTRA_INTENT_NOT_DEFAULT_DATA_SUBSCRIPTION, createPendingIntent(
ACTION_SLICE_PURCHASE_APP_RESPONSE_NOT_DEFAULT_DATA_SUBSCRIPTION, capability,
false));
+ intent.putExtra(EXTRA_INTENT_NOTIFICATIONS_DISABLED, createPendingIntent(
+ ACTION_SLICE_PURCHASE_APP_RESPONSE_NOTIFICATIONS_DISABLED, capability, false));
intent.putExtra(EXTRA_INTENT_SUCCESS, createPendingIntent(
ACTION_SLICE_PURCHASE_APP_RESPONSE_SUCCESS, capability, true));
intent.putExtra(EXTRA_INTENT_NOTIFICATION_SHOWN, createPendingIntent(
@@ -788,6 +842,7 @@
filter.addAction(ACTION_SLICE_PURCHASE_APP_RESPONSE_CARRIER_ERROR);
filter.addAction(ACTION_SLICE_PURCHASE_APP_RESPONSE_REQUEST_FAILED);
filter.addAction(ACTION_SLICE_PURCHASE_APP_RESPONSE_NOT_DEFAULT_DATA_SUBSCRIPTION);
+ filter.addAction(ACTION_SLICE_PURCHASE_APP_RESPONSE_NOTIFICATIONS_DISABLED);
filter.addAction(ACTION_SLICE_PURCHASE_APP_RESPONSE_SUCCESS);
filter.addAction(ACTION_SLICE_PURCHASE_APP_RESPONSE_NOTIFICATION_SHOWN);
mPhone.getContext().registerReceiver(
@@ -977,7 +1032,8 @@
private long getThrottleDuration(@TelephonyManager.PurchasePremiumCapabilityResult int result) {
if (result == TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED
- || result == TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT) {
+ || result == TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT
+ || result == TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED) {
return getCarrierConfigs().getLong(CarrierConfigManager
.KEY_PREMIUM_CAPABILITY_NOTIFICATION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG);
}
@@ -1037,26 +1093,71 @@
return mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId();
}
- private boolean isSlicingConfigActive(@TelephonyManager.PremiumCapability int capability) {
+ /**
+ * Check whether the current network slicing configuration indicates that the given premium
+ * capability is active and set up on the carrier network.
+ * @param capability The premium capability to check for.
+ * @return {@code true} if the slicing config indicates the capability is active and
+ * {@code false} otherwise.
+ */
+ @VisibleForTesting
+ public boolean isSlicingConfigActive(@TelephonyManager.PremiumCapability int capability) {
if (mSlicingConfig == null) {
return false;
}
- int capabilityServiceType = getSliceServiceType(capability);
- for (NetworkSliceInfo sliceInfo : mSlicingConfig.getSliceInfo()) {
- if (sliceInfo.getSliceServiceType() == capabilityServiceType
- && sliceInfo.getStatus() == NetworkSliceInfo.SLICE_STATUS_ALLOWED) {
- return true;
+ for (UrspRule urspRule : mSlicingConfig.getUrspRules()) {
+ for (TrafficDescriptor trafficDescriptor : urspRule.getTrafficDescriptors()) {
+ TrafficDescriptor.OsAppId osAppId =
+ new TrafficDescriptor.OsAppId(trafficDescriptor.getOsAppId());
+ if (osAppId.getAppId().equals(getAppId(capability))) {
+ for (RouteSelectionDescriptor rsd : urspRule.getRouteSelectionDescriptor()) {
+ for (NetworkSliceInfo sliceInfo : rsd.getSliceInfo()) {
+ if (sliceInfo.getStatus() == NetworkSliceInfo.SLICE_STATUS_ALLOWED
+ && getSliceServiceTypes(capability).contains(
+ sliceInfo.getSliceServiceType())) {
+ return true;
+ }
+ }
+ }
+ }
}
}
return false;
}
- @NetworkSliceInfo.SliceServiceType private int getSliceServiceType(
- @TelephonyManager.PremiumCapability int capability) {
+ /**
+ * Get the application ID associated with the given premium capability.
+ * The app ID is a field in {@link TrafficDescriptor} that helps match URSP rules to determine
+ * whether the premium capability was successfully set up on the carrier network.
+ * @param capability The premium capability to get the app ID for.
+ * @return The application ID associated with the premium capability.
+ */
+ @VisibleForTesting
+ @NonNull public static String getAppId(@TelephonyManager.PremiumCapability int capability) {
if (capability == TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY) {
- return NetworkSliceInfo.SLICE_SERVICE_TYPE_URLLC;
+ return "PRIORITIZE_LATENCY";
}
- return NetworkSliceInfo.SLICE_SERVICE_TYPE_NONE;
+ return "";
+ }
+
+ /**
+ * Get the slice service types associated with the given premium capability.
+ * The slice service type is a field in {@link NetworkSliceInfo} that helps to match determine
+ * whether the premium capability was successfully set up on the carrier network.
+ * @param capability The premium capability to get the associated slice service types for.
+ * @return A set of slice service types associated with the premium capability.
+ */
+ @VisibleForTesting
+ @NonNull @NetworkSliceInfo.SliceServiceType public static Set<Integer> getSliceServiceTypes(
+ @TelephonyManager.PremiumCapability int capability) {
+ Set<Integer> sliceServiceTypes = new HashSet<>();
+ if (capability == TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY) {
+ sliceServiceTypes.add(NetworkSliceInfo.SLICE_SERVICE_TYPE_EMBB);
+ sliceServiceTypes.add(NetworkSliceInfo.SLICE_SERVICE_TYPE_URLLC);
+ } else {
+ sliceServiceTypes.add(NetworkSliceInfo.SLICE_SERVICE_TYPE_NONE);
+ }
+ return sliceServiceTypes;
}
private boolean isNetworkAvailable() {
@@ -1094,9 +1195,9 @@
switch (failureCode) {
case FAILURE_CODE_UNKNOWN: return "UNKNOWN";
case FAILURE_CODE_CARRIER_URL_UNAVAILABLE: return "CARRIER_URL_UNAVAILABLE";
- case FAILURE_CODE_SERVER_UNREACHABLE: return "SERVER_UNREACHABLE";
case FAILURE_CODE_AUTHENTICATION_FAILED: return "AUTHENTICATION_FAILED";
case FAILURE_CODE_PAYMENT_FAILED: return "PAYMENT_FAILED";
+ case FAILURE_CODE_NO_USER_DATA: return "NO_USER_DATA";
default:
return "UNKNOWN(" + failureCode + ")";
}
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index d36f8be..adb07f9 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -72,7 +72,7 @@
public static DisconnectCause toTelecomDisconnectCause(
int telephonyDisconnectCause, int telephonyPreciseDisconnectCause, String reason) {
return toTelecomDisconnectCause(telephonyDisconnectCause, telephonyPreciseDisconnectCause,
- reason, SubscriptionManager.getDefaultVoicePhoneId(), null);
+ reason, SubscriptionManager.getDefaultVoicePhoneId(), null, new FlagsAdapterImpl());
}
/**
@@ -86,7 +86,7 @@
public static DisconnectCause toTelecomDisconnectCause(int telephonyDisconnectCause,
String reason, int phoneId) {
return toTelecomDisconnectCause(telephonyDisconnectCause, CallFailCause.NOT_VALID,
- reason, phoneId, null);
+ reason, phoneId, null, new FlagsAdapterImpl());
}
/**
@@ -101,9 +101,9 @@
*/
public static DisconnectCause toTelecomDisconnectCause(
int telephonyDisconnectCause, int telephonyPreciseDisconnectCause, String reason,
- int phoneId, ImsReasonInfo imsReasonInfo) {
+ int phoneId, ImsReasonInfo imsReasonInfo, FlagsAdapter featureFlags) {
return toTelecomDisconnectCause(telephonyDisconnectCause, telephonyPreciseDisconnectCause,
- reason, phoneId, imsReasonInfo, getCarrierConfigBundle(phoneId));
+ reason, phoneId, imsReasonInfo, getCarrierConfigBundle(phoneId), featureFlags);
}
/**
@@ -115,16 +115,17 @@
@VisibleForTesting
static DisconnectCause toTelecomDisconnectCause(
int telephonyDisconnectCause, int telephonyPreciseDisconnectCause, String reason,
- int phoneId, ImsReasonInfo imsReasonInfo, PersistableBundle carrierConfig) {
+ int phoneId, ImsReasonInfo imsReasonInfo, PersistableBundle carrierConfig,
+ FlagsAdapter featureFlags) {
Context context = PhoneGlobals.getInstance();
return new DisconnectCause(
toTelecomDisconnectCauseCode(telephonyDisconnectCause, carrierConfig),
toTelecomDisconnectCauseLabel(context, telephonyDisconnectCause,
- telephonyPreciseDisconnectCause, carrierConfig),
+ telephonyPreciseDisconnectCause, carrierConfig, featureFlags),
toTelecomDisconnectCauseDescription(context, telephonyDisconnectCause, phoneId),
toTelecomDisconnectReason(context, telephonyDisconnectCause, reason, phoneId),
- toTelecomDisconnectCauseTone(telephonyDisconnectCause, carrierConfig),
+ toTelecomDisconnectCauseTone(telephonyDisconnectCause, carrierConfig, featureFlags),
telephonyDisconnectCause,
telephonyPreciseDisconnectCause,
imsReasonInfo);
@@ -264,20 +265,29 @@
*/
private static CharSequence toTelecomDisconnectCauseLabel(
Context context, int telephonyDisconnectCause, int telephonyPreciseDisconnectCause,
- PersistableBundle carrierConfig) {
+ PersistableBundle carrierConfig, FlagsAdapter featureFlags) {
CharSequence label;
-
- // special case: some carriers determine what disconnect causes play the BUSY tone.
- // hence, must adjust the disconnectCause LABEL to match the tone.
- if (doesCarrierClassifyDisconnectCauseAsBusyCause(telephonyDisconnectCause,
- carrierConfig)) {
- return context.getResources().getString(R.string.callFailed_userBusy);
+ if (!featureFlags.doNotOverridePreciseLabel()) {
+ // special case: some carriers determine what disconnect causes play the BUSY tone.
+ // hence, must adjust the disconnectCause LABEL to match the tone.
+ if (doesCarrierClassifyDisconnectCauseAsBusyCause(telephonyDisconnectCause,
+ carrierConfig)) {
+ return context.getResources().getString(R.string.callFailed_userBusy);
+ }
}
if (telephonyPreciseDisconnectCause != CallFailCause.NOT_VALID) {
label = getLabelFromPreciseDisconnectCause(context, telephonyPreciseDisconnectCause,
telephonyDisconnectCause);
} else {
+ if (featureFlags.doNotOverridePreciseLabel()) {
+ // special case: some carriers determine what disconnect causes play the BUSY tone.
+ // hence, must adjust the disconnectCause LABEL to match the tone.
+ if (doesCarrierClassifyDisconnectCauseAsBusyCause(telephonyDisconnectCause,
+ carrierConfig)) {
+ return context.getResources().getString(R.string.callFailed_userBusy);
+ }
+ }
label = getLabelFromDisconnectCause(context, telephonyDisconnectCause);
}
return label;
@@ -889,7 +899,7 @@
* Returns the tone to play for the disconnect cause, or UNKNOWN if none should be played.
*/
private static int toTelecomDisconnectCauseTone(int telephonyDisconnectCause,
- PersistableBundle carrierConfig) {
+ PersistableBundle carrierConfig, FlagsAdapter featureFlags) {
// special case: some carriers determine what disconnect causes play the BUSY tone.
if (doesCarrierClassifyDisconnectCauseAsBusyCause(telephonyDisconnectCause,
@@ -898,6 +908,10 @@
}
switch (telephonyDisconnectCause) {
+ case android.telephony.DisconnectCause.BUSY:
+ if (featureFlags.doNotOverridePreciseLabel()) {
+ return ToneGenerator.TONE_SUP_BUSY;
+ }
case android.telephony.DisconnectCause.CONGESTION:
return ToneGenerator.TONE_SUP_CONGESTION;
@@ -932,14 +946,21 @@
/**
* Helper method that examines the carrierConfig KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY
* containing the DisconnectCauses that are classified as DisconnectCause.BUSY
- * @param telephonyDisconnectCause
+ *
* @param carrierConfig object that holds all the carrier specific settings
* @return whether the cause is in the carrier config busy tone array
*/
- private static boolean doesCarrierClassifyDisconnectCauseAsBusyCause(
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public static boolean doesCarrierClassifyDisconnectCauseAsBusyCause(
int telephonyDisconnectCause, PersistableBundle carrierConfig) {
+ if (carrierConfig == null) {
+ return false;
+ }
int[] busyToneArray = carrierConfig.getIntArray(
CarrierConfigManager.KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY);
+ if (busyToneArray == null) {
+ return false;
+ }
for (int busyTone : busyToneArray) {
if (busyTone == telephonyDisconnectCause) {
return true;
diff --git a/src/com/android/services/telephony/FlagsAdapter.java b/src/com/android/services/telephony/FlagsAdapter.java
new file mode 100644
index 0000000..fdf00a5
--- /dev/null
+++ b/src/com/android/services/telephony/FlagsAdapter.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 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.services.telephony;
+
+/**
+ * FlagsAdapter can assist in testing flags that are "Fixed Read Only Flags"
+ * (is_fixed_read_only: true)
+ */
+public interface FlagsAdapter {
+ boolean doNotOverridePreciseLabel();
+}
diff --git a/src/com/android/services/telephony/FlagsAdapterImpl.java b/src/com/android/services/telephony/FlagsAdapterImpl.java
new file mode 100644
index 0000000..c935c59
--- /dev/null
+++ b/src/com/android/services/telephony/FlagsAdapterImpl.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 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.services.telephony;
+
+import com.android.internal.telephony.flags.Flags;
+
+/**
+ * FlagsAdapterImpl should always be used in production when Telephony is checking a flag status.
+ * To help with testing, it may be necessary to have a different implementation
+ * (e.g. flag is read only).
+ */
+public class FlagsAdapterImpl implements FlagsAdapter {
+ public boolean doNotOverridePreciseLabel() {
+ return Flags.doNotOverridePreciseLabel();
+ }
+}
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 755c85f..7f0c800 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -38,6 +38,7 @@
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.flags.Flags;
import com.android.phone.PhoneUtils;
import com.android.phone.R;
import com.android.telephony.Rlog;
@@ -700,7 +701,11 @@
if (mConferenceHost == null) {
return;
}
- mConferenceHost.performHold();
+ if (Flags.conferenceHoldUnholdChangedToSendMessage()) {
+ mConferenceHost.onHold();
+ } else {
+ mConferenceHost.performHold();
+ }
}
/**
@@ -711,7 +716,11 @@
if (mConferenceHost == null) {
return;
}
- mConferenceHost.performUnhold();
+ if (Flags.conferenceHoldUnholdChangedToSendMessage()) {
+ mConferenceHost.onUnhold();
+ } else {
+ mConferenceHost.performUnhold();
+ }
}
/**
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 2b69b82..ea29b77 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -16,6 +16,7 @@
package com.android.services.telephony;
+import android.app.ActivityManager;
import android.app.PropertyInvalidatedCache;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -1191,7 +1192,7 @@
private int mSubscriptionListenerState = LISTENER_STATE_UNREGISTERED;
private int mServiceState = ServiceState.STATE_POWER_OFF;
private int mActiveDataSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- private boolean mIsPrimaryUser = true;
+ private boolean mIsPrimaryUser = UserHandle.of(ActivityManager.getCurrentUser()).isSystem();
private ExponentialBackoff mRegisterSubscriptionListenerBackoff;
private final HandlerThread mHandlerThread = new HandlerThread("TelecomAccountRegistry");
diff --git a/src/com/android/services/telephony/TelephonyConference.java b/src/com/android/services/telephony/TelephonyConference.java
index 7e4693f..4a70e1c 100644
--- a/src/com/android/services/telephony/TelephonyConference.java
+++ b/src/com/android/services/telephony/TelephonyConference.java
@@ -23,6 +23,7 @@
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.Flags;
import java.util.List;
@@ -128,7 +129,11 @@
public void onHold() {
final TelephonyConnection connection = getFirstConnection();
if (connection != null) {
- connection.performHold();
+ if (Flags.conferenceHoldUnholdChangedToSendMessage()) {
+ connection.onHold();
+ } else {
+ connection.performHold();
+ }
}
}
@@ -139,7 +144,11 @@
public void onUnhold() {
final TelephonyConnection connection = getFirstConnection();
if (connection != null) {
- connection.performUnhold();
+ if (Flags.conferenceHoldUnholdChangedToSendMessage()) {
+ connection.onUnhold();
+ } else {
+ connection.performUnhold();
+ }
}
}
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 6d136b0..86770a1 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -149,6 +149,8 @@
private static final int MSG_DTMF_DONE = 22;
private static final int MSG_MEDIA_ATTRIBUTES_CHANGED = 23;
private static final int MSG_ON_RTT_INITIATED = 24;
+ private static final int MSG_HOLD = 25;
+ private static final int MSG_UNHOLD = 26;
private static final String JAPAN_COUNTRY_CODE_WITH_PLUS_SIGN = "+81";
private static final String JAPAN_ISO_COUNTRY_CODE = "JP";
@@ -344,6 +346,12 @@
}
sendRttInitiationSuccess();
break;
+ case MSG_HOLD:
+ performHold();
+ break;
+ case MSG_UNHOLD:
+ performUnhold();
+ break;
}
}
};
@@ -1049,12 +1057,12 @@
@Override
public void onHold() {
- performHold();
+ mHandler.obtainMessage(MSG_HOLD).sendToTarget();
}
@Override
public void onUnhold() {
- performUnhold();
+ mHandler.obtainMessage(MSG_UNHOLD).sendToTarget();
}
@Override
@@ -2558,7 +2566,8 @@
disconnectCause,
preciseDisconnectCause,
mOriginalConnection.getVendorDisconnectCause(),
- getPhone().getPhoneId(), imsReasonInfo));
+ getPhone().getPhoneId(), imsReasonInfo,
+ new FlagsAdapterImpl()));
close();
}
break;
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index bf7ce00..48169a2 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -16,9 +16,13 @@
package com.android.services.telephony;
+import static android.telephony.CarrierConfigManager.KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL;
import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING;
import static android.telephony.TelephonyManager.HAL_SERVICE_VOICE;
+import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_GSM;
+import static com.android.internal.telephony.flags.Flags.carrierEnabledSatelliteFlag;
+
import android.annotation.NonNull;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -32,6 +36,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelUuid;
+import android.os.PersistableBundle;
import android.provider.DeviceConfig;
import android.telecom.Conference;
import android.telecom.Conferenceable;
@@ -114,6 +119,7 @@
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.regex.Pattern;
+import java.util.stream.Stream;
import javax.annotation.Nullable;
@@ -586,6 +592,24 @@
releaseEmergencyCallDomainSelection(false);
}
}
+
+ @Override
+ public void onConnectionPropertiesChanged(Connection connection,
+ int connectionProperties) {
+ if ((connection == null) || (mEmergencyStateTracker == null)) {
+ return;
+ }
+ TelephonyConnection c = (TelephonyConnection) connection;
+ com.android.internal.telephony.Connection origConn = c.getOriginalConnection();
+ if ((origConn == null) || (!origConn.getState().isAlive())) {
+ // ignore if there is no original connection alive
+ Log.i(this, "onConnectionPropertiesChanged without orig connection alive");
+ return;
+ }
+ Log.i(this, "onConnectionPropertiesChanged prop=" + connectionProperties);
+ mEmergencyStateTracker.onEmergencyCallPropertiesChanged(connectionProperties,
+ c.getTelecomCallId());
+ }
};
private final TelephonyConnection.TelephonyConnectionListener
@@ -1061,8 +1085,6 @@
final boolean isAirplaneModeOn = mDeviceState.isAirplaneModeOn(this);
- boolean needToTurnOnRadio = (isEmergencyNumber && (!isRadioOn() || isAirplaneModeOn))
- || isRadioPowerDownOnBluetooth();
boolean needToTurnOffSatellite = isSatelliteBlockingCall(isEmergencyNumber);
// Get the right phone object from the account data passed in.
@@ -1070,6 +1092,10 @@
/* Note: when not an emergency, handle can be null for unknown callers */
handle == null ? null : handle.getSchemeSpecificPart());
+ boolean isPhoneWifiCallingEnabled = phone != null && phone.isWifiCallingEnabled();
+ boolean needToTurnOnRadio = (isEmergencyNumber && (!isRadioOn() || isAirplaneModeOn))
+ || (isRadioPowerDownOnBluetooth() && !isPhoneWifiCallingEnabled);
+
if (mDomainSelectionResolver.isDomainSelectionSupported()) {
// Normal routing emergency number shall be handled by normal call domain selctor.
if (isEmergencyNumber && !isNormalRouting(phone, number)) {
@@ -1083,7 +1109,7 @@
if (needToTurnOnRadio || needToTurnOffSatellite) {
final Uri resultHandle = handle;
- final int originalPhoneType = phone.getPhoneType();
+ final int originalPhoneType = (phone == null) ? PHONE_TYPE_GSM : phone.getPhoneType();
final Connection resultConnection = getTelephonyConnection(request, numberToDial,
isEmergencyNumber, resultHandle, phone);
if (mRadioOnHelper == null) {
@@ -1171,7 +1197,8 @@
}
if (!isEmergencyNumber) {
- if (mSatelliteController.isSatelliteEnabled()) {
+ if (mSatelliteController.isSatelliteEnabled()
+ || isCallDisallowedDueToSatellite(phone)) {
Log.d(this, "onCreateOutgoingConnection, cannot make call in satellite mode.");
return Connection.createFailedConnection(
mDisconnectCauseFactory.toTelecomDisconnectCause(
@@ -1362,7 +1389,7 @@
// one and causing UI Jank.
boolean noActiveSimCard = SubscriptionManagerService.getInstance()
.getActiveSubInfoCount(phone.getContext().getOpPackageName(),
- phone.getContext().getAttributionTag()) == 0;
+ phone.getContext().getAttributionTag(), true/*isForAllProfile*/) == 0;
// If there's no active sim card and the device is in emergency mode, use E account.
addExistingConnection(mPhoneUtilsProxy.makePstnPhoneAccountHandleWithPrefix(
phone, "", isEmergencyNumber && noActiveSimCard), repConnection);
@@ -2249,8 +2276,7 @@
.setVideoState(videoState)
.setIntentExtras(extras)
.setRttTextStream(mNormalCallConnection.getRttTextStream())
- .setIsWpsCall(NormalCallDomainSelectionConnection
- .isWpsCall(number))
+ .setIsWpsCall(PhoneNumberUtils.isWpsCallNumber(number))
.build(),
mNormalCallConnection::registerForCallEvents);
@@ -2311,7 +2337,7 @@
// Check and select same domain as ongoing call on the same subscription (if exists)
int activeCallDomain = getActiveCallDomain(phone.getSubId());
if (activeCallDomain != NetworkRegistrationInfo.DOMAIN_UNKNOWN
- && !NormalCallDomainSelectionConnection.isWpsCall(number)) {
+ && !PhoneNumberUtils.isWpsCallNumber(number)) {
Log.d(LOG_TAG, "Selecting same domain as ongoing call on same subId");
mNormalCallConnection = connection;
handleOutgoingCallConnectionByCallDomainSelection(
@@ -2573,17 +2599,63 @@
return false;
}
- private boolean isNormalRouting(Phone phone, String number) {
- if (phone.getEmergencyNumberTracker() != null) {
- EmergencyNumber num = phone.getEmergencyNumberTracker().getEmergencyNumber(number);
- if (num != null) {
- return num.getEmergencyCallRouting()
- == EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
+ private boolean isEmergencyNumberAllowedOnDialedSim(Phone phone, String number) {
+ CarrierConfigManager cfgManager = (CarrierConfigManager)
+ phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (cfgManager != null) {
+ PersistableBundle b = cfgManager.getConfigForSubId(phone.getSubId(),
+ KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL);
+ if (b == null) {
+ b = CarrierConfigManager.getDefaultConfig();
+ }
+ // We need to check only when KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL is true.
+ if (b.getBoolean(KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, false)
+ && (phone.getEmergencyNumberTracker() != null)) {
+ if (!phone.getEmergencyNumberTracker().isEmergencyNumber(number)) {
+ Log.i(this, "isEmergencyNumberAllowedOnDialedSim false");
+ return false;
+ }
}
}
+ return true;
+ }
+
+ private boolean isNormalRouting(Phone phone, String number) {
+ // Check isEmergencyNumberAllowedOnDialedSim(): some carriers do not want to handle
+ // dial requests for numbers which are in the emergency number list on another SIM,
+ // but not on their own. Such numbers shall be handled by normal call domain selector.
+ return (isNormalRoutingNumber(phone, number)
+ || !isEmergencyNumberAllowedOnDialedSim(phone, number));
+ }
+
+ private boolean isNormalRoutingNumber(Phone phone, String number) {
+ if (phone.getEmergencyNumberTracker() != null) {
+ // Note: There can potentially be multiple instances of EmergencyNumber found; if any of
+ // them have normal routing, then use normal routing.
+ List<EmergencyNumber> nums = phone.getEmergencyNumberTracker().getEmergencyNumbers(
+ number);
+ return nums.stream().anyMatch(n ->
+ n.getEmergencyCallRouting() == EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
+ }
return false;
}
+ /**
+ * Determines the phone to use for a normal routed emergency call.
+ * @param number The emergency number.
+ * @return The {@link Phone} to place the normal routed emergency call on, or {@code null} if
+ * none was found.
+ */
+ @VisibleForTesting
+ public Phone getPhoneForNormalRoutedEmergencyCall(String number) {
+ return Stream.of(mPhoneFactoryProxy.getPhones())
+ .filter(p -> p.shouldPreferInServiceSimForNormalRoutedEmergencyCall()
+ && isNormalRoutingNumber(p, number)
+ && isAvailableForEmergencyCalls(p,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL))
+ .findFirst().orElse(null);
+ }
+
private boolean isVoiceInService(Phone phone, boolean imsVoiceCapable) {
// Dialing normal call is available.
if (phone.isWifiCallingEnabled()) {
@@ -3031,15 +3103,34 @@
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
int phoneId = mSubscriptionManagerProxy.getPhoneId(subId);
chosenPhone = mPhoneFactoryProxy.getPhone(phoneId);
+ Log.i(this, "getPhoneForAccount: handle=%s, subId=%s", accountHandle,
+ (chosenPhone == null ? "null" : chosenPhone.getSubId()));
}
- // If this is an emergency call and the phone we originally planned to make this call
+
+ // If this isn't an emergency call, just use the chosen phone (or null if none was found).
+ if (!isEmergency) {
+ return chosenPhone;
+ }
+
+ // Check if this call should be treated as a normal routed emergency call; we'll return null
+ // if this is not a normal routed emergency call.
+ Phone normalRoutingPhone = getPhoneForNormalRoutedEmergencyCall(emergencyNumberAddress);
+ if (normalRoutingPhone != null) {
+ Log.i(this, "getPhoneForAccount: normal routed emergency number,"
+ + "using phoneId=%d/subId=%d", normalRoutingPhone.getPhoneId(),
+ normalRoutingPhone.getSubId());
+ return normalRoutingPhone;
+ }
+
+ // Default emergency call phone selection logic:
+ // This is an emergency call and the phone we originally planned to make this call
// with is not in service or was invalid, try to find one that is in service, using the
// default as a last chance backup.
- if (isEmergency && (chosenPhone == null || !isAvailableForEmergencyCalls(chosenPhone))) {
+ if (chosenPhone == null || !isAvailableForEmergencyCalls(chosenPhone)) {
Log.d(this, "getPhoneForAccount: phone for phone acct handle %s is out of service "
+ "or invalid for emergency call.", accountHandle);
chosenPhone = getPhoneForEmergencyCall(emergencyNumberAddress);
- Log.d(this, "getPhoneForAccount: using subId: " +
+ Log.i(this, "getPhoneForAccount: emergency call - using subId: %s",
(chosenPhone == null ? "null" : chosenPhone.getSubId()));
}
return chosenPhone;
@@ -3459,10 +3550,20 @@
}
}
- /**
- * Returns true if the state of the Phone is IN_SERVICE or available for emergency calling only.
- */
private boolean isAvailableForEmergencyCalls(Phone phone) {
+ return isAvailableForEmergencyCalls(phone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
+ }
+
+ /**
+ * Determines if the phone is available for an emergency call given the specified routing.
+ *
+ * @param phone the phone to check the service availability for
+ * @param routing the emergency call routing for this call
+ */
+ @VisibleForTesting
+ public boolean isAvailableForEmergencyCalls(Phone phone,
+ @EmergencyNumber.EmergencyCallRouting int routing) {
if (phone.getImsRegistrationTech() == ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM) {
// When a Phone is registered to Cross-SIM calling, there must always be a Phone on the
// other sub which is registered to cellular, so that must be selected.
@@ -3470,8 +3571,17 @@
+ phone + " as it is registered to CROSS_SIM");
return false;
}
- return ServiceState.STATE_IN_SERVICE == phone.getServiceState().getState() ||
- phone.getServiceState().isEmergencyOnly();
+
+ // In service phones are always appropriate for emergency calls.
+ if (ServiceState.STATE_IN_SERVICE == phone.getServiceState().getState()) {
+ return true;
+ }
+
+ // If the call routing is unknown or is using emergency routing, an emergency only attach is
+ // sufficient for placing the emergency call. Normal routed emergency calls cannot be
+ // placed on an emergency-only phone.
+ return (routing != EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL
+ && phone.getServiceState().isEmergencyOnly());
}
/**
@@ -3852,6 +3962,19 @@
});
}
+ static boolean isStateActive(Conferenceable conferenceable) {
+ if (conferenceable instanceof Connection) {
+ Connection connection = (Connection) conferenceable;
+ return connection.getState() == Connection.STATE_ACTIVE;
+ } else if (conferenceable instanceof Conference) {
+ Conference conference = (Conference) conferenceable;
+ return conference.getState() == Connection.STATE_ACTIVE;
+ } else {
+ throw new IllegalArgumentException(
+ "isStateActive(): Unexpected conferenceable! " + conferenceable);
+ }
+ }
+
static void onHold(Conferenceable conferenceable) {
if (conferenceable instanceof Connection) {
Connection connection = (Connection) conferenceable;
@@ -4011,7 +4134,7 @@
TelephonyManagerProxy telephonyManagerProxy) {
Conferenceable c = maybeGetFirstConferenceableFromOtherSubscription(
connections, conferences, outgoingHandle, telephonyManagerProxy);
- if (c != null) {
+ if (c != null && isStateActive(c)) {
onHold(c);
return c;
}
@@ -4061,10 +4184,44 @@
private void handleEmergencyCallStartedForSatelliteSOSMessageRecommender(
@NonNull TelephonyConnection connection, @NonNull Phone phone) {
if (mSatelliteSOSMessageRecommender == null) {
- mSatelliteSOSMessageRecommender = new SatelliteSOSMessageRecommender(
+ mSatelliteSOSMessageRecommender = new SatelliteSOSMessageRecommender(phone.getContext(),
phone.getContext().getMainLooper());
}
connection.addTelephonyConnectionListener(mEmergencyConnectionSatelliteListener);
- mSatelliteSOSMessageRecommender.onEmergencyCallStarted(connection, phone);
+ mSatelliteSOSMessageRecommender.onEmergencyCallStarted(connection);
+ }
+
+ /**
+ * Check whether making a call is disallowed while using satellite
+ * @param phone phone object whose supported services needs to be checked
+ * @return {@code true} if network does not support calls while using satellite
+ * else {@code false}.
+ */
+ private boolean isCallDisallowedDueToSatellite(Phone phone) {
+ if (!carrierEnabledSatelliteFlag()) {
+ return false;
+ }
+
+ if (phone == null) {
+ return false;
+ }
+
+ ServiceState serviceState = phone.getServiceState();
+ if (!serviceState.isUsingNonTerrestrialNetwork()) {
+ // Device is not connected to satellite
+ return false;
+ }
+
+ for (NetworkRegistrationInfo nri : serviceState.getNetworkRegistrationInfoList()) {
+ if (nri.isNonTerrestrialNetwork()
+ && nri.getAvailableServices().contains(
+ NetworkRegistrationInfo.SERVICE_TYPE_VOICE)) {
+ // Call is supported while using satellite
+ return false;
+ }
+ }
+
+ // Call is disallowed while using satellite
+ return true;
}
}
diff --git a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
index 3388c97..b8956d5 100644
--- a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
@@ -53,9 +53,11 @@
import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING;
import static android.telephony.PreciseDisconnectCause.EMERGENCY_PERM_FAILURE;
import static android.telephony.PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE;
+import static android.telephony.PreciseDisconnectCause.SERVICE_OPTION_NOT_AVAILABLE;
import android.annotation.NonNull;
import android.content.Context;
+import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -83,12 +85,12 @@
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
-import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ProvisioningManager;
import android.text.TextUtils;
import android.util.LocalLog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.phone.R;
import java.util.ArrayList;
import java.util.Arrays;
@@ -117,17 +119,7 @@
private static final LocalLog sLocalLog = new LocalLog(LOG_SIZE);
- private static final ArrayList<String> sAllowOnlyWithSimReady = new ArrayList<>();
-
- static {
- // b/177967010, JP
- sAllowOnlyWithSimReady.add("jp"); // Japan
- // b/198393826, DE
- sAllowOnlyWithSimReady.add("de"); // Germany
- // b/230443699, IN and SG
- sAllowOnlyWithSimReady.add("in"); // India
- sAllowOnlyWithSimReady.add("sg"); // Singapore
- }
+ private static List<String> sSimReadyAllowList;
/**
* Network callback used to determine whether Wi-Fi is connected or not.
@@ -171,6 +163,7 @@
private CancellationSignal mCancelSignal;
+ // Members for carrier configuration
private @RadioAccessNetworkType int[] mImsRatsConfig;
private @RadioAccessNetworkType int[] mCsRatsConfig;
private @RadioAccessNetworkType int[] mImsRoamRatsConfig;
@@ -180,8 +173,6 @@
private List<String> mCdmaPreferredNumbers;
private boolean mPreferImsWhenCallsOnCs;
private int mVoWifiRequiresCondition;
- private boolean mIsMonitoringConnectivity;
- private boolean mWiFiAvailable;
private int mScanTimeout;
private int mMaxCellularTimeout;
private int mMaxNumOfVoWifiTries;
@@ -191,6 +182,11 @@
private boolean mRequiresImsRegistration;
private boolean mRequiresVoLteEnabled;
private boolean mLtePreferredAfterNrFailure;
+
+ // Members for states
+ private boolean mIsMonitoringConnectivity;
+ private boolean mWiFiAvailable;
+ private boolean mWasCsfbAfterPsFailure;
private boolean mTryCsWhenPsFails;
private boolean mTryEpsFallback;
private int mModemCount;
@@ -367,11 +363,21 @@
// Dial CS for CSFB instead of scanning with CS preferred network list.
logi("reselectDomain tryCs=" + accessNetworkTypeToString(mCsNetworkType));
if (mCsNetworkType != UNKNOWN) {
+ mWasCsfbAfterPsFailure = true;
onWwanNetworkTypeSelected(mCsNetworkType);
return;
}
}
+ if (mWasCsfbAfterPsFailure) {
+ mWasCsfbAfterPsFailure = false;
+ if (cause == SERVICE_OPTION_NOT_AVAILABLE) {
+ // b/299875872, combined attach but EXTENDED_SERVICE_REQUEST failed.
+ // Try CS preferred scan instead of PS preferred scan.
+ mLastNetworkType = EUTRAN;
+ }
+ }
+
if (mMaxCellularTimerExpired) {
if (mLastTransportType == TRANSPORT_TYPE_WWAN
&& maybeDialOverWlan()) {
@@ -435,6 +441,7 @@
private void startDomainSelection() {
logi("startDomainSelection modemCount=" + mModemCount);
+ readResourceConfiguration();
updateCarrierConfiguration();
mDomainSelectionRequested = true;
startCrossStackTimer();
@@ -469,6 +476,12 @@
selectDomain();
}
+ private boolean isSimReady() {
+ if (!SubscriptionManager.isValidSubscriptionId(getSubId())) return false;
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ return tm.getSimState(getSlotId()) == TelephonyManager.SIM_STATE_READY;
+ }
+
/**
* Caches the configuration.
*/
@@ -483,8 +496,9 @@
b.getIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY);
mImsRoamRatsConfig = b.getIntArray(
KEY_EMERGENCY_OVER_IMS_ROAMING_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY);
- if (!SubscriptionManager.isValidSubscriptionId(getSubId())) {
- // Default configuration includes only EUTRAN . In case of no SIM, add NGRAN.
+ if (!isSimReady()) {
+ // Default configuration includes only EUTRAN.
+ // In case of no SIM or SIM locked state, add NGRAN.
mImsRatsConfig = new int[] { EUTRAN, NGRAN };
mImsRoamRatsConfig = new int[] { EUTRAN, NGRAN };
}
@@ -557,22 +571,51 @@
}
}
+ /**
+ * Caches the resource configuration.
+ */
+ private void readResourceConfiguration() {
+ if (sSimReadyAllowList != null) return;
+ try {
+ sSimReadyAllowList = Arrays.asList(mContext.getResources().getStringArray(
+ R.array.config_countries_require_sim_for_emergency));
+ } catch (Resources.NotFoundException nfe) {
+ loge("readResourceConfiguration exception=" + nfe);
+ } catch (NullPointerException npe) {
+ loge("readResourceConfiguration exception=" + npe);
+ } finally {
+ if (sSimReadyAllowList == null) {
+ sSimReadyAllowList = new ArrayList<String>();
+ }
+ }
+ logi("readResourceConfiguration simReadyCountries=" + sSimReadyAllowList);
+ }
+
+ /** For test purpose only */
+ @VisibleForTesting
+ public void clearResourceConfiguration() {
+ sSimReadyAllowList = null;
+ }
+
private void selectDomain() {
// State updated right after creation.
if (!mDomainSelectionRequested) return;
- // Emergency network scan requested has not been completed.
- if (mIsScanRequested) return;
-
- // Domain selection completed, {@link #reselectDomain()} will restart domain selection.
- if (mDomainSelected) return;
-
if (!mBarringInfoReceived || !mImsRegStateReceived || !mMmTelCapabilitiesReceived) {
logi("selectDomain not received"
+ " BarringInfo, IMS registration state, or MMTEL capabilities");
return;
}
+ // The statements below should be executed only once to select domain from initial state.
+ // Next domain selection shall be triggered by reselectDomain().
+ // However, selectDomain() can be called by change of IMS service state and Barring status
+ // at any time. mIsScanRequested and mDomainSelected are not enough since there are cases
+ // when neither mIsScanRequested nor mDomainSelected is set though selectDomain() has been
+ // executed already.
+ // Reset mDomainSelectionRequested to avoid redundant execution of selectDomain().
+ mDomainSelectionRequested = false;
+
if (!allowEmergencyCalls(mSelectionAttributes.getEmergencyRegResult())) {
// Detected the country and found that emergency calls are not allowed with this slot.
terminateSelectionPermanentlyForSlot();
@@ -694,8 +737,7 @@
mCancelSignal = new CancellationSignal();
// In case dialing over Wi-Fi has failed, do not the change the domain preference.
if (!wifiFailed) {
- mLastPreferredNetworks = getNextPreferredNetworks(csPreferred, mTryEpsFallback,
- !startVoWifiTimer);
+ mLastPreferredNetworks = getNextPreferredNetworks(csPreferred, mTryEpsFallback);
}
mTryEpsFallback = false;
@@ -733,13 +775,11 @@
*
* @param csPreferred Indicates whether CS preferred scan is requested.
* @param tryEpsFallback Indicates whether scan requested for EPS fallback.
- * @param lastScanFailed Indicates whether this a scan request due to the failure of last scan
- * request.
* @return The list of preferred network types.
*/
@VisibleForTesting
public @RadioAccessNetworkType List<Integer> getNextPreferredNetworks(boolean csPreferred,
- boolean tryEpsFallback, boolean lastScanFailed) {
+ boolean tryEpsFallback) {
if (mRequiresVoLteEnabled && !isAdvancedCallingSettingEnabled()) {
// Emergency call over IMS is not supported.
logi("getNextPreferredNetworks VoLte setting is not enabled.");
@@ -809,23 +849,6 @@
}
}
- // There can be cases that dialing IMS call failed but the modem doesn't know this
- // situation with some vendor solutions. For example, dialing failure due to the
- // emergency registration failure.
- // Remove the current RAT from the scan list to avoid modem select current PLMN.
- // If the scan fails, the next scan will include this RAT again.
- //
- // TODO (b/278183420) Replace this with a better solution by adding indication
- // of call setup failure to the scan request.
- ImsReasonInfo reasonInfo = mSelectionAttributes.getPsDisconnectCause();
- if (!lastScanFailed && reasonInfo != null
- && reasonInfo.getCode() == ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED) {
- logi("getNextPreferredNetworks remove " + mLastNetworkType);
- if (preferredNetworks.size() > 1) {
- preferredNetworks.remove(Integer.valueOf(mLastNetworkType));
- }
- }
-
return preferredNetworks;
}
@@ -1035,13 +1058,13 @@
* @return {@code true} if emergency call over Wi-Fi allowed.
*/
private boolean isEmcOverWifiSupported() {
- if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ if (isSimReady()) {
List<Integer> domains = getDomainPreference();
boolean ret = domains.contains(DOMAIN_PS_NON_3GPP);
logi("isEmcOverWifiSupported " + ret);
return ret;
} else {
- logi("isEmcOverWifiSupported invalid subId");
+ logi("isEmcOverWifiSupported invalid subId or lock state");
}
return false;
}
@@ -1332,7 +1355,7 @@
}
String iso = regResult.getIso();
- if (sAllowOnlyWithSimReady.contains(iso)) {
+ if (sSimReadyAllowList.contains(iso)) {
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
int simState = tm.getSimState(getSlotId());
if (simState != TelephonyManager.SIM_STATE_READY) {
diff --git a/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
index f176d90..32c05fa 100644
--- a/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
@@ -28,13 +28,12 @@
import android.telephony.DisconnectCause;
import android.telephony.DomainSelectionService.SelectionAttributes;
import android.telephony.NetworkRegistrationInfo;
+import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TransportSelectorCallback;
import android.telephony.ims.ImsReasonInfo;
-import com.android.internal.telephony.domainselection.NormalCallDomainSelectionConnection;
-
/**
* Implements domain selector for outgoing non-emergency calls.
*/
@@ -119,6 +118,12 @@
mTransportSelectorCallback = null;
}
+ @Override
+ public void destroy() {
+ finishSelection();
+ super.destroy();
+ }
+
/**
* Cancel an ongoing selection operation. It is up to the DomainSelectionService
* to clean up all ongoing operations with the framework.
@@ -375,9 +380,7 @@
// Handle voice call.
if (mImsStateTracker.isImsVoiceCapable()) {
logd("IMS is voice capable");
- // TODO(b/266175810) Remove this dependency.
- if (NormalCallDomainSelectionConnection
- .isWpsCall(mSelectionAttributes.getNumber())) {
+ if (PhoneNumberUtils.isWpsCallNumber(mSelectionAttributes.getNumber())) {
handleWpsCall();
} else {
notifyPsSelected();
diff --git a/src/com/android/services/telephony/domainselection/OWNERS b/src/com/android/services/telephony/domainselection/OWNERS
new file mode 100644
index 0000000..b9112be
--- /dev/null
+++ b/src/com/android/services/telephony/domainselection/OWNERS
@@ -0,0 +1,8 @@
+# automatically inherit owners from fw/opt/telephony
+
+hwangoo@google.com
+forestchoi@google.com
+avinashmp@google.com
+mkoon@google.com
+seheele@google.com
+radhikaagrawal@google.com
diff --git a/testapps/GbaTestApp/Android.bp b/testapps/GbaTestApp/Android.bp
index 76e02a0..72f7cc4 100644
--- a/testapps/GbaTestApp/Android.bp
+++ b/testapps/GbaTestApp/Android.bp
@@ -22,7 +22,6 @@
static_libs: [
"androidx.appcompat_appcompat",
"androidx-constraintlayout_constraintlayout",
- "ub-uiautomator",
],
srcs: ["src/**/*.java"],
javacflags: ["-parameters"],
diff --git a/testapps/TestSatelliteApp/Android.bp b/testapps/TestSatelliteApp/Android.bp
new file mode 100644
index 0000000..78d125d
--- /dev/null
+++ b/testapps/TestSatelliteApp/Android.bp
@@ -0,0 +1,20 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_app {
+ name: "SatelliteTestApp",
+ system_ext_specific: true,
+ platform_apis: true,
+ manifest: "AndroidManifest.xml",
+ srcs: [
+ "src/**/*.java",
+ "src/**/I*.aidl",
+ ],
+ static_libs: [
+ "SatelliteClient",
+ ],
+ owner: "google",
+ privileged: true,
+ certificate: "platform",
+}
diff --git a/testapps/TestSatelliteApp/AndroidManifest.xml b/testapps/TestSatelliteApp/AndroidManifest.xml
new file mode 100644
index 0000000..fb30bf3
--- /dev/null
+++ b/testapps/TestSatelliteApp/AndroidManifest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.phone.testapps.satellitetestapp">
+ <uses-permission android:name="android.permission.BIND_SATELLITE_SERVICE"/>
+ <uses-permission android:name="android.permission.SATELLITE_COMMUNICATION"/>
+ <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+ <application android:label="SatelliteTestApp">
+ <activity android:name=".SatelliteTestApp"
+ android:label="SatelliteTestApp"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+
+ <service android:name=".TestSatelliteService"
+ android:directBootAware="true"
+ android:persistent="true"
+ android:permission="android.permission.BIND_SATELLITE_SERVICE"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.telephony.satellite.SatelliteService"/>
+ </intent-filter>
+ </service>
+
+ <activity android:name=".SatelliteControl" />
+ <activity android:name=".Datagram" />
+ <activity android:name=".Provisioning" />
+ <activity android:name=".MultipleSendReceive" />
+ <activity android:name=".SendReceive" />
+ <activity android:name=".TestSatelliteWrapper" />
+ </application>
+</manifest>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_Datagram.xml b/testapps/TestSatelliteApp/res/layout/activity_Datagram.xml
new file mode 100644
index 0000000..9e53f41
--- /dev/null
+++ b/testapps/TestSatelliteApp/res/layout/activity_Datagram.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingLeft="4dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:textColor="@android:color/holo_blue_dark"
+ android:textSize="20dp"
+ android:text="Datagram APIs"/>
+ <Button
+ android:id="@+id/startSatelliteTransmissionUpdates"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/startSatelliteTransmissionUpdates"/>
+ <Button
+ android:id="@+id/stopSatelliteTransmissionUpdates"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/stopSatelliteTransmissionUpdates"/>
+ <Button
+ android:id="@+id/pollPendingSatelliteDatagrams"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/pollPendingSatelliteDatagrams"/>
+ <Button
+ android:id="@+id/sendSatelliteDatagram"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/sendSatelliteDatagram"/>
+ <Button
+ android:id="@+id/registerForSatelliteDatagram"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/registerForSatelliteDatagram"/>
+ <Button
+ android:id="@+id/unregisterForSatelliteDatagram"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/unregisterForSatelliteDatagram"/>
+ <Button
+ android:id="@+id/showDatagramSendStateTransition"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/showDatagramSendStateTransition"/>
+ <Button
+ android:id="@+id/showDatagramReceiveStateTransition"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/showDatagramReceiveStateTransition"/>
+ <Button
+ android:id="@+id/registerForSatelliteModemStateChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/registerForSatelliteModemStateChanged"/>
+ <Button
+ android:id="@+id/unregisterForSatelliteModemStateChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/unregisterForSatelliteModemStateChanged"/>
+ <Button
+ android:id="@+id/showSatelliteModemStateTransition"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/showSatelliteModemStateTransition"/>
+ <Button
+ android:id="@+id/Back"
+ android:onClick="Back"
+ android:textColor="@android:color/holo_blue_dark"
+ android:layout_marginTop="100dp"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/Back"/>
+ <TextView
+ android:id="@+id/text_id"
+ android:layout_width="400dp"
+ android:layout_height="50dp"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:textSize="15dp" />
+ <TextView
+ android:id="@+id/showErrorStatus"
+ android:layout_width="400dp"
+ android:layout_height="50dp"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:textSize="15dp" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_MultipleSendReceive.xml b/testapps/TestSatelliteApp/res/layout/activity_MultipleSendReceive.xml
new file mode 100644
index 0000000..3632ecb
--- /dev/null
+++ b/testapps/TestSatelliteApp/res/layout/activity_MultipleSendReceive.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingLeft="4dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:textColor="@android:color/holo_blue_dark"
+ android:textSize="20dp"
+ android:text="Multiple Send and Receive APIs"/>
+ <Button
+ android:id="@+id/multiplePollPendingSatelliteDatagrams"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/multiplePollPendingSatelliteDatagrams"/>
+ <Button
+ android:id="@+id/multipleSendSatelliteDatagram"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/multipleSendSatelliteDatagram"/>
+ <Button
+ android:id="@+id/multipleSendReceiveSatelliteDatagram"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/multipleSendReceiveSatelliteDatagram"/>
+ <Button
+ android:id="@+id/Back"
+ android:onClick="Back"
+ android:textColor="@android:color/holo_blue_dark"
+ android:layout_marginTop="100dp"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/Back"/>
+ <TextView
+ android:id="@+id/text_id"
+ android:layout_width="400dp"
+ android:layout_height="50dp"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:textSize="15dp" />
+ <TextView
+ android:id="@+id/text_id1"
+ android:layout_width="400dp"
+ android:layout_height="65dp"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:layout_centerVertical="true"
+ android:textSize="15dp" />
+ <TextView
+ android:id="@+id/text_id2"
+ android:layout_width="400dp"
+ android:layout_height="65dp"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:layout_centerVertical="true"
+ android:textSize="15dp" />
+ <TextView
+ android:id="@+id/text_id3"
+ android:layout_width="400dp"
+ android:layout_height="65dp"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:layout_centerVertical="true"
+ android:textSize="15dp" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_Provisioning.xml b/testapps/TestSatelliteApp/res/layout/activity_Provisioning.xml
new file mode 100644
index 0000000..da5105d
--- /dev/null
+++ b/testapps/TestSatelliteApp/res/layout/activity_Provisioning.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingLeft="4dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:textColor="@android:color/holo_blue_dark"
+ android:textSize="20dp"
+ android:text="Provisioning APIs"/>
+ <Button
+ android:id="@+id/provisionSatelliteService"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/provisionSatelliteService"/>
+ <Button
+ android:id="@+id/deprovisionSatelliteService"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/deprovisionSatelliteService"/>
+ <Button
+ android:id="@+id/requestIsSatelliteProvisioned"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/requestIsSatelliteProvisioned"/>
+ <Button
+ android:id="@+id/registerForSatelliteProvisionStateChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/registerForSatelliteProvisionStateChanged"/>
+ <Button
+ android:id="@+id/unregisterForSatelliteProvisionStateChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/unregisterForSatelliteProvisionStateChanged"/>
+ <Button
+ android:id="@+id/showCurrentSatelliteProvisionState"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/showCurrentSatelliteProvisionState"/>
+ <Button
+ android:id="@+id/Back"
+ android:onClick="Back"
+ android:textColor="@android:color/holo_blue_dark"
+ android:layout_marginTop="100dp"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/Back"/>
+ <TextView
+ android:id="@+id/text_id"
+ android:layout_width="300dp"
+ android:layout_height="200dp"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:layout_centerVertical="true"
+ android:textSize="15dp" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_SatelliteControl.xml b/testapps/TestSatelliteApp/res/layout/activity_SatelliteControl.xml
new file mode 100644
index 0000000..40e3c69
--- /dev/null
+++ b/testapps/TestSatelliteApp/res/layout/activity_SatelliteControl.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingLeft="4dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:textColor="@android:color/holo_blue_dark"
+ android:textSize="20dp"
+ android:text="Satellite Control APIs"/>
+ <Button
+ android:id="@+id/enableSatellite"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/enableSatellite"/>
+ <Button
+ android:id="@+id/disableSatellite"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/disableSatellite"/>
+ <Button
+ android:id="@+id/requestIsSatelliteEnabled"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/requestIsSatelliteEnabled"/>
+ <Button
+ android:id="@+id/requestIsDemoModeEnabled"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/requestIsDemoModeEnabled"/>
+ <Button
+ android:id="@+id/requestIsSatelliteSupported"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/requestIsSatelliteSupported"/>
+ <Button
+ android:id="@+id/requestSatelliteCapabilities"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/requestSatelliteCapabilities"/>
+ <Button
+ android:id="@+id/requestIsSatelliteCommunicationAllowedForCurrentLocation"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/requestIsSatelliteCommunicationAllowedForCurrentLocation"/>
+ <Button
+ android:id="@+id/requestTimeForNextSatelliteVisibility"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/requestTimeForNextSatelliteVisibility"/>
+ <Button
+ android:id="@+id/Back"
+ android:onClick="Back"
+ android:textColor="@android:color/holo_blue_dark"
+ android:layout_marginTop="100dp"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/Back"/>
+ <TextView
+ android:id="@+id/text_id"
+ android:layout_width="300dp"
+ android:layout_height="200dp"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:layout_centerVertical="true"
+ android:textSize="15dp" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_SatelliteTestApp.xml b/testapps/TestSatelliteApp/res/layout/activity_SatelliteTestApp.xml
new file mode 100644
index 0000000..0753b82
--- /dev/null
+++ b/testapps/TestSatelliteApp/res/layout/activity_SatelliteTestApp.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingLeft="4dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:textColor="@android:color/holo_blue_dark"
+ android:textSize="20dp"
+ android:text="Available Satellite APIs"/>
+ <Button
+ android:id="@+id/SatelliteControl"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/SatelliteControl"/>
+ <Button
+ android:id="@+id/Datagram"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/Datagram"/>
+ <Button
+ android:id="@+id/Provisioning"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/Provisioning"/>
+ <Button
+ android:id="@+id/MultipleSendReceive"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/MultipleSendReceive"/>
+ <Button
+ android:id="@+id/SendReceive"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/SendReceive"/>
+ <Button
+ android:id="@+id/TestSatelliteWrapper"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingEnd="4dp"
+ android:text="@string/TestSatelliteWrapper"/>
+ </LinearLayout>
+</LinearLayout>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_SendReceive.xml b/testapps/TestSatelliteApp/res/layout/activity_SendReceive.xml
new file mode 100644
index 0000000..6490e5d
--- /dev/null
+++ b/testapps/TestSatelliteApp/res/layout/activity_SendReceive.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingLeft="4dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" android:layout_weight="0"
+ android:textColor="@android:color/holo_blue_dark"
+ android:textSize="20dp"
+ android:text="Send and Receive APIs"/>
+ <Button
+ android:id="@+id/sendMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/sendMessage"/>
+ <Button
+ android:id="@+id/receiveMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/receiveMessage"/>
+ <EditText
+ android:id="@+id/enterText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:hint="Enter message to send"
+ android:inputType="text" />
+ <Button
+ android:id="@+id/Back"
+ android:onClick="Back"
+ android:textColor="@android:color/holo_blue_dark"
+ android:layout_marginTop="100dp"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/Back"/>
+ <TextView
+ android:id="@+id/showErrorStatus"
+ android:layout_width="400dp"
+ android:layout_height="50dp"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:textSize="15dp" />
+ <TextView
+ android:id="@+id/devicePosition"
+ android:layout_width="400dp"
+ android:layout_height="65dp"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:layout_centerVertical="true"
+ android:textSize="15dp" />
+ <TextView
+ android:id="@+id/satellitePosition"
+ android:layout_width="400dp"
+ android:layout_height="65dp"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:layout_centerVertical="true"
+ android:textSize="15dp" />
+ <TextView
+ android:id="@+id/messageStatus"
+ android:layout_width="400dp"
+ android:layout_height="65dp"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:layout_centerVertical="true"
+ android:textSize="15dp" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml b/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
new file mode 100644
index 0000000..c136ce7
--- /dev/null
+++ b/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingStart="4dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:layout_weight="0"
+ android:textColor="@android:color/holo_blue_dark"
+ android:textSize="20dp"
+ android:text="Satellite Wrapper Test"/>
+ <Button
+ android:id="@+id/requestNtnSignalStrength"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/requestNtnSignalStrength"/>
+ <Button
+ android:id="@+id/registerForNtnSignalStrengthChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/registerForNtnSignalStrengthChanged"/>
+ <Button
+ android:id="@+id/unregisterForNtnSignalStrengthChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/unregisterForNtnSignalStrengthChanged"/>
+ <Button
+ android:id="@+id/isOnlyNonTerrestrialNetworkSubscription"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/isOnlyNonTerrestrialNetworkSubscription"/>
+ <Button
+ android:id="@+id/registerForSatelliteCapabilitiesChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/registerForSatelliteCapabilitiesChanged"/>
+ <Button
+ android:id="@+id/unregisterForSatelliteCapabilitiesChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/unregisterForSatelliteCapabilitiesChanged"/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <Button
+ android:id="@+id/Back"
+ android:onClick="Back"
+ android:textColor="@android:color/holo_blue_dark"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="10dp"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:paddingRight="4dp"
+ android:text="@string/Back"/>
+ <Button
+ android:id="@+id/ClearLog"
+ android:onClick="ClearLog"
+ android:textColor="@android:color/holo_blue_dark"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="10dp"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:paddingRight="4dp"
+ android:text="@string/ClearLog"/>
+ </LinearLayout>
+ <ListView
+ android:id="@+id/logListView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:layout_centerVertical="true"
+ android:textSize="8dp" />
+</LinearLayout>
diff --git a/testapps/TestSatelliteApp/res/layout/log_textview.xml b/testapps/TestSatelliteApp/res/layout/log_textview.xml
new file mode 100644
index 0000000..a44641b
--- /dev/null
+++ b/testapps/TestSatelliteApp/res/layout/log_textview.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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.
+ -->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/log_textview"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textColor="@android:color/holo_blue_light"
+ android:padding="10dp"/>
diff --git a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
new file mode 100644
index 0000000..8ebe5f3
--- /dev/null
+++ b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2023 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>
+ <string name="SatelliteControl">SatelliteControl APIs</string>
+ <string name="Datagram">Datagram APIs</string>
+ <string name="Provisioning">Provisioning APIs</string>
+ <string name="MultipleSendReceive">Test multiple poll and send</string>
+ <string name="SendReceive">Send and Receive datagrams</string>
+
+ <string name="enableSatellite">enableSatellite</string>
+ <string name="disableSatellite">disableSatellite</string>
+ <string name="requestIsSatelliteEnabled">requestIsSatelliteEnabled</string>
+ <string name="requestIsDemoModeEnabled">requestIsDemoModeEnabled</string>
+ <string name="requestIsSatelliteSupported">requestIsSatelliteSupported</string>
+ <string name="requestSatelliteCapabilities">requestSatelliteCapabilities</string>
+ <string name="requestIsSatelliteCommunicationAllowedForCurrentLocation">requestIsSatelliteCommunicationAllowedForCurrentLocation</string>
+ <string name="requestTimeForNextSatelliteVisibility">requestTimeForNextSatelliteVisibility</string>
+
+ <string name="pollPendingSatelliteDatagrams">pollPendingSatelliteDatagrams</string>
+ <string name="sendSatelliteDatagram">sendSatelliteDatagram</string>
+ <string name="registerForSatelliteDatagram">registerForSatelliteDatagram</string>
+ <string name="unregisterForSatelliteDatagram">unregisterForSatelliteDatagram</string>
+ <string name="registerForSatelliteModemStateChanged">registerForSatelliteModemStateChanged</string>
+ <string name="unregisterForSatelliteModemStateChanged">unregisterForSatelliteModemStateChanged</string>
+ <string name="showSatelliteModemStateTransition">showSatelliteModemStateTransition</string>
+ <string name="startSatelliteTransmissionUpdates">startSatelliteTransmissionUpdates</string>
+ <string name="stopSatelliteTransmissionUpdates">stopSatelliteTransmissionUpdates</string>
+ <string name="showDatagramSendStateTransition">showDatagramSendStateTransition</string>
+ <string name="showDatagramReceiveStateTransition">showDatagramReceiveStateTransition</string>
+
+ <string name="provisionSatelliteService">provisionSatelliteService</string>
+ <string name="deprovisionSatelliteService">deprovisionSatelliteService</string>
+ <string name="requestIsSatelliteProvisioned">requestIsSatelliteProvisioned</string>
+ <string name="registerForSatelliteProvisionStateChanged">registerForSatelliteProvisionStateChanged</string>
+ <string name="unregisterForSatelliteProvisionStateChanged">unregisterForSatelliteProvisionStateChanged</string>
+ <string name="showCurrentSatelliteProvisionState">showCurrentSatelliteProvisionState</string>
+
+ <string name="multiplePollPendingSatelliteDatagrams">multiplePollPendingSatelliteDatagrams</string>
+ <string name="multipleSendSatelliteDatagram">multipleSendSatelliteDatagram</string>
+ <string name="multipleSendReceiveSatelliteDatagram">multipleSendReceiveSatelliteDatagram</string>
+
+ <string name="sendMessage">sendMessage</string>
+ <string name="receiveMessage">receiveMessage</string>
+
+ <string name="TestSatelliteWrapper">Test Satellite Wrapper</string>
+ <string name="requestNtnSignalStrength">requestNtnSignalStrength</string>
+ <string name="registerForNtnSignalStrengthChanged">registerForNtnSignalStrengthChanged</string>
+ <string name="unregisterForNtnSignalStrengthChanged">unregisterForNtnSignalStrengthChanged</string>
+ <string name="isOnlyNonTerrestrialNetworkSubscription">isOnlyNonTerrestrialNetworkSubscription</string>
+ <string name="registerForSatelliteCapabilitiesChanged">registerForSatelliteCapabilitiesChanged</string>
+ <string name="unregisterForSatelliteCapabilitiesChanged">unregisterForSatelliteCapabilitiesChanged</string>
+
+ <string name="Back">Back</string>
+ <string name="ClearLog">Clear Log</string>
+</resources>
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java
new file mode 100644
index 0000000..97f676f
--- /dev/null
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java
@@ -0,0 +1,440 @@
+/*
+ * Copyright (C) 2023 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.phone.testapps.satellitetestapp;
+
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.telephony.satellite.PointingInfo;
+import android.telephony.satellite.SatelliteDatagram;
+import android.telephony.satellite.SatelliteDatagramCallback;
+import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteStateCallback;
+import android.telephony.satellite.SatelliteTransmissionUpdateCallback;
+import android.telephony.satellite.stub.SatelliteResult;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+
+import java.util.LinkedList;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * Activity related to Datagram APIs.
+ */
+public class Datagram extends Activity {
+
+ private static final String TAG = "Datagram";
+ private static final int MAX_NUMBER_OF_STORED_STATES = 3;
+ private int mTransferState;
+ private int mModemState;
+ LinkedList<Integer> mModemStateQueue = new LinkedList<>();
+ LinkedList<Integer> mSendQueue = new LinkedList<>();
+ LinkedList<Integer> mReceiveQueue = new LinkedList<>();
+
+ private SatelliteManager mSatelliteManager;
+ private SatelliteDatagramCallbackTestApp mDatagramCallback;
+ private SatelliteStateCallbackTestApp mStateCallback;
+ private SatelliteTransmissionUpdateCallbackTestApp mCallback;
+ private android.telephony.satellite.stub.SatelliteDatagram mReceivedDatagram;
+
+ private String mShowSatelliteModemStateTransition;
+ private String mShowDatagramSendStateTransition;
+ private String mShowDatagramReceiveStateTransition;
+ private static final long TIMEOUT = 3000;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mSatelliteManager = getSystemService(SatelliteManager.class);
+ mDatagramCallback = new SatelliteDatagramCallbackTestApp();
+ mStateCallback = new SatelliteStateCallbackTestApp();
+ mCallback = new SatelliteTransmissionUpdateCallbackTestApp();
+
+ mReceivedDatagram = new android.telephony.satellite.stub.SatelliteDatagram();
+
+ setContentView(R.layout.activity_Datagram);
+ findViewById(R.id.startSatelliteTransmissionUpdates)
+ .setOnClickListener(this::startSatelliteTransmissionUpdatesApp);
+ findViewById(R.id.stopSatelliteTransmissionUpdates)
+ .setOnClickListener(this::stopSatelliteTransmissionUpdatesApp);
+ findViewById(R.id.pollPendingSatelliteDatagrams)
+ .setOnClickListener(this::pollPendingSatelliteDatagramsApp);
+ findViewById(R.id.sendSatelliteDatagram)
+ .setOnClickListener(this::sendSatelliteDatagramApp);
+ findViewById(R.id.registerForSatelliteDatagram)
+ .setOnClickListener(this::registerForSatelliteDatagramApp);
+ findViewById(R.id.unregisterForSatelliteDatagram)
+ .setOnClickListener(this::unregisterForSatelliteDatagramApp);
+ findViewById(R.id.showDatagramSendStateTransition)
+ .setOnClickListener(this::showDatagramSendStateTransitionApp);
+ findViewById(R.id.showDatagramReceiveStateTransition)
+ .setOnClickListener(this::showDatagramReceiveStateTransitionApp);
+ findViewById(R.id.registerForSatelliteModemStateChanged)
+ .setOnClickListener(this::registerForSatelliteModemStateChangedApp);
+ findViewById(R.id.unregisterForSatelliteModemStateChanged)
+ .setOnClickListener(this::unregisterForSatelliteModemStateChangedApp);
+ findViewById(R.id.showSatelliteModemStateTransition)
+ .setOnClickListener(this::showSatelliteModemStateTransitionApp);
+
+ findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(Datagram.this, SatelliteTestApp.class));
+ }
+ });
+ }
+
+ protected class SatelliteDatagramCallbackTestApp implements SatelliteDatagramCallback {
+ @Override
+ public void onSatelliteDatagramReceived(long datagramId, SatelliteDatagram datagram,
+ int pendingCount, Consumer<Void> callback) {
+ Log.d(TAG, "onSatelliteDatagramReceived in TestApp: datagramId =" + datagramId
+ + ", datagram =" + datagram + ", pendingCount=" + pendingCount);
+ }
+ }
+
+ protected class SatelliteStateCallbackTestApp implements SatelliteStateCallback {
+ @Override
+ public void onSatelliteModemStateChanged(int state) {
+ mModemState = state;
+ mModemStateQueue.addLast(state);
+ if (mModemStateQueue.size() > MAX_NUMBER_OF_STORED_STATES) {
+ mModemStateQueue.removeFirst();
+ }
+ mShowSatelliteModemStateTransition = getSatelliteModemStateTransition(mModemStateQueue);
+ Log.d(TAG, "onSatelliteModemStateChanged in TestApp: state=" + mModemState);
+ }
+ }
+ protected class SatelliteTransmissionUpdateCallbackTestApp implements
+ SatelliteTransmissionUpdateCallback {
+ @Override
+ public void onSatellitePositionChanged(PointingInfo pointingInfo) {
+ Log.d(TAG, "onSatellitePositionChanged in TestApp: pointingInfo =" + pointingInfo);
+ }
+
+ @Override
+ public void onSendDatagramStateChanged(int state, int sendPendingCount, int errorCode) {
+ mTransferState = state;
+ mSendQueue.addLast(state);
+ if (mSendQueue.size() > MAX_NUMBER_OF_STORED_STATES) {
+ mSendQueue.removeFirst();
+ }
+ mShowDatagramSendStateTransition = getTransferStateTransition(mSendQueue);
+ Log.d(TAG, "onSendDatagramStateChanged in TestApp: state =" + mTransferState
+ + ", sendPendingCount =" + sendPendingCount + ", errorCode=" + errorCode);
+ }
+
+ @Override
+ public void onReceiveDatagramStateChanged(
+ int state, int receivePendingCount, int errorCode) {
+ mTransferState = state;
+ mReceiveQueue.addLast(state);
+ if (mReceiveQueue.size() > MAX_NUMBER_OF_STORED_STATES) {
+ mReceiveQueue.removeFirst();
+ }
+ mShowDatagramReceiveStateTransition = getTransferStateTransition(mReceiveQueue);
+ Log.d(TAG, "onReceiveDatagramStateChanged in TestApp: state=" + mTransferState
+ + ", receivePendingCount=" + receivePendingCount + ", errorCode=" + errorCode);
+ }
+ }
+
+ private void startSatelliteTransmissionUpdatesApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
+ mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, error::offer);
+ TextView showErrorStatusTextView = findViewById(R.id.showErrorStatus);
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ showErrorStatusTextView.setText("Timed out to enable the satellite");
+ return;
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ showErrorStatusTextView.setText("Failed to enable satellite, error = "
+ + SatelliteErrorUtils.mapError(value));
+ return;
+ }
+ } catch (InterruptedException e) {
+ showErrorStatusTextView.setText("Enable SatelliteService exception caught = " + e);
+ return;
+ }
+ error.clear();
+ mSatelliteManager.startSatelliteTransmissionUpdates(Runnable::run, error::offer, mCallback);
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ textView.setText("Timed out to startSatelliteTransmissionUpdates");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ textView.setText("Failed to startSatelliteTransmissionUpdates with error = "
+ + SatelliteErrorUtils.mapError(value));
+ } else {
+ textView.setText("startSatelliteTransmissionUpdates is successful");
+ }
+ } catch (InterruptedException e) {
+ textView.setText("startSatelliteTransmissionUpdates exception caught =" + e);
+ }
+ }
+
+ private void stopSatelliteTransmissionUpdatesApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
+ mSatelliteManager.stopSatelliteTransmissionUpdates(mCallback, Runnable::run, error::offer);
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ textView.setText("Timed out to stopSatelliteTransmissionUpdates");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ textView.setText("Failed to stopSatelliteTransmissionUpdates with error = "
+ + SatelliteErrorUtils.mapError(value));
+ } else {
+ textView.setText("stopSatelliteTransmissionUpdates is successful");
+ }
+ } catch (InterruptedException e) {
+ textView.setText("stopSatelliteTransmissionUpdates exception caught =" + e);
+ }
+ }
+ private void pollPendingSatelliteDatagramsApp(View view) {
+ LinkedBlockingQueue<Integer> resultListener = new LinkedBlockingQueue<>(1);
+ TextView showErrorStatusTextView = findViewById(R.id.showErrorStatus);
+ TextView textView = findViewById(R.id.text_id);
+ mSatelliteManager.setDeviceAlignedWithSatellite(true);
+ if (SatelliteTestApp.getTestSatelliteService() != null) {
+ SatelliteTestApp.getTestSatelliteService().sendOnPendingDatagrams();
+ }
+ mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, resultListener::offer);
+ try {
+ Integer value = resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ showErrorStatusTextView.setText("Timed out to enable the satellite");
+ return;
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ showErrorStatusTextView.setText("Failed to enable satellite, error = "
+ + SatelliteErrorUtils.mapError(value));
+ return;
+ }
+ resultListener.clear();
+ Log.d(TAG, "Poll to check queue is cleared = "
+ + resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {
+ showErrorStatusTextView.setText("Enable SatelliteService exception caught = " + e);
+ return;
+ }
+ mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ try {
+ Integer value = resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ textView.setText("Timed out for poll message");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ textView.setText("Failed to pollPendingSatelliteDatagrams with error = "
+ + SatelliteErrorUtils.mapError(value));
+ } else {
+ textView.setText("pollPendingSatelliteDatagrams is successful");
+ }
+ } catch (InterruptedException e) {
+ textView.setText("pollPendingSatelliteDatagrams exception caught =" + e);
+ }
+ }
+
+ private void sendSatelliteDatagramApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ mSatelliteManager.setDeviceAlignedWithSatellite(true);
+ LinkedBlockingQueue<Integer> resultListener = new LinkedBlockingQueue<>(1);
+ String mText = "This is a test datagram message";
+ SatelliteDatagram datagram = new SatelliteDatagram(mText.getBytes());
+ mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ datagram, true, Runnable::run, resultListener::offer);
+ try {
+ Integer value = resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ textView.setText("Timed out for sendSatelliteDatagram");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ textView.setText("Failed to sendSatelliteDatagram with error = "
+ + SatelliteErrorUtils.mapError(value));
+ } else {
+ textView.setText("sendSatelliteDatagram is successful");
+ }
+ } catch (InterruptedException e) {
+ textView.setText("sendSatelliteDatagram exception caught =" + e);
+ }
+ }
+
+ private void registerForSatelliteDatagramApp(View view) {
+ int result = mSatelliteManager.registerForSatelliteDatagram(Runnable::run,
+ mDatagramCallback);
+ TextView textView = findViewById(R.id.text_id);
+ if (result == 0) {
+ textView.setText("registerForSatelliteDatagram is successful");
+ } else {
+ textView.setText("Status for registerForSatelliteDatagram : "
+ + SatelliteErrorUtils.mapError(result));
+ }
+ }
+
+ private void unregisterForSatelliteDatagramApp(View view) {
+ mSatelliteManager.unregisterForSatelliteDatagram(mDatagramCallback);
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("unregisterForSatelliteDatagram is successful");
+ }
+
+ private void showDatagramSendStateTransitionApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Last datagram send state transition is : "
+ + mShowDatagramSendStateTransition);
+ }
+
+ private void showDatagramReceiveStateTransitionApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Last datagram receive state transition is : "
+ + mShowDatagramReceiveStateTransition);
+ }
+
+ private void registerForSatelliteModemStateChangedApp(View view) {
+ int result = mSatelliteManager.registerForSatelliteModemStateChanged(Runnable::run,
+ mStateCallback);
+ TextView textView = findViewById(R.id.text_id);
+ if (result == 0) {
+ textView.setText("registerForSatelliteModemStateChanged is successful");
+ } else {
+ textView.setText("Status for registerForSatelliteModemStateChanged : "
+ + SatelliteErrorUtils.mapError(result));
+ }
+ }
+
+ private void unregisterForSatelliteModemStateChangedApp(View view) {
+ mSatelliteManager.unregisterForSatelliteModemStateChanged(mStateCallback);
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("unregisterForSatelliteModemStateChanged is successful");
+ }
+
+ private void showSatelliteModemStateTransitionApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText(
+ "Last modem transition state is: " + mShowSatelliteModemStateTransition);
+ }
+
+ private String getSatelliteModemStateName(@SatelliteManager.SatelliteModemState int state) {
+ switch (state) {
+ case SatelliteManager.SATELLITE_MODEM_STATE_IDLE:
+ return "IDLE";
+ case SatelliteManager.SATELLITE_MODEM_STATE_LISTENING:
+ return "LISTENING";
+ case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING:
+ return "DATAGRAM_TRANSFERRING";
+ case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING:
+ return "DATAGRAM_RETRYING";
+ case SatelliteManager.SATELLITE_MODEM_STATE_OFF:
+ return "OFF";
+ case SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE:
+ return "UNAVAILABLE";
+ default: return "UNKNOWN";
+ }
+ }
+
+ private String getSatelliteModemStateTransition(LinkedList<Integer> states) {
+ StringBuilder sb = new StringBuilder();
+ for (int state : states) {
+ sb.append(getSatelliteModemStateName(state));
+ sb.append("=>");
+ }
+ if (!sb.isEmpty()) {
+ sb.delete(sb.length() - 2, sb.length());
+ }
+ return sb.toString();
+ }
+
+ private String getDatagramTransferStateName(
+ @SatelliteManager.SatelliteDatagramTransferState int state) {
+ switch (state) {
+ case SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE: return "IDLE";
+ case SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING: return "SENDING";
+ case SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS: return "SEND_SUCCESS";
+ case SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED: return "SEND_FAILED";
+ case SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING: return "RECEIVING";
+ case SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS: return "RECEIVE_SUCCESS";
+ case SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE: return "RECEIVE_NONE";
+ case SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED: return "RECEIVE_FAILED";
+ default: return "UNKNOWN";
+ }
+ }
+
+ private String getTransferStateTransition(LinkedList<Integer> states) {
+ StringBuilder sb = new StringBuilder();
+ for (int state : states) {
+ sb.append(getDatagramTransferStateName(state));
+ sb.append("=>");
+ }
+ if (!sb.isEmpty()) {
+ sb.delete(sb.length() - 2, sb.length());
+ }
+ return sb.toString();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ SharedPreferences sh = getSharedPreferences("TestSatelliteSharedPref", MODE_PRIVATE);
+ String modemStateTransition = sh.getString("modem_state",
+ mShowSatelliteModemStateTransition);
+ String datagramSendStateTransition = sh.getString("datagram_send_state",
+ mShowDatagramSendStateTransition);
+ String datagramReceiveStateTransition = sh.getString("datagram_receive_state",
+ mShowDatagramReceiveStateTransition);
+
+ // Setting the fetched data
+ mShowSatelliteModemStateTransition = modemStateTransition;
+ mShowDatagramSendStateTransition = datagramSendStateTransition;
+ mShowDatagramReceiveStateTransition = datagramReceiveStateTransition;
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ SharedPreferences sharedPreferences = getSharedPreferences("TestSatelliteSharedPref",
+ MODE_PRIVATE);
+ SharedPreferences.Editor myEdit = sharedPreferences.edit();
+
+ myEdit.putString("modem_state", mShowSatelliteModemStateTransition);
+ myEdit.putString("datagram_send_state", mShowDatagramSendStateTransition);
+ myEdit.putString("datagram_receive_state", mShowDatagramReceiveStateTransition);
+ myEdit.apply();
+ }
+
+ protected void onDestroy() {
+ super.onDestroy();
+ SharedPreferences sharedPreferences = getSharedPreferences("TestSatelliteSharedPref",
+ MODE_PRIVATE);
+ final SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit();
+
+ sharedPrefsEditor.remove("modem_state");
+ sharedPrefsEditor.remove("datagram_send_state");
+ sharedPrefsEditor.remove("datagram_receive_state");
+ sharedPrefsEditor.commit();
+ }
+}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/ILocalSatelliteListener.aidl b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/ILocalSatelliteListener.aidl
new file mode 100644
index 0000000..2c320c8
--- /dev/null
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/ILocalSatelliteListener.aidl
@@ -0,0 +1,67 @@
+
+/*
+ * Copyright (C) 2023 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.phone.testapps.satellitetestapp;
+
+import android.telephony.satellite.stub.SatelliteDatagram;
+
+/**
+ * {@hide}
+ */
+oneway interface ILocalSatelliteListener {
+ /**
+ * Indicates that the remote service - SatelliteModemInterface - has successfully connected to
+ * the TestSatelliteService.
+ */
+ void onRemoteServiceConnected();
+
+ /**
+ * Indicates that TestSatelliteService has just received the request
+ * startSendingSatellitePointingInfo from Telephony.
+ */
+ void onStartSendingSatellitePointingInfo();
+
+ /**
+ * Indicates that TestSatelliteService has just received the request
+ * stopSendingSatellitePointingInfo from Telephony.
+ */
+ void onStopSendingSatellitePointingInfo();
+
+ /**
+ * Indicates that TestSatelliteService has just received the request
+ * pollPendingSatelliteDatagrams from Telephony.
+ */
+ void onPollPendingSatelliteDatagrams();
+
+ /**
+ * Indicates that TestSatelliteService has just received the request
+ * sendSatelliteDatagram from Telephony.
+ */
+ void onSendSatelliteDatagram(in SatelliteDatagram datagram, in boolean isEmergency);
+
+ /**
+ * Indicates that TestSatelliteService has just received the request
+ * requestSatelliteListeningEnabled from Telephony.
+ */
+ void onSatelliteListeningEnabled(in boolean enabled);
+
+ /**
+ * Indicates that TestSatelliteService has just received the request
+ * enableCellularModemWhileSatelliteModeIsOn from Telephony.
+ */
+ void onEnableCellularModemWhileSatelliteModeIsOn(in boolean enable);
+}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/MultipleSendReceive.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/MultipleSendReceive.java
new file mode 100644
index 0000000..3c0b2fd
--- /dev/null
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/MultipleSendReceive.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2023 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.phone.testapps.satellitetestapp;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.telephony.satellite.SatelliteDatagram;
+import android.telephony.satellite.SatelliteManager;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Activity related to Send and Receiving of message APIs for satellite.
+ */
+public class MultipleSendReceive extends Activity {
+
+ private static final String TAG = "MultipleSendReceive";
+
+ private SatelliteManager mSatelliteManager;
+ private android.telephony.satellite.stub.SatelliteDatagram mReceivedDatagram;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mSatelliteManager = getSystemService(SatelliteManager.class);
+ mReceivedDatagram = new android.telephony.satellite.stub.SatelliteDatagram();
+
+ setContentView(R.layout.activity_MultipleSendReceive);
+ findViewById(R.id.multiplePollPendingSatelliteDatagrams)
+ .setOnClickListener(this::multiplePollPendingSatelliteDatagramsApp);
+ findViewById(R.id.multipleSendSatelliteDatagram)
+ .setOnClickListener(this::multipleSendSatelliteDatagramApp);
+ findViewById(R.id.multipleSendReceiveSatelliteDatagram)
+ .setOnClickListener(this::multipleSendReceiveSatelliteDatagramApp);
+ findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MultipleSendReceive.this, SatelliteTestApp.class));
+ }
+ });
+ }
+
+ private void multiplePollPendingSatelliteDatagramsApp(View view) {
+ mSatelliteManager.setDeviceAlignedWithSatellite(true);
+ SatelliteTestApp.getTestSatelliteService().sendOnPendingDatagrams();
+ SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
+ mReceivedDatagram, 4);
+ LinkedBlockingQueue<Integer> resultListener = new LinkedBlockingQueue<>(1);
+ mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, resultListener::offer);
+ mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
+ mReceivedDatagram, 3);
+ mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
+ mReceivedDatagram, 2);
+ mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
+ mReceivedDatagram, 1);
+ mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
+ mReceivedDatagram, 0);
+ mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ try {
+ Integer value = resultListener.poll(1000, TimeUnit.MILLISECONDS);
+ TextView textView = findViewById(R.id.text_id);
+ if (value == 0) {
+ textView.setText("multiplePollPendingSatelliteDatagrams is Successful");
+ } else {
+ textView.setText("Status for multiplePollPendingSatelliteDatagrams : "
+ + SatelliteErrorUtils.mapError(value));
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "exception caught =" + e);
+ }
+ }
+
+
+ private void multipleSendSatelliteDatagramApp(View view) {
+ mSatelliteManager.setDeviceAlignedWithSatellite(true);
+ LinkedBlockingQueue<Integer> resultListener = new LinkedBlockingQueue<>(1);
+ String mText = "This is a test datagram message";
+ SatelliteDatagram datagram = new SatelliteDatagram(mText.getBytes());
+ mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ datagram, true, Runnable::run, resultListener::offer);
+ mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ datagram, true, Runnable::run, resultListener::offer);
+ mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ datagram, true, Runnable::run, resultListener::offer);
+ mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ datagram, true, Runnable::run, resultListener::offer);
+ mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ datagram, true, Runnable::run, resultListener::offer);
+ try {
+ Integer value = resultListener.poll(1000, TimeUnit.MILLISECONDS);
+ TextView textView = findViewById(R.id.text_id);
+ if (value == 0) {
+ textView.setText("multipleSendSatelliteDatagram is Successful");
+ } else {
+ textView.setText("Status for multipleSendSatelliteDatagram : "
+ + SatelliteErrorUtils.mapError(value));
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "exception caught =" + e);
+ }
+ }
+
+ private void multipleSendReceiveSatelliteDatagramApp(View view) {
+ mSatelliteManager.setDeviceAlignedWithSatellite(true);
+ LinkedBlockingQueue<Integer> resultListener = new LinkedBlockingQueue<>(1);
+ mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, resultListener::offer);
+ String mText = "This is a test datagram message";
+ SatelliteDatagram datagram = new SatelliteDatagram(mText.getBytes());
+ mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ datagram, true, Runnable::run, resultListener::offer);
+ SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
+ mReceivedDatagram, 4);
+ mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ datagram, true, Runnable::run, resultListener::offer);
+ SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
+ mReceivedDatagram, 3);
+ mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ datagram, true, Runnable::run, resultListener::offer);
+ SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
+ mReceivedDatagram, 2);
+ mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ datagram, true, Runnable::run, resultListener::offer);
+ SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
+ mReceivedDatagram, 1);
+ mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ datagram, true, Runnable::run, resultListener::offer);
+ SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
+ mReceivedDatagram, 0);
+ try {
+ Integer value = resultListener.poll(1000, TimeUnit.MILLISECONDS);
+ TextView textView = findViewById(R.id.text_id);
+ if (value == 0) {
+ textView.setText("multipleSendReceiveSatelliteDatagram is Successful");
+ } else {
+ textView.setText("Status for multipleSendReceiveSatelliteDatagram : "
+ + SatelliteErrorUtils.mapError(value));
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "exception caught =" + e);
+ }
+ }
+}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Provisioning.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Provisioning.java
new file mode 100644
index 0000000..940435e
--- /dev/null
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Provisioning.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2023 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.phone.testapps.satellitetestapp;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.OutcomeReceiver;
+import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteProvisionStateCallback;
+import android.telephony.satellite.stub.SatelliteResult;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Activity related to Provisioning APIs.
+ */
+public class Provisioning extends Activity {
+
+ private static final String TAG = "Provisioning";
+
+ private boolean mProvisioned = false;
+
+ private SatelliteManager mSatelliteManager;
+ private SatelliteProvisionStateCallbackTestApp mCallback;
+ private static final long TIMEOUT = 3000;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mSatelliteManager = getSystemService(SatelliteManager.class);
+ mCallback = new SatelliteProvisionStateCallbackTestApp();
+
+ setContentView(R.layout.activity_Provisioning);
+ findViewById(R.id.provisionSatelliteService)
+ .setOnClickListener(this::provisionSatelliteServiceApp);
+ findViewById(R.id.deprovisionSatelliteService)
+ .setOnClickListener(this::deprovisionSatelliteServiceApp);
+ findViewById(R.id.requestIsSatelliteProvisioned)
+ .setOnClickListener(this::requestIsSatelliteProvisionedApp);
+ findViewById(R.id.registerForSatelliteProvisionStateChanged)
+ .setOnClickListener(this::registerForSatelliteProvisionStateChangedApp);
+ findViewById(R.id.unregisterForSatelliteProvisionStateChanged)
+ .setOnClickListener(this::unregisterForSatelliteProvisionStateChangedApp);
+ findViewById(R.id.showCurrentSatelliteProvisionState)
+ .setOnClickListener(this::showCurrentSatelliteProvisionStateApp);
+ findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(Provisioning.this, SatelliteTestApp.class));
+ }
+ });
+ }
+
+ protected class SatelliteProvisionStateCallbackTestApp implements
+ SatelliteProvisionStateCallback {
+ @Override
+ public void onSatelliteProvisionStateChanged(boolean provisioned) {
+ mProvisioned = provisioned;
+ Log.d(TAG, "onSatelliteProvisionStateChanged in SatelliteTestApp: provisioned="
+ + mProvisioned);
+ }
+ }
+
+ private void provisionSatelliteServiceApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ CancellationSignal cancellationSignal = new CancellationSignal();
+ LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
+ String mText = "This is test provision data.";
+ byte[] testProvisionData = mText.getBytes();
+ mSatelliteManager.provisionSatelliteService("SATELLITE_TOKEN", testProvisionData,
+ cancellationSignal, Runnable::run, error::offer);
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ textView.setText("Timed out to provision the satellite");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ textView.setText("Failed to provision SatelliteService with error = "
+ + SatelliteErrorUtils.mapError(value));
+ } else {
+ textView.setText("Successfully provisioned the satellite");
+ }
+ } catch (InterruptedException e) {
+ textView.setText("Provision SatelliteService exception caught =" + e);
+ }
+ }
+
+ private void deprovisionSatelliteServiceApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
+ mSatelliteManager.deprovisionSatelliteService("SATELLITE_TOKEN", Runnable::run,
+ error::offer);
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ textView.setText("Timed out to deprovision the satellite");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ textView.setText("Failed to deprovision SatelliteService with error = "
+ + SatelliteErrorUtils.mapError(value));
+ } else {
+ textView.setText("Successfully deprovisioned the satellite");
+ }
+ } catch (InterruptedException e) {
+ textView.setText("Deprovision SatelliteService exception caught =" + e);
+ }
+ }
+
+ private void requestIsSatelliteProvisionedApp(View view) {
+ final AtomicReference<Boolean> enabled = new AtomicReference<>();
+ final AtomicReference<Integer> errorCode = new AtomicReference<>();
+ OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> mReceiver =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Boolean result) {
+ enabled.set(result);
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Status for requestIsSatelliteProvisioned result: "
+ + enabled.get());
+ }
+
+ @Override
+ public void onError(SatelliteManager.SatelliteException exception) {
+ errorCode.set(exception.getErrorCode());
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Status for requestIsSatelliteProvisioned error : "
+ + SatelliteErrorUtils.mapError(errorCode.get()));
+ }
+ };
+ mSatelliteManager.requestIsSatelliteProvisioned(Runnable::run, mReceiver);
+ }
+
+ private void registerForSatelliteProvisionStateChangedApp(View view) {
+ int result = mSatelliteManager.registerForSatelliteProvisionStateChanged(Runnable::run,
+ mCallback);
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Status for registerForSatelliteProvisionStateChanged : "
+ + SatelliteErrorUtils.mapError(result));
+ }
+
+ private void unregisterForSatelliteProvisionStateChangedApp(View view) {
+ mSatelliteManager.unregisterForSatelliteProvisionStateChanged(mCallback);
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("unregisterForSatelliteProvisionStateChanged is successful");
+ }
+
+ private void showCurrentSatelliteProvisionStateApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Current Provision State is " + mProvisioned);
+ }
+
+ // Fetch the stored data in onResume()
+ // Because this is what will be called when the app opens again
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // Fetching the stored data from the SharedPreference
+ SharedPreferences sh = getSharedPreferences("MySharedPref", MODE_PRIVATE);
+ boolean isProvisioned = sh.getBoolean("provision_state", mProvisioned);
+
+ // Setting the fetched data
+ mProvisioned = isProvisioned;
+ }
+
+ // Store the data in the SharedPreference in the onPause() method
+ // When the user closes the application onPause() will be called and data will be stored
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // Creating a shared pref object with a file name "MySharedPref" in private mode
+ SharedPreferences sharedPreferences = getSharedPreferences("MySharedPref", MODE_PRIVATE);
+ SharedPreferences.Editor myEdit = sharedPreferences.edit();
+
+ // write all the data entered by the user in SharedPreference and apply
+ myEdit.putBoolean("provision_state", mProvisioned);
+ myEdit.apply();
+ }
+
+ protected void onDestroy() {
+ super.onDestroy();
+ SharedPreferences sharedPreferences = getSharedPreferences("MySharedPref", MODE_PRIVATE);
+
+ final SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit();
+ sharedPrefsEditor.remove("provision_state");
+ sharedPrefsEditor.commit();
+ }
+}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java
new file mode 100644
index 0000000..4e339a3
--- /dev/null
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2023 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.phone.testapps.satellitetestapp;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.OutcomeReceiver;
+import android.telephony.satellite.SatelliteCapabilities;
+import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.stub.SatelliteResult;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+
+import java.time.Duration;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Activity related to SatelliteControl APIs for satellite.
+ */
+public class SatelliteControl extends Activity {
+
+ private static final long TIMEOUT = 3000;
+
+ private SatelliteManager mSatelliteManager;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mSatelliteManager = getSystemService(SatelliteManager.class);
+
+ setContentView(R.layout.activity_SatelliteControl);
+ findViewById(R.id.enableSatellite)
+ .setOnClickListener(this::enableSatelliteApp);
+ findViewById(R.id.disableSatellite)
+ .setOnClickListener(this::disableSatelliteApp);
+ findViewById(R.id.requestIsSatelliteEnabled)
+ .setOnClickListener(this::requestIsSatelliteEnabledApp);
+ findViewById(R.id.requestIsDemoModeEnabled)
+ .setOnClickListener(this::requestIsDemoModeEnabledApp);
+ findViewById(R.id.requestIsSatelliteSupported)
+ .setOnClickListener(this::requestIsSatelliteSupportedApp);
+ findViewById(R.id.requestSatelliteCapabilities)
+ .setOnClickListener(this::requestSatelliteCapabilitiesApp);
+ findViewById(R.id.requestIsSatelliteCommunicationAllowedForCurrentLocation)
+ .setOnClickListener(
+ this::requestIsSatelliteCommunicationAllowedForCurrentLocationApp);
+ findViewById(R.id.requestTimeForNextSatelliteVisibility)
+ .setOnClickListener(this::requestTimeForNextSatelliteVisibilityApp);
+ findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(SatelliteControl.this, SatelliteTestApp.class));
+ }
+ });
+ }
+
+ private void enableSatelliteApp(View view) {
+ LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
+ mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, error::offer);
+ TextView textView = findViewById(R.id.text_id);
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ textView.setText("Timed out to enable the satellite");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ textView.setText("Failed to enable the satellite, error ="
+ + SatelliteErrorUtils.mapError(value));
+ } else {
+ textView.setText("Successfully enabled the satellite");
+ }
+ } catch (InterruptedException e) {
+ textView.setText("Enable SatelliteService exception caught =" + e);
+ }
+ }
+
+ private void disableSatelliteApp(View view) {
+ LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
+ mSatelliteManager.requestSatelliteEnabled(false, true, Runnable::run, error::offer);
+ TextView textView = findViewById(R.id.text_id);
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ textView.setText("Timed out to disable the satellite");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ textView.setText("Failed to disable the satellite, error ="
+ + SatelliteErrorUtils.mapError(value));
+ } else {
+ textView.setText("Successfully disabled the satellite");
+ }
+ } catch (InterruptedException e) {
+ textView.setText("Disable SatelliteService exception caught =" + e);
+ }
+ }
+
+ private void requestIsSatelliteEnabledApp(View view) {
+ final AtomicReference<Boolean> enabled = new AtomicReference<>();
+ final AtomicReference<Integer> errorCode = new AtomicReference<>();
+ OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Boolean result) {
+ enabled.set(result);
+ TextView textView = findViewById(R.id.text_id);
+ if (enabled.get()) {
+ textView.setText("requestIsSatelliteEnabled is true");
+ } else {
+ textView.setText("Status for requestIsSatelliteEnabled result : "
+ + enabled.get());
+ }
+ }
+
+ @Override
+ public void onError(SatelliteManager.SatelliteException exception) {
+ errorCode.set(exception.getErrorCode());
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Status for requestIsSatelliteEnabled error : "
+ + SatelliteErrorUtils.mapError(errorCode.get()));
+ }
+ };
+ mSatelliteManager.requestIsSatelliteEnabled(Runnable::run, receiver);
+ }
+
+ private void requestIsDemoModeEnabledApp(View view) {
+ final AtomicReference<Boolean> enabled = new AtomicReference<>();
+ final AtomicReference<Integer> errorCode = new AtomicReference<>();
+ OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Boolean result) {
+ enabled.set(result);
+ TextView textView = findViewById(R.id.text_id);
+ if (enabled.get()) {
+ textView.setText("requestIsDemoModeEnabled is true");
+ } else {
+ textView.setText("Status for requestIsDemoModeEnabled result : "
+ + enabled.get());
+ }
+ }
+
+ @Override
+ public void onError(SatelliteManager.SatelliteException exception) {
+ errorCode.set(exception.getErrorCode());
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Status for requestIsDemoModeEnabled error : "
+ + SatelliteErrorUtils.mapError(errorCode.get()));
+ }
+ };
+ mSatelliteManager.requestIsDemoModeEnabled(Runnable::run, receiver);
+ }
+
+ private void requestIsSatelliteSupportedApp(View view) {
+ final AtomicReference<Boolean> enabled = new AtomicReference<>();
+ final AtomicReference<Integer> errorCode = new AtomicReference<>();
+ OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Boolean result) {
+ enabled.set(result);
+ TextView textView = findViewById(R.id.text_id);
+ if (enabled.get()) {
+ textView.setText("requestIsSatelliteSupported is true");
+ } else {
+ textView.setText("Status for requestIsSatelliteSupported result : "
+ + enabled.get());
+ }
+ }
+
+ @Override
+ public void onError(SatelliteManager.SatelliteException exception) {
+ errorCode.set(exception.getErrorCode());
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Status for requestIsSatelliteSupported error : "
+ + SatelliteErrorUtils.mapError(errorCode.get()));
+ }
+ };
+ mSatelliteManager.requestIsSatelliteSupported(Runnable::run, receiver);
+ }
+
+ private void requestSatelliteCapabilitiesApp(View view) {
+ final AtomicReference<SatelliteCapabilities> capabilities = new AtomicReference<>();
+ final AtomicReference<Integer> errorCode = new AtomicReference<>();
+ OutcomeReceiver<SatelliteCapabilities, SatelliteManager.SatelliteException> receiver =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(SatelliteCapabilities result) {
+ capabilities.set(result);
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Status for requestSatelliteCapabilities result: "
+ + capabilities.get());
+ }
+
+ @Override
+ public void onError(SatelliteManager.SatelliteException exception) {
+ errorCode.set(exception.getErrorCode());
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Status for requestSatelliteCapabilities error : "
+ + SatelliteErrorUtils.mapError(errorCode.get()));
+ }
+ };
+ mSatelliteManager.requestSatelliteCapabilities(Runnable::run, receiver);
+ }
+
+ private void requestIsSatelliteCommunicationAllowedForCurrentLocationApp(View view) {
+ final AtomicReference<Boolean> enabled = new AtomicReference<>();
+ final AtomicReference<Integer> errorCode = new AtomicReference<>();
+ String display = "requestIsSatelliteCommunicationAllowedForCurrentLocation";
+ OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Boolean result) {
+ enabled.set(result);
+ TextView textView = findViewById(R.id.text_id);
+ if (enabled.get()) {
+ textView.setText(display + "is true");
+ } else {
+ textView.setText("Status for" + display + "result: " + enabled.get());
+ }
+
+ }
+
+ @Override
+ public void onError(SatelliteManager.SatelliteException exception) {
+ errorCode.set(exception.getErrorCode());
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Status for" + display + "error: "
+ + SatelliteErrorUtils.mapError(errorCode.get()));
+ }
+ };
+ mSatelliteManager.requestIsSatelliteCommunicationAllowedForCurrentLocation(Runnable::run,
+ receiver);
+ }
+
+ private void requestTimeForNextSatelliteVisibilityApp(View view) {
+ final AtomicReference<Duration> nextVisibilityDuration = new AtomicReference<>();
+ final AtomicReference<Integer> errorCode = new AtomicReference<>();
+ OutcomeReceiver<Duration, SatelliteManager.SatelliteException> receiver =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Duration result) {
+ nextVisibilityDuration.set(result);
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Status for requestTimeForNextSatelliteVisibility result : "
+ + result.getSeconds());
+ }
+
+ @Override
+ public void onError(SatelliteManager.SatelliteException exception) {
+ errorCode.set(exception.getErrorCode());
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("Status for requestTimeForNextSatelliteVisibility error : "
+ + SatelliteErrorUtils.mapError(errorCode.get()));
+ }
+ };
+ mSatelliteManager.requestTimeForNextSatelliteVisibility(Runnable::run, receiver);
+ }
+}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteErrorUtils.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteErrorUtils.java
new file mode 100644
index 0000000..ffdabdf
--- /dev/null
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteErrorUtils.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 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.phone.testapps.satellitetestapp;
+
+import android.telephony.satellite.stub.SatelliteResult;
+import android.util.Log;
+
+/**
+ * Utils class for satellite error to display as string in SatelliteTestApp UI.
+ */
+public class SatelliteErrorUtils {
+ private static final String TAG = "SatelliteErrorUtils";
+
+ /**
+ * @param error int from the satellite manager.
+ * @return The converted SatelliteError for the testapp, result of the operation.
+ */
+ public static String mapError(int error) {
+ switch (error) {
+ case SatelliteResult.SATELLITE_RESULT_SUCCESS:
+ return "SATELLITE_RESULT_SUCCESS";
+ case SatelliteResult.SATELLITE_RESULT_ERROR:
+ return "SATELLITE_RESULT_ERROR";
+ case SatelliteResult.SATELLITE_RESULT_SERVER_ERROR:
+ return "SATELLITE_RESULT_SERVER_ERROR";
+ case SatelliteResult.SATELLITE_RESULT_SERVICE_ERROR:
+ return "SATELLITE_RESULT_SERVICE_ERROR";
+ case SatelliteResult.SATELLITE_RESULT_MODEM_ERROR:
+ return "SATELLITE_RESULT_MODEM_ERROR";
+ case SatelliteResult.SATELLITE_RESULT_NETWORK_ERROR:
+ return "SATELLITE_RESULT_NETWORK_ERROR";
+ case SatelliteResult.SATELLITE_RESULT_INVALID_MODEM_STATE:
+ return "SATELLITE_RESULT_INVALID_MODEM_STATE";
+ case SatelliteResult.SATELLITE_RESULT_INVALID_ARGUMENTS:
+ return "SATELLITE_RESULT_INVALID_ARGUMENTS";
+ case SatelliteResult.SATELLITE_RESULT_REQUEST_FAILED:
+ return "SATELLITE_RESULT_REQUEST_FAILED";
+ case SatelliteResult.SATELLITE_RESULT_RADIO_NOT_AVAILABLE:
+ return "SATELLITE_RESULT_RADIO_NOT_AVAILABLE";
+ case SatelliteResult.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED:
+ return "SATELLITE_RESULT_REQUEST_NOT_SUPPORTED";
+ case SatelliteResult.SATELLITE_RESULT_NO_RESOURCES:
+ return "SATELLITE_RESULT_NO_RESOURCES";
+ case SatelliteResult.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED:
+ return "SATELLITE_RESULT_SERVICE_NOT_PROVISIONED";
+ case SatelliteResult.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS:
+ return "SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS";
+ case SatelliteResult.SATELLITE_RESULT_REQUEST_ABORTED:
+ return "SATELLITE_RESULT_REQUEST_ABORTED";
+ case SatelliteResult.SATELLITE_RESULT_ACCESS_BARRED:
+ return "SATELLITE_RESULT_ACCESS_BARRED";
+ case SatelliteResult.SATELLITE_RESULT_NETWORK_TIMEOUT:
+ return "SATELLITE_RESULT_NETWORK_TIMEOUT";
+ case SatelliteResult.SATELLITE_RESULT_NOT_REACHABLE:
+ return "SATELLITE_RESULT_NOT_REACHABLE";
+ case SatelliteResult.SATELLITE_RESULT_NOT_AUTHORIZED:
+ return "SATELLITE_RESULT_NOT_AUTHORIZED";
+ }
+ Log.d(TAG, "Received invalid satellite service error: " + error);
+ return "SATELLITE_RESULT_SERVICE_ERROR";
+ }
+}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
new file mode 100644
index 0000000..ced9a06
--- /dev/null
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2023 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.phone.testapps.satellitetestapp;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.telephony.satellite.stub.SatelliteDatagram;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * SatelliteTestApp main activity to navigate to other APIs related to satellite.
+ */
+public class SatelliteTestApp extends Activity {
+
+ private static final String TAG = "SatelliteTestApp";
+ public static TestSatelliteService sSatelliteService;
+ private final Object mSendDatagramLock = new Object();
+
+ private TestSatelliteServiceConnection mSatelliteServiceConn;
+ private List<SatelliteDatagram> mSentSatelliteDatagrams = new ArrayList<>();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (mSatelliteServiceConn == null) {
+ mSatelliteServiceConn = new TestSatelliteServiceConnection();
+ getBaseContext().bindService(new Intent(getBaseContext(),
+ TestSatelliteService.class), mSatelliteServiceConn, Context.BIND_AUTO_CREATE);
+ }
+
+ setContentView(R.layout.activity_SatelliteTestApp);
+ findViewById(R.id.SatelliteControl).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SatelliteTestApp.this, SatelliteControl.class);
+ startActivity(intent);
+ }
+ });
+ findViewById(R.id.Datagram).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SatelliteTestApp.this, Datagram.class);
+ startActivity(intent);
+ }
+ });
+ findViewById(R.id.Provisioning).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SatelliteTestApp.this, Provisioning.class);
+ startActivity(intent);
+ }
+ });
+ findViewById(R.id.MultipleSendReceive).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SatelliteTestApp.this, MultipleSendReceive.class);
+ startActivity(intent);
+ }
+ });
+ findViewById(R.id.SendReceive).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SatelliteTestApp.this, SendReceive.class);
+ startActivity(intent);
+ }
+ });
+ findViewById(R.id.TestSatelliteWrapper).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SatelliteTestApp.this, TestSatelliteWrapper.class);
+ startActivity(intent);
+ }
+ });
+ }
+
+ private final ILocalSatelliteListener mSatelliteListener =
+ new ILocalSatelliteListener.Stub() {
+ @Override
+ public void onRemoteServiceConnected() {
+ Log.d(TAG, "onRemoteServiceConnected");
+ }
+
+ @Override
+ public void onStartSendingSatellitePointingInfo() {
+ Log.d(TAG, "onStartSendingSatellitePointingInfo");
+ }
+
+ @Override
+ public void onStopSendingSatellitePointingInfo() {
+ Log.d(TAG, "onStopSendingSatellitePointingInfo");
+ }
+
+ @Override
+ public void onPollPendingSatelliteDatagrams() {
+ Log.d(TAG, "onPollPendingSatelliteDatagrams");
+ }
+
+ @Override
+ public void onSendSatelliteDatagram(
+ SatelliteDatagram datagram, boolean isEmergency) {
+ Log.d(TAG, "onSendSatelliteDatagram");
+ synchronized (mSendDatagramLock) {
+ mSentSatelliteDatagrams.add(datagram);
+ }
+ }
+
+ @Override
+ public void onSatelliteListeningEnabled(boolean enable) {
+ Log.d(TAG, "onSatelliteListeningEnabled");
+ }
+
+ @Override
+ public void onEnableCellularModemWhileSatelliteModeIsOn(boolean enable) {
+ Log.d(TAG, "onEnableCellularModemWhileSatelliteModeIsOn");
+ }
+ };
+
+ private class TestSatelliteServiceConnection implements ServiceConnection {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ Log.d(TAG, "onServiceConnected in SatelliteTestApp");
+ sSatelliteService = ((TestSatelliteService.LocalBinder) service).getService();
+ sSatelliteService.setLocalSatelliteListener(mSatelliteListener);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ Log.d(TAG, "onServiceDisconnected in SatelliteTestApp");
+ sSatelliteService = null;
+ }
+ }
+
+ public static TestSatelliteService getTestSatelliteService() {
+ return sSatelliteService;
+ }
+}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SendReceive.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SendReceive.java
new file mode 100644
index 0000000..a64aa5d
--- /dev/null
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SendReceive.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2023 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.phone.testapps.satellitetestapp;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.OutcomeReceiver;
+import android.telephony.satellite.PointingInfo;
+import android.telephony.satellite.SatelliteCapabilities;
+import android.telephony.satellite.SatelliteDatagram;
+import android.telephony.satellite.SatelliteDatagramCallback;
+import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteTransmissionUpdateCallback;
+import android.telephony.satellite.stub.SatelliteResult;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+
+/**
+ * Activity related to Send and Receiving of message APIs for satellite.
+ */
+public class SendReceive extends Activity {
+
+ private static final String TAG = "SendReceive";
+
+ private SatelliteManager mSatelliteManager;
+ private SendReceive.SatelliteDatagramCallbackTestApp mCallback;
+
+ private PointingInfo mPointingInfo;
+ private String mMessageInput = "";
+ private String mMessageOutput = "";
+ private static final long TIMEOUT = 3000;
+
+ private EditText mEnterMessage;
+ private TextView mMessageStatusTextView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mSatelliteManager = getSystemService(SatelliteManager.class);
+ mCallback = new SendReceive.SatelliteDatagramCallbackTestApp();
+
+ setContentView(R.layout.activity_SendReceive);
+ findViewById(R.id.sendMessage).setOnClickListener(this::sendStatusApp);
+ findViewById(R.id.receiveMessage).setOnClickListener(this::receiveStatusApp);
+ mEnterMessage = (EditText) findViewById(R.id.enterText);
+ mMessageStatusTextView = findViewById(R.id.messageStatus);
+ findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(SendReceive.this, SatelliteTestApp.class));
+ }
+ });
+ }
+
+ protected class SatelliteDatagramCallbackTestApp implements SatelliteDatagramCallback {
+ @Override
+ public void onSatelliteDatagramReceived(long datagramId, SatelliteDatagram datagram,
+ int pendingCount, Consumer<Void> callback) {
+ Log.d(TAG, "onSatelliteDatagramReceived in TestApp: datagramId =" + datagramId
+ + ", datagram =" + datagram + ", pendingCount=" + pendingCount);
+ mMessageStatusTextView.setText("Last received satellite message is = "
+ + new String(datagram.getSatelliteDatagram()));
+ }
+ }
+
+ protected class SatelliteTransmissionUpdateCallbackTestApp implements
+ SatelliteTransmissionUpdateCallback {
+ @Override
+ public void onSatellitePositionChanged(PointingInfo pointingInfo) {
+ mPointingInfo = pointingInfo;
+ Log.d(TAG, "onSatellitePositionChanged in TestApp for sendReceive: pointingInfo = "
+ + mPointingInfo);
+ TextView satellitePositionTextView = findViewById(R.id.satellitePosition);
+ satellitePositionTextView.setText("Successfully received the satellite position : "
+ + mPointingInfo);
+ }
+
+ @Override
+ public void onSendDatagramStateChanged(int state, int sendPendingCount, int errorCode) {
+ Log.d(TAG, "onSendDatagramStateChanged in TestApp for sendReceive: state = "
+ + state + ", sendPendingCount =" + sendPendingCount + ", errorCode="
+ + errorCode);
+ }
+
+ @Override
+ public void onReceiveDatagramStateChanged(
+ int state, int receivePendingCount, int errorCode) {
+ Log.d(TAG, "onReceiveDatagramStateChanged in TestApp for sendReceive: state = "
+ + state + ", " + "receivePendingCount=" + receivePendingCount + ", errorCode="
+ + errorCode);
+ }
+ }
+
+ private void sendStatusApp(View view) {
+ LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
+ mMessageInput = mEnterMessage.getText().toString();
+ mMessageOutput = mEnterMessage.getText().toString();
+ byte[] testProvisionData = mMessageInput.getBytes();
+ setupForTransferringDatagram(testProvisionData);
+
+ SatelliteDatagram datagram = new SatelliteDatagram(mMessageInput.getBytes());
+ //Sending Message
+ mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ datagram, true, Runnable::run, error::offer);
+ TextView messageStatusTextView = findViewById(R.id.messageStatus);
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ messageStatusTextView.setText("Timed out to send the message");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ messageStatusTextView.setText("Failed to send the message, error ="
+ + SatelliteErrorUtils.mapError(value));
+ } else {
+ messageStatusTextView.setText("Successfully sent the message = "
+ + mEnterMessage.getText().toString());
+ }
+ } catch (InterruptedException e) {
+ messageStatusTextView.setText("sendSatelliteDatagram exception caught = " + e);
+ }
+ }
+
+ private void receiveStatusApp(View view) {
+ LinkedBlockingQueue<Integer> resultListener = new LinkedBlockingQueue<>(1);
+ byte[] testProvisionData = mMessageOutput.getBytes();
+ setupForTransferringDatagram(testProvisionData);
+
+ int result = mSatelliteManager.registerForSatelliteDatagram(Runnable::run, mCallback);
+ TextView showErrorStatusTextView = findViewById(R.id.showErrorStatus);
+ if (result != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ showErrorStatusTextView.setText("Status for registerForSatelliteDatagram : "
+ + SatelliteErrorUtils.mapError(result));
+ }
+ if (SatelliteTestApp.getTestSatelliteService() != null) {
+ SatelliteTestApp.getTestSatelliteService().sendOnPendingDatagrams();
+ }
+ mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, resultListener::offer);
+ try {
+ Integer value = resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ showErrorStatusTextView.setText("Timed out to enable the satellite");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ showErrorStatusTextView.setText("Failed to enable satellite, error = "
+ + SatelliteErrorUtils.mapError(value));
+ return;
+ }
+ resultListener.clear();
+ } catch (InterruptedException e) {
+ showErrorStatusTextView.setText("Enable SatelliteService exception caught = " + e);
+ return;
+ }
+
+ mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ try {
+ Integer value = resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ mMessageStatusTextView.setText("Timed out to poll pending messages");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ mMessageStatusTextView.setText("Failed to poll pending messages, error = "
+ + SatelliteErrorUtils.mapError(value));
+ } else {
+ mMessageStatusTextView.setText("Successfully polled pending messages");
+ }
+ } catch (InterruptedException e) {
+ mMessageStatusTextView.setText("pollPendingSatelliteDatagrams exception caught = " + e);
+ }
+ }
+
+ private void setupForTransferringDatagram(byte[] provisionData) {
+ TextView showErrorStatusTextView = findViewById(R.id.showErrorStatus);
+ CancellationSignal cancellationSignal = new CancellationSignal();
+ LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
+
+ //Provisioning
+ mSatelliteManager.provisionSatelliteService("SATELLITE_TOKEN", provisionData,
+ cancellationSignal, Runnable::run, error::offer);
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ showErrorStatusTextView.setText("Timed out to provision the satellite");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ showErrorStatusTextView.setText("Failed to provision satellite, error = "
+ + SatelliteErrorUtils.mapError(value));
+ return;
+ }
+ } catch (InterruptedException e) {
+ showErrorStatusTextView.setText("Provision SatelliteService exception caught = " + e);
+ return;
+ }
+ error.clear();
+
+ //Static position of device
+ final AtomicReference<SatelliteCapabilities> capabilities = new AtomicReference<>();
+ final AtomicReference<Integer> errorCode = new AtomicReference<>();
+ OutcomeReceiver<SatelliteCapabilities, SatelliteManager.SatelliteException> receiver =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(SatelliteCapabilities result) {
+ capabilities.set(result);
+ TextView devicePositionTextView = findViewById(R.id.devicePosition);
+ devicePositionTextView.setText("Successfully receive the device position : "
+ + capabilities.get().getAntennaPositionMap());
+ }
+
+ @Override
+ public void onError(SatelliteManager.SatelliteException exception) {
+ errorCode.set(exception.getErrorCode());
+ TextView devicePositionTextView = findViewById(R.id.devicePosition);
+ devicePositionTextView.setText("Unable to fetch device position error is : "
+ + SatelliteErrorUtils.mapError(errorCode.get()));
+ }
+ };
+ mSatelliteManager.requestSatelliteCapabilities(Runnable::run, receiver);
+
+ //Satellite Position
+ SatelliteTransmissionUpdateCallbackTestApp callback =
+ new SatelliteTransmissionUpdateCallbackTestApp();
+ mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, error::offer);
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ showErrorStatusTextView.setText("Timed out to enable the satellite");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ showErrorStatusTextView.setText("Failed to enable satellite, error = "
+ + SatelliteErrorUtils.mapError(value));
+ return;
+ }
+ } catch (InterruptedException e) {
+ showErrorStatusTextView.setText("Enable SatelliteService exception caught = " + e);
+ return;
+ }
+ error.clear();
+
+ mSatelliteManager.startSatelliteTransmissionUpdates(Runnable::run, error::offer, callback);
+ // Position update
+ android.telephony.satellite.stub.PointingInfo pointingInfo =
+ new android.telephony.satellite.stub.PointingInfo();
+ pointingInfo.satelliteAzimuth = 50.5f;
+ pointingInfo.satelliteElevation = 20.36f;
+ if (SatelliteTestApp.getTestSatelliteService() != null) {
+ SatelliteTestApp.getTestSatelliteService().sendOnSatellitePositionChanged(pointingInfo);
+ }
+ TextView satellitePositionTextView = findViewById(R.id.satellitePosition);
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ satellitePositionTextView.setText("Failed to register for satellite transmission"
+ + "updates");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ satellitePositionTextView.setText("Failed to register for satellite transmission "
+ + "updates, error = " + SatelliteErrorUtils.mapError(value));
+ }
+ } catch (InterruptedException e) {
+ satellitePositionTextView.setText("startSatelliteTransmissionUpdates exception caught ="
+ + e);
+ }
+ //Device is aligned with the satellite for demo mode
+ mSatelliteManager.setDeviceAlignedWithSatellite(true);
+ }
+}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java
new file mode 100644
index 0000000..929a2e5
--- /dev/null
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java
@@ -0,0 +1,528 @@
+/*
+ * Copyright (C) 2023 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.phone.testapps.satellitetestapp;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.telephony.IBooleanConsumer;
+import android.telephony.IIntegerConsumer;
+import android.telephony.satellite.AntennaDirection;
+import android.telephony.satellite.AntennaPosition;
+import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer;
+import android.telephony.satellite.stub.ISatelliteListener;
+import android.telephony.satellite.stub.NTRadioTechnology;
+import android.telephony.satellite.stub.PointingInfo;
+import android.telephony.satellite.stub.SatelliteCapabilities;
+import android.telephony.satellite.stub.SatelliteDatagram;
+import android.telephony.satellite.stub.SatelliteImplBase;
+import android.telephony.satellite.stub.SatelliteModemState;
+import android.telephony.satellite.stub.SatelliteResult;
+import android.telephony.satellite.stub.SatelliteService;
+import android.util.Log;
+
+import com.android.internal.util.FunctionalUtils;
+import com.android.telephony.Rlog;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Test service for Satellite to verify end to end flow via testapp.
+ */
+public class TestSatelliteService extends SatelliteImplBase {
+ private static final String TAG = "TestSatelliteService";
+
+ // Hardcoded values below
+ private static final int SATELLITE_ALWAYS_VISIBLE = 0;
+ /** SatelliteCapabilities constant indicating that the radio technology is proprietary. */
+ private static final int[] SUPPORTED_RADIO_TECHNOLOGIES =
+ new int[]{NTRadioTechnology.PROPRIETARY};
+ /** SatelliteCapabilities constant indicating that pointing to satellite is required. */
+ private static final boolean POINTING_TO_SATELLITE_REQUIRED = true;
+ /** SatelliteCapabilities constant indicating the maximum number of characters per datagram. */
+ private static final int MAX_BYTES_PER_DATAGRAM = 339;
+ /** SatelliteCapabilities constant keys which are used to fill mAntennaPositionMap. */
+ private static final int[] ANTENNA_POSITION_KEYS = new int[]{
+ SatelliteManager.DISPLAY_MODE_OPENED, SatelliteManager.DISPLAY_MODE_CLOSED};
+ /** SatelliteCapabilities constant values which are used to fill mAntennaPositionMap. */
+ private static final AntennaPosition[] ANTENNA_POSITION_VALUES = new AntennaPosition[] {
+ new AntennaPosition(new AntennaDirection(1, 1, 1),
+ SatelliteManager.DEVICE_HOLD_POSITION_PORTRAIT),
+ new AntennaPosition(new AntennaDirection(2, 2, 2),
+ SatelliteManager.DEVICE_HOLD_POSITION_LANDSCAPE_LEFT)
+ };
+
+ @NonNull
+ private final Map<IBinder, ISatelliteListener> mRemoteListeners = new HashMap<>();
+ @Nullable private ILocalSatelliteListener mLocalListener;
+ private final LocalBinder mBinder = new LocalBinder();
+ @SatelliteResult
+ private int mErrorCode = SatelliteResult.SATELLITE_RESULT_SUCCESS;
+ private final AtomicBoolean mShouldNotifyRemoteServiceConnected =
+ new AtomicBoolean(false);
+
+ // For local access of this Service.
+ class LocalBinder extends Binder {
+ TestSatelliteService getService() {
+ return TestSatelliteService.this;
+ }
+ }
+
+ private boolean mIsCommunicationAllowedInLocation;
+ private boolean mIsEnabled;
+ private boolean mIsProvisioned;
+ private boolean mIsSupported;
+ private int mModemState;
+ private boolean mIsCellularModemEnabledMode;
+
+ /**
+ * Create TestSatelliteService using the Executor specified for methods being called from
+ * the framework.
+ *
+ * @param executor The executor for the framework to use when executing satellite methods.
+ */
+ public TestSatelliteService(@NonNull Executor executor) {
+ super(executor);
+ mIsCommunicationAllowedInLocation = true;
+ mIsEnabled = false;
+ mIsProvisioned = false;
+ mIsSupported = true;
+ mModemState = SatelliteModemState.SATELLITE_MODEM_STATE_OFF;
+ mIsCellularModemEnabledMode = false;
+ }
+
+ /**
+ * Zero-argument constructor to prevent service binding exception.
+ */
+ public TestSatelliteService() {
+ this(Runnable::run);
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (SatelliteService.SERVICE_INTERFACE.equals(intent.getAction())) {
+ logd("Remote service bound");
+ return getBinder();
+ }
+ logd("Local service bound");
+ return mBinder;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ logd("onCreate");
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ logd("onDestroy");
+ }
+
+ @Override
+ public void setSatelliteListener(@NonNull ISatelliteListener listener) {
+ logd("setSatelliteListener");
+ mRemoteListeners.put(listener.asBinder(), listener);
+ notifyRemoteServiceConnected();
+ }
+
+ @Override
+ public void requestSatelliteListeningEnabled(boolean enabled, int timeout,
+ @NonNull IIntegerConsumer errorCallback) {
+ logd("requestSatelliteListeningEnabled: mErrorCode=" + mErrorCode);
+
+ if (mLocalListener != null) {
+ runWithExecutor(() -> mLocalListener.onSatelliteListeningEnabled(enabled));
+ } else {
+ loge("requestSatelliteListeningEnabled: mLocalListener is null");
+ }
+
+ if (!verifySatelliteModemState(errorCallback)) {
+ return;
+ }
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ return;
+ }
+
+ if (enabled) {
+ updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_LISTENING);
+ } else {
+ updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_IDLE);
+ }
+ runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
+ }
+
+ @Override
+ public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
+ @NonNull IIntegerConsumer errorCallback) {
+ logd("requestSatelliteEnabled: mErrorCode=" + mErrorCode + " enable = " + enableSatellite);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ return;
+ }
+
+ if (enableSatellite) {
+ enableSatellite(errorCallback);
+ } else {
+ disableSatellite(errorCallback);
+ }
+ }
+
+ private void enableSatellite(@NonNull IIntegerConsumer errorCallback) {
+ mIsEnabled = true;
+ updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_IDLE);
+ runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
+ }
+
+ private void disableSatellite(@NonNull IIntegerConsumer errorCallback) {
+ mIsEnabled = false;
+ updateSatelliteModemState(SatelliteModemState.SATELLITE_MODEM_STATE_OFF);
+ runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
+ }
+
+ @Override
+ public void requestIsSatelliteEnabled(@NonNull IIntegerConsumer errorCallback,
+ @NonNull IBooleanConsumer callback) {
+ logd("requestIsSatelliteEnabled: mErrorCode=" + mErrorCode);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ return;
+ }
+ runWithExecutor(() -> callback.accept(mIsEnabled));
+ }
+
+ @Override
+ public void requestIsSatelliteSupported(@NonNull IIntegerConsumer errorCallback,
+ @NonNull IBooleanConsumer callback) {
+ logd("requestIsSatelliteSupported");
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ return;
+ }
+ runWithExecutor(() -> callback.accept(mIsSupported));
+ }
+
+ @Override
+ public void requestSatelliteCapabilities(@NonNull IIntegerConsumer errorCallback,
+ @NonNull ISatelliteCapabilitiesConsumer callback) {
+ logd("requestSatelliteCapabilities: mErrorCode=" + mErrorCode);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ return;
+ }
+
+ SatelliteCapabilities capabilities = new SatelliteCapabilities();
+ capabilities.supportedRadioTechnologies = SUPPORTED_RADIO_TECHNOLOGIES;
+ capabilities.isPointingRequired = POINTING_TO_SATELLITE_REQUIRED;
+ capabilities.maxBytesPerOutgoingDatagram = MAX_BYTES_PER_DATAGRAM;
+ capabilities.antennaPositionKeys = ANTENNA_POSITION_KEYS;
+ capabilities.antennaPositionValues = ANTENNA_POSITION_VALUES;
+ runWithExecutor(() -> callback.accept(capabilities));
+ }
+
+ @Override
+ public void startSendingSatellitePointingInfo(@NonNull IIntegerConsumer errorCallback) {
+ logd("startSendingSatellitePointingInfo: mErrorCode=" + mErrorCode);
+ if (!verifySatelliteModemState(errorCallback)) {
+ if (mLocalListener != null) {
+ runWithExecutor(() -> mLocalListener.onStartSendingSatellitePointingInfo());
+ } else {
+ loge("startSendingSatellitePointingInfo: mLocalListener is null");
+ }
+ return;
+ }
+
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ } else {
+ runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
+ }
+
+ if (mLocalListener != null) {
+ runWithExecutor(() -> mLocalListener.onStartSendingSatellitePointingInfo());
+ } else {
+ loge("startSendingSatellitePointingInfo: mLocalListener is null");
+ }
+ }
+
+ @Override
+ public void stopSendingSatellitePointingInfo(@NonNull IIntegerConsumer errorCallback) {
+ logd("stopSendingSatellitePointingInfo: mErrorCode=" + mErrorCode);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ } else {
+ runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
+ }
+
+ if (mLocalListener != null) {
+ runWithExecutor(() -> mLocalListener.onStopSendingSatellitePointingInfo());
+ } else {
+ loge("stopSendingSatellitePointingInfo: mLocalListener is null");
+ }
+ }
+
+ @Override
+ public void provisionSatelliteService(@NonNull String token, @NonNull byte[] provisionData,
+ @NonNull IIntegerConsumer errorCallback) {
+ logd("provisionSatelliteService: mErrorCode=" + mErrorCode);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ return;
+ }
+ runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
+ updateSatelliteProvisionState(true);
+ }
+
+ @Override
+ public void deprovisionSatelliteService(@NonNull String token,
+ @NonNull IIntegerConsumer errorCallback) {
+ logd("deprovisionSatelliteService: mErrorCode=" + mErrorCode);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ return;
+ }
+ runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
+ updateSatelliteProvisionState(false);
+ }
+
+ @Override
+ public void requestIsSatelliteProvisioned(@NonNull IIntegerConsumer errorCallback,
+ @NonNull IBooleanConsumer callback) {
+ logd("requestIsSatelliteProvisioned: mErrorCode=" + mErrorCode);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ return;
+ }
+ runWithExecutor(() -> callback.accept(mIsProvisioned));
+ }
+
+ @Override
+ public void pollPendingSatelliteDatagrams(@NonNull IIntegerConsumer errorCallback) {
+ logd("pollPendingSatelliteDatagrams: mErrorCode=" + mErrorCode);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ } else {
+ runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
+ }
+
+ if (mLocalListener != null) {
+ runWithExecutor(() -> mLocalListener.onPollPendingSatelliteDatagrams());
+ } else {
+ loge("pollPendingSatelliteDatagrams: mLocalListener is null");
+ }
+ }
+
+ @Override
+ public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isEmergency,
+ @NonNull IIntegerConsumer errorCallback) {
+ logd("sendSatelliteDatagram: mErrorCode=" + mErrorCode);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ } else {
+ runWithExecutor(() -> errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
+ }
+
+ if (mLocalListener != null) {
+ runWithExecutor(() -> mLocalListener.onSendSatelliteDatagram(datagram, isEmergency));
+ } else {
+ loge("sendSatelliteDatagram: mLocalListener is null");
+ }
+ }
+
+ @Override
+ public void requestSatelliteModemState(@NonNull IIntegerConsumer errorCallback,
+ @NonNull IIntegerConsumer callback) {
+ logd("requestSatelliteModemState: mErrorCode=" + mErrorCode);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ return;
+ }
+ runWithExecutor(() -> callback.accept(mModemState));
+ }
+
+ @Override
+ public void requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ @NonNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback) {
+ logd("requestIsSatelliteCommunicationAllowedForCurrentLocation: mErrorCode=" + mErrorCode);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ return;
+ }
+
+ if (mIsCommunicationAllowedInLocation) {
+ runWithExecutor(() -> callback.accept(true));
+ } else {
+ runWithExecutor(() -> callback.accept(false));
+ }
+ }
+
+ @Override
+ public void requestTimeForNextSatelliteVisibility(@NonNull IIntegerConsumer errorCallback,
+ @NonNull IIntegerConsumer callback) {
+ logd("requestTimeForNextSatelliteVisibility: mErrorCode=" + mErrorCode);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> errorCallback.accept(mErrorCode));
+ return;
+ }
+ runWithExecutor(() -> callback.accept(SATELLITE_ALWAYS_VISIBLE));
+ }
+
+ public void setLocalSatelliteListener(@NonNull ILocalSatelliteListener listener) {
+ logd("setLocalSatelliteListener: listener=" + listener);
+ mLocalListener = listener;
+ if (mShouldNotifyRemoteServiceConnected.get()) {
+ notifyRemoteServiceConnected();
+ }
+ }
+
+ public void setErrorCode(@SatelliteResult int errorCode) {
+ logd("setErrorCode: errorCode=" + errorCode);
+ mErrorCode = errorCode;
+ }
+
+ public void setSatelliteSupport(boolean supported) {
+ logd("setSatelliteSupport: supported=" + supported);
+ mIsSupported = supported;
+ }
+
+ public void sendOnSatelliteDatagramReceived(SatelliteDatagram datagram, int pendingCount) {
+ logd("sendOnSatelliteDatagramReceived");
+ mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
+ listener.onSatelliteDatagramReceived(datagram, pendingCount)));
+ }
+
+ public void sendOnPendingDatagrams() {
+ logd("sendOnPendingDatagrams");
+ mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
+ listener.onPendingDatagrams()));
+ }
+
+ public void sendOnSatellitePositionChanged(PointingInfo pointingInfo) {
+ logd("sendOnSatellitePositionChanged");
+ mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
+ listener.onSatellitePositionChanged(pointingInfo)));
+ }
+
+ /**
+ * Helper method to verify that the satellite modem is properly configured to receive
+ * requests.
+ *
+ * @param errorCallback The callback to notify of any errors preventing satellite requests.
+ * @return {@code true} if the satellite modem is configured to receive requests and
+ * {@code false} if it is not.
+ */
+ private boolean verifySatelliteModemState(@NonNull IIntegerConsumer errorCallback) {
+ if (!mIsSupported) {
+ runWithExecutor(() -> errorCallback.accept(
+ SatelliteResult.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED));
+ return false;
+ }
+ if (!mIsProvisioned) {
+ runWithExecutor(() -> errorCallback.accept(
+ SatelliteResult.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED));
+ return false;
+ }
+ if (!mIsEnabled) {
+ runWithExecutor(() -> errorCallback.accept(
+ SatelliteResult.SATELLITE_RESULT_INVALID_MODEM_STATE));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Update the satellite modem state and notify listeners if it changed.
+ *
+ * @param modemState The {@link SatelliteModemState} to update.
+ */
+ private void updateSatelliteModemState(int modemState) {
+ if (modemState == mModemState) {
+ return;
+ }
+ if (mIsCellularModemEnabledMode
+ && modemState == SatelliteModemState.SATELLITE_MODEM_STATE_OFF) {
+ logd("Not updating the Modem state to Off as it is in CellularModemEnabledMode");
+ return;
+ }
+ mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
+ listener.onSatelliteModemStateChanged(modemState)));
+ mModemState = modemState;
+ }
+
+ /**
+ * Update the satellite provision state and notify listeners if it changed.
+ *
+ * @param isProvisioned {@code true} if the satellite is currently provisioned and
+ * {@code false} if it is not.
+ */
+ private void updateSatelliteProvisionState(boolean isProvisioned) {
+ logd("updateSatelliteProvisionState: isProvisioned=" + isProvisioned
+ + ", mIsProvisioned=" + mIsProvisioned);
+ if (isProvisioned == mIsProvisioned) {
+ return;
+ }
+ mIsProvisioned = isProvisioned;
+ logd("updateSatelliteProvisionState: mRemoteListeners.size=" + mRemoteListeners.size());
+ mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
+ listener.onSatelliteProvisionStateChanged(mIsProvisioned)));
+ }
+
+ /**
+ * Execute the given runnable using the executor that this service was created with.
+ *
+ * @param r A runnable that can throw an exception.
+ */
+ private void runWithExecutor(@NonNull FunctionalUtils.ThrowingRunnable r) {
+ mExecutor.execute(() -> Binder.withCleanCallingIdentity(r));
+ }
+
+ private void notifyRemoteServiceConnected() {
+ logd("notifyRemoteServiceConnected");
+ if (mLocalListener != null) {
+ runWithExecutor(() -> mLocalListener.onRemoteServiceConnected());
+ mShouldNotifyRemoteServiceConnected.set(false);
+ } else {
+ mShouldNotifyRemoteServiceConnected.set(true);
+ }
+ }
+
+ /**
+ * Log the message to the radio buffer with {@code DEBUG} priority.
+ *
+ * @param log The message to log.
+ */
+ private static void logd(@NonNull String log) {
+ Rlog.d(TAG, log);
+ }
+
+ /**
+ * Log with error attribute
+ *
+ * @param s is string log
+ */
+ protected void loge(@NonNull String s) {
+ Log.e(TAG, s);
+ }
+}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
new file mode 100644
index 0000000..20efecb
--- /dev/null
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2023 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.phone.testapps.satellitetestapp;
+
+import android.annotation.NonNull;
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.OutcomeReceiver;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.satellite.wrapper.NtnSignalStrengthCallbackWrapper;
+import android.telephony.satellite.wrapper.NtnSignalStrengthWrapper;
+import android.telephony.satellite.wrapper.SatelliteCapabilitiesCallbackWrapper;
+import android.telephony.satellite.wrapper.SatelliteManagerWrapper;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+
+/**
+ * Activity related to SatelliteControl APIs for satellite.
+ */
+public class TestSatelliteWrapper extends Activity {
+ private static final String TAG = "TestSatelliteWrapper";
+ ArrayList<String> mLogMessages = new ArrayList<>();
+ ArrayAdapter<String> mAdapter;
+
+ private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
+ private SatelliteManagerWrapper mSatelliteManagerWrapper;
+ private NtnSignalStrengthCallback mNtnSignalStrengthCallback = null;
+ private SatelliteCapabilitiesCallbackWrapper mSatelliteCapabilitiesCallback;
+ private SubscriptionManager mSubscriptionManager;
+
+ private ListView mLogListView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mSatelliteManagerWrapper = SatelliteManagerWrapper.getInstance(this);
+ mSubscriptionManager = getSystemService(SubscriptionManager.class);
+
+ setContentView(R.layout.activity_TestSatelliteWrapper);
+ findViewById(R.id.requestNtnSignalStrength)
+ .setOnClickListener(this::requestNtnSignalStrength);
+ findViewById(R.id.registerForNtnSignalStrengthChanged)
+ .setOnClickListener(this::registerForNtnSignalStrengthChanged);
+ findViewById(R.id.unregisterForNtnSignalStrengthChanged)
+ .setOnClickListener(this::unregisterForNtnSignalStrengthChanged);
+ findViewById(R.id.isOnlyNonTerrestrialNetworkSubscription)
+ .setOnClickListener(this::isOnlyNonTerrestrialNetworkSubscription);
+ findViewById(R.id.registerForSatelliteCapabilitiesChanged)
+ .setOnClickListener(this::registerForSatelliteCapabilitiesChanged);
+ findViewById(R.id.unregisterForSatelliteCapabilitiesChanged)
+ .setOnClickListener(this::unregisterForSatelliteCapabilitiesChanged);
+ findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(TestSatelliteWrapper.this, SatelliteTestApp.class));
+ }
+ });
+ findViewById(R.id.ClearLog).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ clearListView();
+ }
+ });
+
+ mLogListView = findViewById(R.id.logListView);
+ mAdapter = new ArrayAdapter<>(this, R.layout.log_textview, mLogMessages);
+ mLogListView.setAdapter(mAdapter);
+
+ addLogMessage("TestSatelliteWrapper.onCreate()");
+ }
+
+
+ private void clearListView() {
+ mLogMessages.clear();
+ mAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ if (mSatelliteManagerWrapper != null) {
+ if (mNtnSignalStrengthCallback != null) {
+ Log.d(TAG, "unregisterForNtnSignalStrengthChanged()");
+ mSatelliteManagerWrapper.unregisterForNtnSignalStrengthChanged(
+ mNtnSignalStrengthCallback);
+ }
+ if (mSatelliteCapabilitiesCallback != null) {
+ Log.d(TAG, "unregisterForSatelliteCapabilitiesChanged()");
+ mSatelliteManagerWrapper.unregisterForSatelliteCapabilitiesChanged(
+ mSatelliteCapabilitiesCallback);
+ }
+ }
+ }
+
+ private void requestNtnSignalStrength(View view) {
+ addLogMessage("requestNtnSignalStrength");
+ Log.d(TAG, "requestNtnSignalStrength");
+ OutcomeReceiver<NtnSignalStrengthWrapper,
+ SatelliteManagerWrapper.SatelliteExceptionWrapper> receiver =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(NtnSignalStrengthWrapper level) {
+ if (level != null) {
+ addLogMessage("requestNtnSignalStrength level is " + level.getLevel());
+ }
+ }
+
+ @Override
+ public void onError(
+ SatelliteManagerWrapper.SatelliteExceptionWrapper exception) {
+ if (exception != null) {
+ String onError = "requestNtnSignalStrength exception: "
+ + translateResultCodeToString(exception.getErrorCode());
+ Log.d(TAG, onError);
+ addLogMessage(onError);
+ }
+ }
+ };
+
+ mSatelliteManagerWrapper.requestNtnSignalStrength(mExecutor, receiver);
+ }
+
+ private void registerForNtnSignalStrengthChanged(View view) {
+ addLogMessage("registerForNtnSignalStrengthChanged");
+ Log.d(TAG, "registerForNtnSignalStrengthChanged()");
+ if (mNtnSignalStrengthCallback == null) {
+ Log.d(TAG, "create new NtnSignalStrengthCallback instance.");
+ mNtnSignalStrengthCallback = new NtnSignalStrengthCallback();
+ }
+ int result = mSatelliteManagerWrapper.registerForNtnSignalStrengthChanged(mExecutor,
+ mNtnSignalStrengthCallback);
+ if (result != SatelliteManagerWrapper.SATELLITE_RESULT_SUCCESS) {
+ String onError = translateResultCodeToString(result);
+ Log.d(TAG, onError);
+ addLogMessage(onError);
+ mNtnSignalStrengthCallback = null;
+ }
+ }
+
+ private void unregisterForNtnSignalStrengthChanged(View view) {
+ addLogMessage("unregisterForNtnSignalStrengthChanged");
+ Log.d(TAG, "unregisterForNtnSignalStrengthChanged()");
+ if (mNtnSignalStrengthCallback != null) {
+ mSatelliteManagerWrapper.unregisterForNtnSignalStrengthChanged(
+ mNtnSignalStrengthCallback);
+ mNtnSignalStrengthCallback = null;
+ addLogMessage("mNtnSignalStrengthCallback was unregistered");
+ } else {
+ addLogMessage("mNtnSignalStrengthCallback is null, ignored.");
+ }
+ }
+
+ private void isOnlyNonTerrestrialNetworkSubscription(View view) {
+ addLogMessage("isOnlyNonTerrestrialNetworkSubscription");
+ Log.d(TAG, "isOnlyNonTerrestrialNetworkSubscription()");
+ List<SubscriptionInfo> infoList = mSubscriptionManager.getAvailableSubscriptionInfoList();
+ List<Integer> subIdList = infoList.stream()
+ .map(SubscriptionInfo::getSubscriptionId)
+ .toList();
+
+ Map<Integer, Boolean> resultMap = subIdList.stream().collect(
+ Collectors.toMap(
+ id -> id,
+ id -> {
+ boolean result = mSatelliteManagerWrapper
+ .isOnlyNonTerrestrialNetworkSubscription(id);
+ addLogMessage("SatelliteManagerWrapper"
+ + ".isOnlyNonTerrestrialNetworkSubscription(" + id + ")");
+ return result;
+ }
+ ));
+
+ for (Map.Entry<Integer, Boolean> entry : resultMap.entrySet()) {
+ int subId = entry.getKey();
+ boolean result = entry.getValue();
+ addLogMessage("Subscription ID: " + subId + ", Result: " + result);
+ }
+ }
+
+ private void registerForSatelliteCapabilitiesChanged(View view) {
+ addLogMessage("registerForSatelliteCapabilitiesChanged");
+ Log.d(TAG, "registerForSatelliteCapabilitiesChanged()");
+ if (mSatelliteCapabilitiesCallback == null) {
+ mSatelliteCapabilitiesCallback =
+ SatelliteCapabilities -> {
+ String message = "Received SatelliteCapabillities : "
+ + SatelliteCapabilities;
+ Log.d(TAG, message);
+ runOnUiThread(() -> addLogMessage(message));
+ };
+ }
+
+ int result = mSatelliteManagerWrapper.registerForSatelliteCapabilitiesChanged(mExecutor,
+ mSatelliteCapabilitiesCallback);
+ if (result != SatelliteManagerWrapper.SATELLITE_RESULT_SUCCESS) {
+ String onError = translateResultCodeToString(result);
+ Log.d(TAG, onError);
+ addLogMessage(onError);
+ mSatelliteCapabilitiesCallback = null;
+ }
+ }
+
+ private void unregisterForSatelliteCapabilitiesChanged(View view) {
+ addLogMessage("unregisterForSatelliteCapabilitiesChanged");
+ Log.d(TAG, "unregisterForSatelliteCapabilitiesChanged()");
+ if (mSatelliteCapabilitiesCallback != null) {
+ mSatelliteManagerWrapper.unregisterForSatelliteCapabilitiesChanged(
+ mSatelliteCapabilitiesCallback);
+ mSatelliteCapabilitiesCallback = null;
+ addLogMessage("mSatelliteCapabilitiesCallback was unregistered");
+ } else {
+ addLogMessage("mSatelliteCapabilitiesCallback is null, ignored.");
+ }
+ }
+
+ public class NtnSignalStrengthCallback implements NtnSignalStrengthCallbackWrapper {
+ @Override
+ public void onNtnSignalStrengthChanged(
+ @NonNull NtnSignalStrengthWrapper ntnSignalStrength) {
+ String message = "Received NTN SignalStrength : " + ntnSignalStrength.getLevel();
+ Log.d(TAG, message);
+ runOnUiThread(() -> addLogMessage(message));
+ }
+ }
+
+ private String translateResultCodeToString(
+ @SatelliteManagerWrapper.SatelliteResult int result) {
+ switch (result) {
+ case SatelliteManagerWrapper.SATELLITE_RESULT_SUCCESS:
+ return "SATELLITE_RESULT_SUCCESS";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_ERROR:
+ return "SATELLITE_RESULT_ERROR";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_SERVER_ERROR:
+ return "SATELLITE_RESULT_SERVER_ERROR";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_SERVICE_ERROR:
+ return "SATELLITE_RESULT_SERVICE_ERROR";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_MODEM_ERROR:
+ return "SATELLITE_RESULT_MODEM_ERROR";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_NETWORK_ERROR:
+ return "SATELLITE_RESULT_NETWORK_ERROR";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_INVALID_TELEPHONY_STATE:
+ return "SATELLITE_RESULT_INVALID_TELEPHONY_STATE";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_INVALID_MODEM_STATE:
+ return "SATELLITE_RESULT_INVALID_MODEM_STATE";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_INVALID_ARGUMENTS:
+ return "SATELLITE_RESULT_INVALID_ARGUMENTS";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_REQUEST_FAILED:
+ return "SATELLITE_RESULT_REQUEST_FAILED";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_RADIO_NOT_AVAILABLE:
+ return "SATELLITE_RESULT_RADIO_NOT_AVAILABLE";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED:
+ return "SATELLITE_RESULT_REQUEST_NOT_SUPPORTED";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_NO_RESOURCES:
+ return "SATELLITE_RESULT_NO_RESOURCES";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED:
+ return "SATELLITE_RESULT_SERVICE_NOT_PROVISIONED";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS:
+ return "SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_REQUEST_ABORTED:
+ return "SATELLITE_RESULT_REQUEST_ABORTED";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_ACCESS_BARRED:
+ return "SATELLITE_RESULT_ACCESS_BARRED";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_NETWORK_TIMEOUT:
+ return "SATELLITE_RESULT_NETWORK_TIMEOUT";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_NOT_REACHABLE:
+ return "SATELLITE_RESULT_NOT_REACHABLE";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_NOT_AUTHORIZED:
+ return "SATELLITE_RESULT_NOT_AUTHORIZED";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_NOT_SUPPORTED:
+ return "SATELLITE_RESULT_NOT_SUPPORTED";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_REQUEST_IN_PROGRESS:
+ return "SATELLITE_RESULT_REQUEST_IN_PROGRESS";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_MODEM_BUSY:
+ return "SATELLITE_RESULT_MODEM_BUSY";
+ default:
+ return "INVALID CODE: " + result;
+ }
+ }
+
+ private void addLogMessage(String message) {
+ mLogMessages.add(message);
+ mAdapter.notifyDataSetChanged();
+ mLogListView.setSelection(mAdapter.getCount() - 1);
+ }
+}
diff --git a/tests/Android.bp b/tests/Android.bp
index 08cac05..d2288d0 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -38,6 +38,7 @@
instrumentation_for: "TeleService",
static_libs: [
+ "frameworks-base-testutils",
"androidx.test.core",
"androidx.test.espresso.core",
"androidx.test.ext.junit",
@@ -45,9 +46,10 @@
"mockito-target-minus-junit4",
"telephony-common-testing",
"testng",
- "truth-prebuilt",
+ "truth",
"testables",
"platform-compat-test-rules",
+ "flag-junit",
],
test_suites: [
diff --git a/tests/src/com/android/phone/CarrierConfigLoaderTest.java b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
index b6f8ed8..bd2e4f7 100644
--- a/tests/src/com/android/phone/CarrierConfigLoaderTest.java
+++ b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
@@ -40,8 +40,10 @@
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.PermissionEnforcer;
import android.os.PersistableBundle;
import android.os.UserHandle;
+import android.os.test.FakePermissionEnforcer;
import android.service.carrier.CarrierIdentifier;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
@@ -97,10 +99,17 @@
private HandlerThread mHandlerThread;
private TestableLooper mTestableLooper;
+ // The AIDL stub will use PermissionEnforcer to check permission from the caller.
+ private FakePermissionEnforcer mFakePermissionEnforcer = new FakePermissionEnforcer();
+
@Before
public void setUp() throws Exception {
super.setUp();
MockitoAnnotations.initMocks(this);
+ doReturn(Context.PERMISSION_ENFORCER_SERVICE).when(mContext).getSystemServiceName(
+ eq(PermissionEnforcer.class));
+ doReturn(mFakePermissionEnforcer).when(mContext).getSystemService(
+ eq(Context.PERMISSION_ENFORCER_SERVICE));
replaceInstance(SubscriptionManagerService.class, "sInstance", null,
mSubscriptionManagerService);
@@ -142,6 +151,9 @@
@After
public void tearDown() throws Exception {
mContext.revokeAllPermissions();
+ mFakePermissionEnforcer.revoke(android.Manifest.permission.DUMP);
+ mFakePermissionEnforcer.revoke(android.Manifest.permission.MODIFY_PHONE_STATE);
+ mFakePermissionEnforcer.revoke(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
mTestableLooper.destroy();
mHandlerThread.quit();
super.tearDown();
@@ -164,7 +176,7 @@
*/
@Test
public void testUpdateConfigForPhoneId_invalidPhoneId() throws Exception {
- mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+ mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
assertThrows(IllegalArgumentException.class,
() -> mCarrierConfigLoader.updateConfigForPhoneId(
@@ -182,7 +194,7 @@
if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
return;
}
- mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+ mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
doNothing().when(mContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class));
// Prepare a cached config to fetch from xml
@@ -215,7 +227,7 @@
if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
return;
}
- mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+ mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
// Prepare to make sure we can save the config into the XML file which used as cache
doReturn(PLATFORM_CARRIER_CONFIG_PACKAGE).when(mTelephonyManager)
@@ -252,7 +264,7 @@
*/
@Test
public void testOverrideConfig_invalidSubId() throws Exception {
- mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+ mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
assertThrows(IllegalArgumentException.class, () -> mCarrierConfigLoader.overrideConfig(
SubscriptionManager.INVALID_SUBSCRIPTION_ID, new PersistableBundle(), false));
@@ -267,7 +279,7 @@
if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
return;
}
- mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+ mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
mCarrierConfigLoader.overrideConfig(DEFAULT_SUB_ID, null /*overrides*/,
false/*persistent*/);
@@ -288,7 +300,7 @@
if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
return;
}
- mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+ mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
PersistableBundle config = getTestConfig();
mCarrierConfigLoader.overrideConfig(DEFAULT_SUB_ID, config /*overrides*/,
@@ -308,7 +320,7 @@
*/
@Test
public void testNotifyConfigChangedForSubId_invalidSubId() throws Exception {
- mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+ mFakePermissionEnforcer.grant(STUB_PERMISSION_ENABLE_ALL);
assertThrows(IllegalArgumentException.class,
() -> mCarrierConfigLoader.notifyConfigChangedForSubId(
@@ -346,7 +358,7 @@
*/
@Test
public void testGetDefaultCarrierServicePackageName_withPermission() {
- mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+ mFakePermissionEnforcer.grant(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
assertThat(mCarrierConfigLoader.getDefaultCarrierServicePackageName())
.isEqualTo(PLATFORM_CARRIER_CONFIG_PACKAGE);
@@ -417,7 +429,7 @@
@Test
public void testMultiSimConfigChanged() throws Exception {
replaceInstance(TelephonyManager.class, "sInstance", null, mTelephonyManager);
- mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+ mFakePermissionEnforcer.grant(android.Manifest.permission.MODIFY_PHONE_STATE);
// Changed from 1 to 2.
doReturn(2).when(mTelephonyManager).getActiveModemCount();
diff --git a/tests/src/com/android/phone/NotificationMgrTest.java b/tests/src/com/android/phone/NotificationMgrTest.java
index e009446..98c6a4a 100644
--- a/tests/src/com/android/phone/NotificationMgrTest.java
+++ b/tests/src/com/android/phone/NotificationMgrTest.java
@@ -631,6 +631,7 @@
MOBILE_NETWORK_SELECTION_PACKAGE);
when(mApp.getString(R.string.mobile_network_settings_class)).thenReturn(
MOBILE_NETWORK_SELECTION_CLASS);
+ when(mSubscriptionManager.isActiveSubId(anyInt())).thenReturn(true);
}
private void moveTimeForward(long seconds) {
diff --git a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
index e702279..150703d 100644
--- a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
+++ b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
@@ -34,6 +34,8 @@
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
+import android.permission.flags.Flags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.RadioAccessFamily;
import android.telephony.TelephonyManager;
@@ -44,9 +46,11 @@
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -66,10 +70,14 @@
PhoneGlobals mPhoneGlobals;
@Mock
Phone mPhone;
+ @Mock
+ FeatureFlags mFeatureFlags;
@Mock
private SubscriptionManagerService mSubscriptionManagerService;
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Before
@UiThreadTest
public void setUp() throws Exception {
@@ -78,7 +86,7 @@
// global singleton, but the context that is passed in is unused if the phone app is already
// alive on a test devices. You must use the spy to mock behavior. Mocks stemming from the
// passed context will remain unused.
- mPhoneInterfaceManager = spy(PhoneInterfaceManager.init(mPhoneGlobals));
+ mPhoneInterfaceManager = spy(PhoneInterfaceManager.init(mPhoneGlobals, mFeatureFlags));
doReturn(mSubscriptionManagerService).when(mPhoneInterfaceManager)
.getSubscriptionManagerService();
TelephonyManager.setupISubForTest(mSubscriptionManagerService);
@@ -283,4 +291,72 @@
mPhoneInterfaceManager.getCarrierRestrictionStatus(mIIntegerConsumer,
"com.test.package");
}
+
+ @Test
+ public void notifyEnableDataWithAppOps_enableByUser_doNoteOp() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER);
+ String packageName = "INVALID_PACKAGE";
+ String error = "";
+ try {
+ mPhoneInterfaceManager.setDataEnabledForReason(1,
+ TelephonyManager.DATA_ENABLED_REASON_USER, true, packageName);
+ } catch (SecurityException expected) {
+ // The test doesn't have access to note the op, but we're just interested that it makes
+ // the attempt.
+ error = expected.getMessage();
+ }
+
+ String appop = "ENABLE_MOBILE_DATA_BY_USER";
+ assertTrue("expected error to contain " + packageName + " but it didn't: " + error,
+ error.contains(packageName));
+ assertTrue("expected error to contain " + appop + " but it didn't: " + error,
+ error.contains(appop));
+ }
+
+ @Test
+ public void notifyEnableDataWithAppOps_enableByCarrier_doNotNoteOp() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER);
+ String packageName = "INVALID_PACKAGE";
+ String error = "";
+ try {
+ mPhoneInterfaceManager.setDataEnabledForReason(1,
+ TelephonyManager.DATA_ENABLED_REASON_CARRIER, true, packageName);
+ } catch (SecurityException expected) {
+ // The test doesn't have access to note the op, but we're just interested that it makes
+ // the attempt.
+ error = expected.getMessage();
+ }
+ assertEquals("Expected error to be empty, was " + error, error, "");
+ }
+
+ @Test
+ public void notifyEnableDataWithAppOps_disableByUser_doNotNoteOp() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER);
+ String packageName = "INVALID_PACKAGE";
+ String error = "";
+ try {
+ mPhoneInterfaceManager.setDataEnabledForReason(1,
+ TelephonyManager.DATA_ENABLED_REASON_USER, false, packageName);
+ } catch (SecurityException expected) {
+ // The test doesn't have access to note the op, but we're just interested that it makes
+ // the attempt.
+ error = expected.getMessage();
+ }
+ assertEquals("Expected error to be empty, was " + error, error, "");
+ }
+
+ @Test
+ public void notifyEnableDataWithAppOps_noPackageNameAndEnableByUser_doNotnoteOp() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER);
+ String error = "";
+ try {
+ mPhoneInterfaceManager.setDataEnabledForReason(1,
+ TelephonyManager.DATA_ENABLED_REASON_USER, false, null);
+ } catch (SecurityException expected) {
+ // The test doesn't have access to note the op, but we're just interested that it makes
+ // the attempt.
+ error = expected.getMessage();
+ }
+ assertEquals("Expected error to be empty, was " + error, error, "");
+ }
}
diff --git a/tests/src/com/android/phone/slice/SlicePurchaseControllerTest.java b/tests/src/com/android/phone/slice/SlicePurchaseControllerTest.java
index b2a4a9f..5637c3a 100644
--- a/tests/src/com/android/phone/slice/SlicePurchaseControllerTest.java
+++ b/tests/src/com/android/phone/slice/SlicePurchaseControllerTest.java
@@ -34,6 +34,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -50,6 +51,9 @@
import android.telephony.TelephonyManager;
import android.telephony.data.NetworkSliceInfo;
import android.telephony.data.NetworkSlicingConfig;
+import android.telephony.data.RouteSelectionDescriptor;
+import android.telephony.data.TrafficDescriptor;
+import android.telephony.data.UrspRule;
import android.testing.TestableLooper;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -58,6 +62,7 @@
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.data.DataSettingsManager;
+import com.android.internal.telephony.flags.FeatureFlags;
import org.junit.Before;
import org.junit.Test;
@@ -66,7 +71,9 @@
import org.mockito.Mockito;
import java.time.LocalDate;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
@RunWith(AndroidJUnit4.class)
@@ -86,6 +93,7 @@
private static final long THROTTLE_TIMEOUT = 4000;
@Mock Phone mPhone;
+ @Mock FeatureFlags mFeatureFlags;
@Mock CarrierConfigManager mCarrierConfigManager;
@Mock CommandsInterface mCommandsInterface;
@Mock ServiceState mServiceState;
@@ -147,7 +155,7 @@
// create a spy to mock final PendingIntent methods
SlicePurchaseController slicePurchaseController =
- new SlicePurchaseController(mPhone, mHandler.getLooper());
+ new SlicePurchaseController(mPhone, mFeatureFlags, mHandler.getLooper());
mSlicePurchaseController = spy(slicePurchaseController);
doReturn(null).when(mSlicePurchaseController).createPendingIntent(
anyString(), anyInt(), anyBoolean());
@@ -578,7 +586,7 @@
intent.putExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY);
intent.putExtra(SlicePurchaseController.EXTRA_FAILURE_CODE,
- SlicePurchaseController.FAILURE_CODE_SERVER_UNREACHABLE);
+ SlicePurchaseController.FAILURE_CODE_CARRIER_URL_UNAVAILABLE);
mContext.getBroadcastReceiver().onReceive(mContext, intent);
mTestableLooper.processAllMessages();
assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_ERROR, mResult);
@@ -619,6 +627,7 @@
public void testPurchasePremiumCapabilityResultNotDefaultDataSubscriptionResponse() {
sendValidPurchaseRequest();
+ // broadcast NOT_DEFAULT_DATA_SUBSCRIPTION response from slice purchase application
Intent intent = new Intent();
intent.setAction("com.android.phone.slice.action."
+ "SLICE_PURCHASE_APP_RESPONSE_NOT_DEFAULT_DATA_SUBSCRIPTION");
@@ -636,6 +645,35 @@
}
@Test
+ public void testPurchasePremiumCapabilityResultNotificationsDisabled() {
+ doReturn(true).when(mFeatureFlags).slicingAdditionalErrorCodes();
+ sendValidPurchaseRequest();
+
+ // broadcast NOTIFICATIONS_DISABLED response from slice purchase application
+ Intent intent = new Intent();
+ intent.setAction("com.android.phone.slice.action."
+ + "SLICE_PURCHASE_APP_RESPONSE_NOTIFICATIONS_DISABLED");
+ intent.putExtra(SlicePurchaseController.EXTRA_PHONE_ID, PHONE_ID);
+ intent.putExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY);
+ mContext.getBroadcastReceiver().onReceive(mContext, intent);
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED, mResult);
+
+ // retry to verify throttled
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, mResult);
+
+ // retry to verify unthrottled
+ mTestableLooper.moveTimeForward(THROTTLE_TIMEOUT);
+ mTestableLooper.processAllMessages();
+
+ testPurchasePremiumCapabilityResultSuccess();
+ }
+
+ @Test
public void testPurchasePremiumCapabilityResultNotificationThrottled() {
mSlicePurchaseController.setLocalDate(LocalDate.of(YEAR, MONTH, DATE));
mSlicePurchaseController.updateNotificationCounts();
@@ -670,6 +708,69 @@
assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, mResult);
}
+ @Test
+ public void testIsSlicingConfigActive_emptyUrspRules() {
+ int capability = TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY;
+ NetworkSliceInfo sliceInfo = createNetworkSliceInfo(
+ getRandomSliceServiceType(capability), true);
+ NetworkSlicingConfig slicingConfig = new NetworkSlicingConfig(
+ Collections.emptyList(), Collections.singletonList(sliceInfo));
+ mSlicePurchaseController.setSlicingConfig(slicingConfig);
+
+ assertFalse(mSlicePurchaseController.isSlicingConfigActive(capability));
+ }
+
+ @Test
+ public void testIsSlicingConfigActive_noMatchingTrafficDescriptor() {
+ int capability = TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY;
+ NetworkSliceInfo sliceInfo = createNetworkSliceInfo(
+ getRandomSliceServiceType(capability), true);
+ TrafficDescriptor trafficDescriptor = createTrafficDescriptor("ENTERPRISE");
+ RouteSelectionDescriptor routeSelectionDescriptor = createRouteSelectionDescriptor(
+ Collections.singletonList(sliceInfo));
+ NetworkSlicingConfig slicingConfig = createNetworkSlicingConfig(
+ Collections.singletonList(sliceInfo),
+ Collections.singletonList(trafficDescriptor),
+ Collections.singletonList(routeSelectionDescriptor));
+ mSlicePurchaseController.setSlicingConfig(slicingConfig);
+
+ assertFalse(mSlicePurchaseController.isSlicingConfigActive(capability));
+ }
+
+ @Test
+ public void testIsSlicingConfigActive_multipleElements() {
+ int capability = TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY;
+ NetworkSliceInfo sliceInfo1 = createNetworkSliceInfo(
+ getRandomSliceServiceType(SlicePurchaseController.PREMIUM_CAPABILITY_INVALID),
+ false);
+ NetworkSliceInfo sliceInfo2 = createNetworkSliceInfo(
+ getRandomSliceServiceType(capability), true);
+ List<NetworkSliceInfo> sliceInfos = new ArrayList<>();
+ sliceInfos.add(sliceInfo1);
+ sliceInfos.add(sliceInfo2);
+
+ TrafficDescriptor trafficDescriptor1 = createTrafficDescriptor("ENTERPRISE");
+ TrafficDescriptor trafficDescriptor2 = createTrafficDescriptor(
+ SlicePurchaseController.getAppId(capability));
+ List<TrafficDescriptor> trafficDescriptors = new ArrayList<>();
+ trafficDescriptors.add(trafficDescriptor1);
+ trafficDescriptors.add(trafficDescriptor2);
+
+ RouteSelectionDescriptor routeSelectionDescriptor1 = createRouteSelectionDescriptor(
+ Collections.emptyList());
+ RouteSelectionDescriptor routeSelectionDescriptor2 = createRouteSelectionDescriptor(
+ sliceInfos);
+ List<RouteSelectionDescriptor> routeSelectionDescriptors = new ArrayList<>();
+ routeSelectionDescriptors.add(routeSelectionDescriptor1);
+ routeSelectionDescriptors.add(routeSelectionDescriptor2);
+
+ NetworkSlicingConfig slicingConfig = createNetworkSlicingConfig(
+ sliceInfos, trafficDescriptors, routeSelectionDescriptors);
+ mSlicePurchaseController.setSlicingConfig(slicingConfig);
+
+ assertTrue(mSlicePurchaseController.isSlicingConfigActive(capability));
+ }
+
private void completeSuccessfulPurchase() {
sendValidPurchaseRequest();
@@ -726,7 +827,7 @@
mEntitlementResponse.mEntitlementStatus =
PremiumNetworkEntitlementResponse.PREMIUM_NETWORK_ENTITLEMENT_STATUS_ENABLED;
mEntitlementResponse.mProvisionStatus =
- PremiumNetworkEntitlementResponse.PREMIUM_NETWORK_PROVISION_STATUS_PROVISIONED;
+ PremiumNetworkEntitlementResponse.PREMIUM_NETWORK_PROVISION_STATUS_NOT_PROVISIONED;
// send purchase request
mSlicePurchaseController.purchasePremiumCapability(
@@ -744,18 +845,61 @@
}
private void sendNetworkSlicingConfig(int capability, boolean configActive) {
- int sliceServiceType = capability == TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY
- ? NetworkSliceInfo.SLICE_SERVICE_TYPE_URLLC
- : NetworkSliceInfo.SLICE_SERVICE_TYPE_NONE;
- NetworkSliceInfo sliceInfo = new NetworkSliceInfo.Builder()
- .setStatus(configActive ? NetworkSliceInfo.SLICE_STATUS_ALLOWED
- : NetworkSliceInfo.SLICE_STATUS_UNKNOWN)
- .setSliceServiceType(sliceServiceType)
- .build();
- NetworkSlicingConfig slicingConfig = new NetworkSlicingConfig(Collections.emptyList(),
+ NetworkSliceInfo sliceInfo = createNetworkSliceInfo(
+ getRandomSliceServiceType(capability), configActive);
+ TrafficDescriptor trafficDescriptor = createTrafficDescriptor(
+ SlicePurchaseController.getAppId(capability));
+ RouteSelectionDescriptor routeSelectionDescriptor = createRouteSelectionDescriptor(
Collections.singletonList(sliceInfo));
+ NetworkSlicingConfig slicingConfig = createNetworkSlicingConfig(
+ Collections.singletonList(sliceInfo),
+ Collections.singletonList(trafficDescriptor),
+ Collections.singletonList(routeSelectionDescriptor));
mSlicePurchaseController.obtainMessage(2 /* EVENT_SLICING_CONFIG_CHANGED */,
new AsyncResult(null, slicingConfig, null)).sendToTarget();
mTestableLooper.processAllMessages();
}
+
+ @NetworkSliceInfo.SliceServiceType private int getRandomSliceServiceType(
+ @TelephonyManager.PremiumCapability int capability) {
+ for (int sliceServiceType : SlicePurchaseController.getSliceServiceTypes(capability)) {
+ // Get a random valid sst from the set
+ return sliceServiceType;
+ }
+ return NetworkSliceInfo.SLICE_SERVICE_TYPE_NONE;
+ }
+
+ @NonNull private NetworkSliceInfo createNetworkSliceInfo(
+ @NetworkSliceInfo.SliceServiceType int sliceServiceType, boolean active) {
+ return new NetworkSliceInfo.Builder()
+ .setStatus(active ? NetworkSliceInfo.SLICE_STATUS_ALLOWED
+ : NetworkSliceInfo.SLICE_STATUS_UNKNOWN)
+ .setSliceServiceType(sliceServiceType)
+ .build();
+ }
+
+ @NonNull private TrafficDescriptor createTrafficDescriptor(@NonNull String appId) {
+ TrafficDescriptor.OsAppId osAppId = new TrafficDescriptor.OsAppId(
+ TrafficDescriptor.OsAppId.ANDROID_OS_ID, appId);
+ return new TrafficDescriptor.Builder()
+ .setOsAppId(osAppId.getBytes())
+ .build();
+ }
+
+ @NonNull private RouteSelectionDescriptor createRouteSelectionDescriptor(
+ @NonNull List<NetworkSliceInfo> sliceInfos) {
+ return new RouteSelectionDescriptor(
+ RouteSelectionDescriptor.MIN_ROUTE_PRECEDENCE,
+ RouteSelectionDescriptor.SESSION_TYPE_IPV4,
+ RouteSelectionDescriptor.ROUTE_SSC_MODE_1,
+ sliceInfos, Collections.emptyList());
+ }
+
+ @NonNull private NetworkSlicingConfig createNetworkSlicingConfig(
+ @NonNull List<NetworkSliceInfo> sliceInfos,
+ @NonNull List<TrafficDescriptor> trafficDescriptors,
+ @NonNull List<RouteSelectionDescriptor> routeSelectionDescriptors) {
+ UrspRule urspRule = new UrspRule(0, trafficDescriptors, routeSelectionDescriptors);
+ return new NetworkSlicingConfig(Collections.singletonList(urspRule), sliceInfos);
+ }
}
diff --git a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
index 969622a..16a5cdb 100644
--- a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
+++ b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
@@ -22,6 +22,10 @@
import static junit.framework.Assert.assertNotNull;
import static junit.framework.TestCase.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -33,6 +37,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.TelephonyTestBase;
+import com.android.internal.telephony.CallFailCause;
import com.android.internal.telephony.GsmCdmaPhone;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
@@ -42,7 +47,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.Mockito;
import java.util.Locale;
@@ -60,11 +64,18 @@
@Mock
private GsmCdmaPhone mMockPhone;
+ private final FlagsAdapter mFeatureFlags = new FlagsAdapter(){
+ @Override
+ public boolean doNotOverridePreciseLabel() {
+ return true;
+ }
+ };
+
@Before
public void setUp() throws Exception {
super.setUp();
// objects that call static getInstance()
- mMockPhone = Mockito.mock(GsmCdmaPhone.class);
+ mMockPhone = mock(GsmCdmaPhone.class);
mContext = InstrumentationRegistry.getTargetContext();
// set mocks
setSinglePhone();
@@ -91,7 +102,7 @@
@Test
public void testDefaultDisconnectCauseBehaviorForCauseNotInCarrierBusyToneArray() {
android.telecom.DisconnectCause tcCause = DisconnectCauseUtil.toTelecomDisconnectCause(
- DisconnectCause.ERROR_UNSPECIFIED, EMPTY_STRING, PHONE_ID);
+ DisconnectCause.ERROR_UNSPECIFIED, -1, EMPTY_STRING, PHONE_ID, null, mFeatureFlags);
// CODE
assertEquals(android.telecom.DisconnectCause.ERROR, tcCause.getCode());
// LABEL
@@ -101,29 +112,143 @@
}
/**
- * Simulate a Carrier classifying the DisconnectCause.ERROR_UNSPECIFIED as a
- * DisconnectCause.BUSY. The code, label, and tone should match DisconnectCause.BUSY.
+ * verify that if a precise label is given Telephony, the label is not overridden by Telecom
*/
@Test
- public void testCarrierSetDisconnectCauseInBusyToneArray() {
- int[] carrierBusyArr = {DisconnectCause.BUSY, DisconnectCause.ERROR_UNSPECIFIED};
+ public void testDefaultPhoneConfig_NoPreciseLabelGiven() {
+ android.telecom.DisconnectCause tcCause =
+ DisconnectCauseUtil.toTelecomDisconnectCause(DisconnectCause.BUSY,
+ -1 /* precise label is NOT given */,
+ EMPTY_STRING, PHONE_ID, null /* carrier config is NOT set */,
+ mFeatureFlags);
+ assertBusyCauseWithTargetLabel(R.string.callFailed_userBusy, tcCause);
+ }
+
+ /**
+ * verify that if a precise label is given Telephony, the label is not overridden by Telecom
+ */
+ @Test
+ public void testDefaultPhoneConfig_PreciseLabelProvided() {
+ android.telecom.DisconnectCause tcCause =
+ DisconnectCauseUtil.toTelecomDisconnectCause(DisconnectCause.BUSY,
+ CallFailCause.USER_BUSY /* Telephony defined a precise label */,
+ EMPTY_STRING, PHONE_ID, null /* carrier config is NOT set */,
+ mFeatureFlags);
+ // Note: The precise label should not be overridden even though the carrier defined
+ // the cause to play a busy tone
+ assertBusyCauseWithTargetLabel(R.string.clh_callFailed_user_busy_txt, tcCause);
+ }
+
+ /**
+ * special case: The Carrier has re-defined a disconnect code that should play a busy tone.
+ * Thus, the code, label, and tone should be remapped.
+ * <p>
+ * <p>
+ * Verify that if the disconnect cause is in the carrier busy tone array that the expected
+ * label, tone, and code are returned.
+ */
+ @Test
+ public void testCarrierSetBusyToneArray_NoPreciseLabelGiven() {
+ android.telecom.DisconnectCause tcCause =
+ DisconnectCauseUtil.toTelecomDisconnectCause(
+ DisconnectCause.BUSY, -1 /* precise label is NOT given */,
+ EMPTY_STRING, PHONE_ID, null, getBundleWithBusyToneArray(), mFeatureFlags);
+
+ assertBusyCauseWithTargetLabel(R.string.callFailed_userBusy, tcCause);
+ }
+
+ /**
+ * special case: The Carrier has re-defined a disconnect code that should play a busy tone.
+ * Thus, the code, label, and tone should be remapped.
+ * <p>
+ * <p>
+ * Verify that if the disconnect cause is in the carrier busy tone array and the Telephony
+ * stack has provided a precise label, the label is not overridden.
+ */
+ @Test
+ public void testCarrierSetBusyToneArray_PreciseLabelProvided() {
+ android.telecom.DisconnectCause tcCause =
+ DisconnectCauseUtil.toTelecomDisconnectCause(DisconnectCause.BUSY,
+ CallFailCause.USER_BUSY /* Telephony defined a precise label */,
+ EMPTY_STRING, PHONE_ID, null, getBundleWithBusyToneArray(), mFeatureFlags);
+ // Note: The precise label should not be overridden even though the carrier defined
+ // the cause to play a busy tone
+ assertBusyCauseWithTargetLabel(R.string.clh_callFailed_user_busy_txt, tcCause);
+ }
+
+ /**
+ * Ensure the helper doesCarrierClassifyDisconnectCauseAsBusyCause does not hit a NPE if a
+ * NULL carrier config is passed in.
+ */
+ @Test
+ public void testDoesCarrierClassifyDisconnectCauseAsBusyCause_nullConfig() {
+ assertFalse(DisconnectCauseUtil.doesCarrierClassifyDisconnectCauseAsBusyCause(-1, null));
+ }
+
+ /**
+ * Ensure the helper doesCarrierClassifyDisconnectCauseAsBusyCause does not hit a NPE if an
+ * EMPTY carrier config is passed in.
+ */
+ @Test
+ public void testDoesCarrierClassifyDisconnectCauseAsBusyCause_ConfigDoesNotDefineArray() {
PersistableBundle config = new PersistableBundle();
+ assertFalse(DisconnectCauseUtil.doesCarrierClassifyDisconnectCauseAsBusyCause(-1, config));
+ }
+
+ /**
+ * Ensure the helper doesCarrierClassifyDisconnectCauseAsBusyCause does not hit a NPE if an
+ * EMPTY array is defined for KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY.
+ */
+ @Test
+ public void testDoesCarrierClassifyDisconnectCauseAsBusyCause_ConfigHasEmptyArray() {
+ PersistableBundle config = new PersistableBundle();
+ int[] carrierBusyArr = {}; // NOTE: This is intentionally let empty
config.putIntArray(
CarrierConfigManager.KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY,
carrierBusyArr);
- android.telecom.DisconnectCause tcCause =
- DisconnectCauseUtil.toTelecomDisconnectCause(
- DisconnectCause.ERROR_UNSPECIFIED, -1,
- EMPTY_STRING, PHONE_ID, null, config);
+ assertFalse(DisconnectCauseUtil.doesCarrierClassifyDisconnectCauseAsBusyCause(-1, config));
+ }
- // CODE
- assertEquals(android.telecom.DisconnectCause.BUSY, tcCause.getCode());
- // LABEL
- safeAssertLabel(R.string.callFailed_userBusy, tcCause);
- // TONE
- assertEquals(TONE_SUP_BUSY, tcCause.getTone());
+ /**
+ * Ensure {@link DisconnectCauseUtil#doesCarrierClassifyDisconnectCauseAsBusyCause} returns
+ * FALSE is the passed in disconnect cause is NOT the busy tone array
+ */
+ @Test
+ public void testDoesCarrierClassifyDisconnectCauseAsBusyCause_ConfigHasBusyToneButNotMatch() {
+ assertFalse(DisconnectCauseUtil.doesCarrierClassifyDisconnectCauseAsBusyCause(-1,
+ getBundleWithBusyToneArray()));
+ }
+
+ /**
+ * Ensure {@link DisconnectCauseUtil#doesCarrierClassifyDisconnectCauseAsBusyCause} returns
+ * TRUE if the disconnect cause is defined in the busy tone array (by the Carrier)
+ */
+ @Test
+ public void testDoesCarrierClassifyDisconnectCauseAsBusyCause_ConfigHasBusyTone() {
+ assertTrue(DisconnectCauseUtil.doesCarrierClassifyDisconnectCauseAsBusyCause(
+ DisconnectCause.BUSY, getBundleWithBusyToneArray()));
+ }
+
+ private void assertBusyCauseWithTargetLabel(Integer targetLabel,
+ android.telecom.DisconnectCause disconnectCause) {
+ // CODE: Describes the cause of a disconnected call
+ assertEquals(android.telecom.DisconnectCause.BUSY, disconnectCause.getCode());
+ // LABEL: This is the label that the user sees
+ safeAssertLabel(targetLabel, disconnectCause);
+ // TONE: This is the DTMF tone being played to the user
+ assertEquals(TONE_SUP_BUSY, disconnectCause.getTone());
+ }
+
+ private PersistableBundle getBundleWithBusyToneArray() {
+ int[] carrierBusyArr = {DisconnectCause.BUSY};
+ PersistableBundle config = new PersistableBundle();
+
+ config.putIntArray(
+ CarrierConfigManager.KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY,
+ carrierBusyArr);
+ return config;
}
private void setSinglePhone() throws Exception {
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 4f9b879..653b492 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -16,6 +16,7 @@
package com.android.services.telephony;
+import static android.telecom.Connection.PROPERTY_WIFI;
import static android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE;
import static android.telephony.DisconnectCause.EMERGENCY_TEMP_FAILURE;
import static android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
@@ -32,9 +33,11 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertNotEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -57,10 +60,12 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.telecom.Conference;
import android.telecom.Conferenceable;
import android.telecom.ConnectionRequest;
import android.telecom.DisconnectCause;
+import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.AccessNetworkConstants;
@@ -74,7 +79,9 @@
import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.test.suitebuilder.annotation.SmallTest;
+import android.util.ArrayMap;
import androidx.test.runner.AndroidJUnit4;
@@ -97,6 +104,7 @@
import com.android.internal.telephony.emergency.EmergencyStateTracker;
import com.android.internal.telephony.emergency.RadioOnHelper;
import com.android.internal.telephony.emergency.RadioOnStateListener;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.gsm.SuppServiceNotification;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.satellite.SatelliteController;
@@ -104,6 +112,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -116,8 +125,10 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
/**
* Unit tests for TelephonyConnectionService.
@@ -125,6 +136,35 @@
@RunWith(AndroidJUnit4.class)
public class TelephonyConnectionServiceTest extends TelephonyTestBase {
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ private static final String NORMAL_ROUTED_EMERGENCY_NUMBER = "110";
+ private static final String EMERGENCY_ROUTED_EMERGENCY_NUMBER = "911";
+ private static final EmergencyNumber MOCK_NORMAL_NUMBER = new EmergencyNumber(
+ NORMAL_ROUTED_EMERGENCY_NUMBER,
+ "US" /* country */,
+ null /* mcc */,
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+ Collections.emptyList() /* categories */,
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
+ private static final EmergencyNumber MOCK_NORMAL_NUMBER_WITH_UNKNOWN_ROUTING =
+ new EmergencyNumber(
+ NORMAL_ROUTED_EMERGENCY_NUMBER,
+ "US" /* country */,
+ "455" /* mcc */,
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+ Collections.emptyList() /* categories */,
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN);
+ private static final EmergencyNumber MOCK_EMERGENCY_NUMBER = new EmergencyNumber(
+ EMERGENCY_ROUTED_EMERGENCY_NUMBER,
+ "US" /* country */,
+ null /* mcc */,
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+ Collections.emptyList() /* categories */,
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
+
/**
* Unlike {@link TestTelephonyConnection}, a bare minimal {@link TelephonyConnection} impl
* that does not try to configure anything.
@@ -174,8 +214,8 @@
private static final ComponentName TEST_COMPONENT_NAME = new ComponentName(
"com.android.phone.tests", TelephonyConnectionServiceTest.class.getName());
- private static final String TEST_ACCOUNT_ID1 = "id1";
- private static final String TEST_ACCOUNT_ID2 = "id2";
+ private static final String TEST_ACCOUNT_ID1 = "0"; // subid 0
+ private static final String TEST_ACCOUNT_ID2 = "1"; // subid 1
private static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE_1 = new PhoneAccountHandle(
TEST_COMPONENT_NAME, TEST_ACCOUNT_ID1);
private static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE_2 = new PhoneAccountHandle(
@@ -263,7 +303,7 @@
mTestConnectionService, mEmergencyStateTracker);
replaceInstance(TelephonyConnectionService.class, "mSatelliteSOSMessageRecommender",
mTestConnectionService, mSatelliteSOSMessageRecommender);
- doNothing().when(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), any());
+ doNothing().when(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
doNothing().when(mSatelliteSOSMessageRecommender).onEmergencyCallConnectionStateChanged(
anyString(), anyInt());
doReturn(CompletableFuture.completedFuture(NOT_DISCONNECTED))
@@ -277,6 +317,8 @@
replaceInstance(TelephonyConnectionService.class,
"mSatelliteController", mTestConnectionService, mSatelliteController);
mBinderStub = (IConnectionService.Stub) mTestConnectionService.onBind(null);
+ mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
+ mSetFlagsRule.enableFlags(Flags.FLAG_DO_NOT_OVERRIDE_PRECISE_LABEL);
}
@After
@@ -1293,7 +1335,83 @@
// This shouldn't happen
fail();
}
- verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), any());
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
+ }
+
+ /**
+ * Test that the TelephonyConnectionService successfully dials an outgoing normal routed
+ * emergency call on an in-service sim.
+ */
+ @Test
+ @SmallTest
+ public void testCreateOutgoingConnectionForNormalRoutedEmergencyCall()
+ throws CallStateException {
+ // A whole load of annoying mocks to set up to test this scenario.
+ // We'll purposely try to start the call on the limited service phone.
+ ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
+ .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
+ .setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, NORMAL_ROUTED_EMERGENCY_NUMBER,
+ null))
+ .build();
+
+ // First phone is in limited service.
+ Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_EMERGENCY_ONLY,
+ true /*isEmergencyOnly*/);
+ doReturn(ImsRegistrationImplBase.REGISTRATION_TECH_LTE).when(testPhone0)
+ .getImsRegistrationTech();
+ doReturn(0).when(testPhone0).getSubId();
+ setupMockEmergencyNumbers(testPhone0, List.of(MOCK_NORMAL_NUMBER,
+ MOCK_NORMAL_NUMBER_WITH_UNKNOWN_ROUTING, MOCK_EMERGENCY_NUMBER));
+
+ // Second phone is in full service; this is ultimately the one we want to pick.
+ Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_IN_SERVICE,
+ false /*isEmergencyOnly*/);
+ doReturn(ImsRegistrationImplBase.REGISTRATION_TECH_LTE).when(testPhone1)
+ .getImsRegistrationTech();
+ doReturn(1).when(testPhone1).getSubId();
+ setupMockEmergencyNumbers(testPhone1, List.of(MOCK_NORMAL_NUMBER,
+ MOCK_NORMAL_NUMBER_WITH_UNKNOWN_ROUTING, MOCK_EMERGENCY_NUMBER));
+
+ // Make sure both phones are going to prefer in service for normal routed ecalls.
+ doReturn(true).when(testPhone0).shouldPreferInServiceSimForNormalRoutedEmergencyCall();
+ doReturn(true).when(testPhone1).shouldPreferInServiceSimForNormalRoutedEmergencyCall();
+
+ // A whole load of other stuff that needs to be setup for this to work.
+ doReturn(GSM_PHONE).when(testPhone0).getPhoneType();
+ doReturn(GSM_PHONE).when(testPhone1).getPhoneType();
+ List<Phone> phones = new ArrayList<>(2);
+ doReturn(true).when(testPhone0).isRadioOn();
+ doReturn(true).when(testPhone1).isRadioOn();
+ phones.add(testPhone0);
+ phones.add(testPhone1);
+ setPhones(phones);
+ doReturn(0).when(mPhoneUtilsProxy).getSubIdForPhoneAccountHandle(
+ eq(PHONE_ACCOUNT_HANDLE_1));
+ doReturn(1).when(mPhoneUtilsProxy).getSubIdForPhoneAccountHandle(
+ eq(PHONE_ACCOUNT_HANDLE_2));
+ setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
+ setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_2, testPhone1);
+ setupDeviceConfig(testPhone0, testPhone1, 0);
+ doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(
+ eq(NORMAL_ROUTED_EMERGENCY_NUMBER));
+ HashMap<Integer, List<EmergencyNumber>> emergencyNumbers = new HashMap<>(1);
+ List<EmergencyNumber> numbers = new ArrayList<>();
+ numbers.add(MOCK_EMERGENCY_NUMBER);
+ numbers.add(MOCK_NORMAL_NUMBER);
+ numbers.add(MOCK_NORMAL_NUMBER_WITH_UNKNOWN_ROUTING);
+ emergencyNumbers.put(0 /*subId*/, numbers);
+ doReturn(emergencyNumbers).when(mTelephonyManagerProxy).getCurrentEmergencyNumberList();
+ doReturn(2).when(mTelephonyManagerProxy).getPhoneCount();
+
+ // All of that for... this.
+ mConnection = mTestConnectionService.onCreateOutgoingConnection(
+ PHONE_ACCOUNT_HANDLE_1, connectionRequest);
+ assertNotNull("test connection was not set up correctly.", mConnection);
+
+ // Lets make sure we DID try to place the call on phone 1, which is the in service phone.
+ verify(testPhone1).dial(anyString(), any(DialArgs.class), any(Consumer.class));
+ // And make sure we DID NOT try to place the call on phone 0, which is in limited service.
+ verify(testPhone0, never()).dial(anyString(), any(DialArgs.class), any(Consumer.class));
}
/**
@@ -1329,7 +1447,107 @@
// This shouldn't happen
fail();
}
- verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), any());
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
+ }
+
+ /**
+ * Test that the TelephonyConnectionService successfully turns radio on before placing the
+ * call when radio off because bluetooth on and wifi calling is not enabled
+ */
+ @Test
+ @SmallTest
+ public void testCreateOutgoingCall_turnOnRadio_bluetoothOn() {
+ doReturn(true).when(mDeviceState).isRadioPowerDownAllowedOnBluetooth(any());
+ doReturn(PhoneConstants.CELL_ON_FLAG).when(mDeviceState).getCellOnStatus(any());
+ Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_POWER_OFF,
+ false /*isEmergencyOnly*/);
+ Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_POWER_OFF,
+ false /*isEmergencyOnly*/);
+ doReturn(false).when(testPhone0).isRadioOn();
+ doReturn(false).when(testPhone0).isWifiCallingEnabled();
+ doReturn(false).when(testPhone1).isRadioOn();
+ doReturn(false).when(testPhone1).isWifiCallingEnabled();
+ List<Phone> phones = new ArrayList<>(2);
+ phones.add(testPhone0);
+ phones.add(testPhone1);
+ setPhones(phones);
+ setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
+ ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
+ .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
+ .setAddress(TEST_ADDRESS)
+ .build();
+ mConnection = mTestConnectionService.onCreateOutgoingConnection(
+ PHONE_ACCOUNT_HANDLE_1, connectionRequest);
+
+ verify(mRadioOnHelper).triggerRadioOnAndListen(any(), eq(false),
+ eq(testPhone0), eq(false), eq(0));
+ }
+
+ /**
+ * Test that the TelephonyConnectionService successfully turns radio on before placing the
+ * call when phone is null, radio off because bluetooth on and wifi calling is not enabled
+ */
+ @Test
+ @SmallTest
+ public void testCreateOutgoingCall_forWearWatch_whenPhoneIsNull() {
+ doReturn(-1).when(mPhoneUtilsProxy).getSubIdForPhoneAccountHandle(any());
+ doReturn(true).when(mDeviceState).isRadioPowerDownAllowedOnBluetooth(any());
+ doReturn(PhoneConstants.CELL_ON_FLAG).when(mDeviceState).getCellOnStatus(any());
+ Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_POWER_OFF,
+ false /*isEmergencyOnly*/);
+ Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_POWER_OFF,
+ false /*isEmergencyOnly*/);
+ doReturn(false).when(testPhone0).isRadioOn();
+ doReturn(false).when(testPhone0).isWifiCallingEnabled();
+ doReturn(false).when(testPhone1).isRadioOn();
+ doReturn(false).when(testPhone1).isWifiCallingEnabled();
+ List<Phone> phones = new ArrayList<>(2);
+ phones.add(testPhone0);
+ phones.add(testPhone1);
+ setPhones(phones);
+ setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
+ ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
+ .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
+ .setAddress(TEST_ADDRESS)
+ .build();
+ mConnection = mTestConnectionService.onCreateOutgoingConnection(
+ PHONE_ACCOUNT_HANDLE_1, connectionRequest);
+
+ verify(mRadioOnHelper).triggerRadioOnAndListen(any(), eq(false),
+ eq(testPhone0), eq(false), eq(0));
+ }
+
+ /**
+ * Test that the TelephonyConnectionService will not turns radio on before placing the
+ * call when radio off because bluetooth on and wifi calling is enabled
+ */
+ @Test
+ @SmallTest
+ public void testCreateOutgoingCall_notTurnOnRadio_bluetoothOnWifiCallingEnabled() {
+ doReturn(true).when(mDeviceState).isRadioPowerDownAllowedOnBluetooth(any());
+ doReturn(PhoneConstants.CELL_ON_FLAG).when(mDeviceState).getCellOnStatus(any());
+ Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_POWER_OFF,
+ false /*isEmergencyOnly*/);
+ Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_POWER_OFF,
+ false /*isEmergencyOnly*/);
+ doReturn(false).when(testPhone0).isRadioOn();
+ doReturn(true).when(testPhone0).isWifiCallingEnabled();
+ doReturn(false).when(testPhone1).isRadioOn();
+ doReturn(true).when(testPhone1).isWifiCallingEnabled();
+ List<Phone> phones = new ArrayList<>(2);
+ phones.add(testPhone0);
+ phones.add(testPhone1);
+ setPhones(phones);
+ setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
+ ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
+ .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
+ .setAddress(TEST_ADDRESS)
+ .build();
+ mConnection = mTestConnectionService.onCreateOutgoingConnection(
+ PHONE_ACCOUNT_HANDLE_1, connectionRequest);
+
+ verify(mRadioOnHelper, times(0)).triggerRadioOnAndListen(any(),
+ eq(true), eq(testPhone0), eq(false), eq(0));
}
/**
@@ -1734,8 +1952,8 @@
}
/**
- * For DSDA devices, placing an outgoing call on a 2nd sub will hold the existing connection on
- * the first sub.
+ * For DSDA devices, placing an outgoing call on a 2nd sub will hold the existing ACTIVE
+ * connection on the first sub.
*/
@Test
@SmallTest
@@ -1744,13 +1962,34 @@
ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
+ tc1.setTelephonyConnectionActive();
tcs.add(tc1);
+
Conferenceable c = TelephonyConnectionService.maybeHoldCallsOnOtherSubs(
tcs, new ArrayList<>(), SUB2_HANDLE, mTelephonyManagerProxy);
assertTrue(c.equals(tc1));
assertTrue(tc1.wasHeld);
}
+ /**
+ * For DSDA devices, if the existing connection was already held, placing an outgoing call on a
+ * 2nd sub will not attempt to hold the existing connection on the first sub.
+ */
+ @Test
+ @SmallTest
+ public void testNoHold_ifExistingConnectionAlreadyHeld_ForVirtualDsdaDevice() {
+ when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
+
+ ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
+ SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
+ tc1.setTelephonyConnectionOnHold();
+ tcs.add(tc1);
+
+ Conferenceable c = TelephonyConnectionService.maybeHoldCallsOnOtherSubs(
+ tcs, new ArrayList<>(), SUB2_HANDLE, mTelephonyManagerProxy);
+ assertNull(c);
+ }
+
// For 'Virtual DSDA' devices, if there is an existing call on sub1, an outgoing call on sub2
// will place the sub1 call on hold.
@Test
@@ -1889,7 +2128,7 @@
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyStateTracker)
.startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
- verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
@@ -1919,7 +2158,7 @@
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyStateTracker)
.startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
- verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
@@ -1950,7 +2189,7 @@
verify(mEmergencyStateTracker, times(1))
.startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
- verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mDomainSelectionResolver, times(0))
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyCallDomainSelectionConnection, times(0))
@@ -2036,6 +2275,8 @@
setupForDialForDomainSelection(mPhone0, selectedDomain, false);
doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
+ doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
+ anyString());
mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
@@ -2044,7 +2285,89 @@
verify(mDomainSelectionResolver)
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
verify(mNormalCallDomainSelectionConnection).createNormalConnection(any(), any());
- verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
+ DialArgs dialArgs = argsCaptor.getValue();
+ assertNotNull("DialArgs param is null", dialArgs);
+ assertNotNull("intentExtras is null", dialArgs.intentExtras);
+ assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
+ assertEquals(
+ selectedDomain, dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
+ }
+
+ @Test
+ public void testDomainSelectionDialedSimEmergencyNumberOnlyFalse() throws Exception {
+ setupForCallTest();
+
+ int selectedDomain = DOMAIN_PS;
+
+ EmergencyNumber emergencyNumber = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "", "",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+ Collections.emptyList(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+ doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
+ doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
+ anyString());
+ doReturn(false).when(mEmergencyNumberTracker).isEmergencyNumber(anyString());
+ getTestContext().getCarrierConfig(0 /*subId*/).putBoolean(
+ CarrierConfigManager.KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, false);
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
+ verify(mEmergencyStateTracker)
+ .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
+ DialArgs dialArgs = argsCaptor.getValue();
+ assertNotNull("DialArgs param is null", dialArgs);
+ assertNotNull("intentExtras is null", dialArgs.intentExtras);
+ assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
+ assertEquals(selectedDomain,
+ dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
+ }
+
+ @Test
+ public void testDomainSelectionDialedSimEmergencyNumberOnlyTrue() throws Exception {
+ setupForCallTest();
+ int selectedDomain = DOMAIN_PS;
+
+ EmergencyNumber emergencyNumber = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "", "",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+ Collections.emptyList(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, false);
+ doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
+ doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
+ doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
+ anyString());
+ doReturn(false).when(mEmergencyNumberTracker).isEmergencyNumber(anyString());
+ getTestContext().getCarrierConfig(0 /*subId*/).putBoolean(
+ CarrierConfigManager.KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, true);
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
+ verify(mNormalCallDomainSelectionConnection).createNormalConnection(any(), any());
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
@@ -2078,6 +2401,8 @@
doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
+ doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
+ anyString());
when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
@@ -2125,6 +2450,8 @@
doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
+ doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
+ anyString());
when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
@@ -2166,6 +2493,8 @@
doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
+ doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
+ anyString());
when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
@@ -2219,6 +2548,8 @@
doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
+ doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
+ anyString());
when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
@@ -2273,6 +2604,8 @@
doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
+ doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
+ anyString());
when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
@@ -2331,7 +2664,7 @@
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyStateTracker)
.startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
- verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
@@ -2372,7 +2705,7 @@
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyStateTracker)
.startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
- verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
@@ -2636,7 +2969,7 @@
verify(mEmergencyStateTracker)
.startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
- verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
// dialing is canceled
mTestConnectionService.onLocalHangup(c);
@@ -2704,7 +3037,7 @@
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyStateTracker)
.startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
- verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
verify(mPhone0).dial(anyString(), any(), any());
@@ -2789,6 +3122,52 @@
}
@Test
+ public void testDomainSelectionListenOriginalConnectionPropertiesChange() throws Exception {
+ setupForCallTest();
+
+ int selectedDomain = DOMAIN_PS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
+ verify(mEmergencyStateTracker)
+ .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+ verify(mPhone0).dial(anyString(), any(), any());
+
+ TestTelephonyConnection c = new TestTelephonyConnection();
+ c.setTelecomCallId(TELECOM_CALL_ID1);
+ c.setIsImsConnection(true);
+ Connection orgConn = c.getOriginalConnection();
+ doReturn(PhoneConstants.PHONE_TYPE_IMS).when(orgConn).getPhoneType();
+
+ TelephonyConnection.TelephonyConnectionListener connectionListener =
+ mTestConnectionService.getEmergencyConnectionListener();
+
+ doReturn(Call.State.DISCONNECTING).when(orgConn).getState();
+ connectionListener.onConnectionPropertiesChanged(c, PROPERTY_WIFI);
+
+ verify(mEmergencyStateTracker, times(0)).onEmergencyCallPropertiesChanged(
+ anyInt(), anyString());
+
+ doReturn(Call.State.ACTIVE).when(orgConn).getState();
+ connectionListener.onConnectionPropertiesChanged(c, PROPERTY_WIFI);
+
+ verify(mEmergencyStateTracker, times(1)).onEmergencyCallPropertiesChanged(
+ eq(PROPERTY_WIFI), eq(TELECOM_CALL_ID1));
+
+ connectionListener.onConnectionPropertiesChanged(c, 0);
+
+ verify(mEmergencyStateTracker, times(1)).onEmergencyCallPropertiesChanged(
+ eq(0), eq(TELECOM_CALL_ID1));
+ }
+
+ @Test
public void testDomainSelectionTempFailure() throws Exception {
setupForCallTest();
@@ -2850,7 +3229,7 @@
verify(mDomainSelectionResolver)
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
verify(mNormalCallDomainSelectionConnection).createNormalConnection(any(), any());
- verify(mSatelliteSOSMessageRecommender, never()).onEmergencyCallStarted(any(), any());
+ verify(mSatelliteSOSMessageRecommender, never()).onEmergencyCallStarted(any());
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
@@ -2875,7 +3254,7 @@
verify(mDomainSelectionResolver)
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
verify(mNormalCallDomainSelectionConnection).createNormalConnection(any(), any());
- verify(mSatelliteSOSMessageRecommender, never()).onEmergencyCallStarted(any(), any());
+ verify(mSatelliteSOSMessageRecommender, never()).onEmergencyCallStarted(any());
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
@@ -2899,6 +3278,205 @@
disconnectCause.getTelephonyDisconnectCause());
}
+ @Test
+ public void testNormalCallUsingNonTerrestrialNetwork_enableFlag() throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
+
+ setupForCallTest();
+ // Call is not supported while using satellite
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setIsNonTerrestrialNetwork(true)
+ .setAvailableServices(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA))
+ .build();
+ ServiceState ss = new ServiceState();
+ ss.addNetworkRegistrationInfo(nri);
+ when(mPhone0.getServiceState()).thenReturn(ss);
+ mConnection = mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
+ DisconnectCause disconnectCause = mConnection.getDisconnectCause();
+ assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
+ disconnectCause.getTelephonyDisconnectCause());
+
+ // Call is supported while using satellite
+ nri = new NetworkRegistrationInfo.Builder()
+ .setIsNonTerrestrialNetwork(true)
+ .setAvailableServices(List.of(NetworkRegistrationInfo.SERVICE_TYPE_VOICE))
+ .build();
+ ss.addNetworkRegistrationInfo(nri);
+ mConnection = mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", "TC@2"));
+ disconnectCause = mConnection.getDisconnectCause();
+ assertNotEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
+ disconnectCause.getTelephonyDisconnectCause());
+ }
+
+ @Test
+ public void testNormalCallUsingNonTerrestrialNetwork_disableFlag() throws Exception {
+ mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
+
+ setupForCallTest();
+ // Flag is disabled, so call is supported while using satellite
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setIsNonTerrestrialNetwork(true)
+ .setAvailableServices(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA))
+ .build();
+ ServiceState ss = new ServiceState();
+ ss.addNetworkRegistrationInfo(nri);
+ when(mPhone0.getServiceState()).thenReturn(ss);
+ mConnection = mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
+ DisconnectCause disconnectCause = mConnection.getDisconnectCause();
+ assertNotEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
+ disconnectCause.getTelephonyDisconnectCause());
+ }
+
+ @Test
+ public void testIsAvailableForEmergencyCallsNotForCrossSim() {
+ Phone mockPhone = Mockito.mock(Phone.class);
+ when(mockPhone.getImsRegistrationTech()).thenReturn(
+ ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM);
+ assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY));
+ assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL));
+ assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
+ }
+
+ @Test
+ public void testIsAvailableForEmergencyCallsForEmergencyRoutingInEmergencyOnly() {
+ ServiceState mockService = Mockito.mock(ServiceState.class);
+ when(mockService.isEmergencyOnly()).thenReturn(true);
+ when(mockService.getState()).thenReturn(ServiceState.STATE_EMERGENCY_ONLY);
+
+ Phone mockPhone = Mockito.mock(Phone.class);
+ when(mockPhone.getImsRegistrationTech()).thenReturn(
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ when(mockPhone.getServiceState()).thenReturn(mockService);
+
+ assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY));
+ assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL));
+ assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
+ }
+
+ @Test
+ public void testIsAvailableForEmergencyCallsForEmergencyRoutingInService() {
+ ServiceState mockService = Mockito.mock(ServiceState.class);
+ when(mockService.isEmergencyOnly()).thenReturn(false);
+ when(mockService.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+
+ Phone mockPhone = Mockito.mock(Phone.class);
+ when(mockPhone.getImsRegistrationTech()).thenReturn(
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ when(mockPhone.getServiceState()).thenReturn(mockService);
+
+ assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY));
+ assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL));
+ assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
+ }
+
+ /**
+ * Verify that is the carrier config indicates that the carrier does not prefer to use an in
+ * service sim for a normal routed emergency call that we'll get no result.
+ */
+ @Test
+ public void testGetPhoneForNormalRoutedEmergencyCallWhenCarrierDoesntSupport() {
+ ServiceState mockService = Mockito.mock(ServiceState.class);
+ when(mockService.isEmergencyOnly()).thenReturn(false);
+ when(mockService.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+
+ Phone mockPhone = Mockito.mock(Phone.class);
+ when(mockPhone.shouldPreferInServiceSimForNormalRoutedEmergencyCall()).thenReturn(
+ false);
+ setupMockEmergencyNumbers(mockPhone, List.of(MOCK_NORMAL_NUMBER));
+ when(mPhoneFactoryProxy.getPhones()).thenReturn(new Phone[] {mockPhone});
+
+ assertNull(mTestConnectionService.getPhoneForNormalRoutedEmergencyCall(
+ NORMAL_ROUTED_EMERGENCY_NUMBER));
+ }
+
+ /**
+ * Verify that is the carrier config indicates that the carrier prefers to use an in service sim
+ * for a normal routed emergency call that we'll get the in service sim that supports it.
+ */
+ @Test
+ public void testGetPhoneForNormalRoutedEmergencyCallWhenCarrierDoesSupport() {
+ ServiceState mockService = Mockito.mock(ServiceState.class);
+ when(mockService.isEmergencyOnly()).thenReturn(false);
+ when(mockService.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+
+ Phone mockPhone = Mockito.mock(Phone.class);
+ when(mockPhone.shouldPreferInServiceSimForNormalRoutedEmergencyCall()).thenReturn(
+ true);
+ when(mockPhone.getServiceState()).thenReturn(mockService);
+ setupMockEmergencyNumbers(mockPhone, List.of(MOCK_NORMAL_NUMBER));
+ when(mPhoneFactoryProxy.getPhones()).thenReturn(new Phone[] {mockPhone});
+
+ assertEquals(mockPhone,
+ mTestConnectionService.getPhoneForNormalRoutedEmergencyCall(
+ NORMAL_ROUTED_EMERGENCY_NUMBER));
+ }
+
+ /**
+ * Verify where there are two sims, one in limited service, and another in full service, if the
+ * carrier prefers to use an in-service sim, we choose the in-service sim.
+ */
+ @Test
+ public void testGetPhoneForNormalRoutedEmergencyCallWhenCarrierDoesSupportMultiSim() {
+ ServiceState mockInService = Mockito.mock(ServiceState.class);
+ when(mockInService.isEmergencyOnly()).thenReturn(false);
+ when(mockInService.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+ ServiceState mockLimitedService = Mockito.mock(ServiceState.class);
+ when(mockLimitedService.isEmergencyOnly()).thenReturn(true);
+ when(mockLimitedService.getState()).thenReturn(ServiceState.STATE_EMERGENCY_ONLY);
+
+ Phone mockInservicePhone = Mockito.mock(Phone.class);
+ when(mockInservicePhone.shouldPreferInServiceSimForNormalRoutedEmergencyCall()).thenReturn(
+ true);
+ when(mockInservicePhone.getServiceState()).thenReturn(mockInService);
+ setupMockEmergencyNumbers(mockInservicePhone, List.of(MOCK_NORMAL_NUMBER));
+
+ Phone mockLimitedServicePhone = Mockito.mock(Phone.class);
+ when(mockLimitedServicePhone.shouldPreferInServiceSimForNormalRoutedEmergencyCall())
+ .thenReturn(true);
+ when(mockLimitedServicePhone.getServiceState()).thenReturn(mockLimitedService);
+ setupMockEmergencyNumbers(mockLimitedServicePhone, List.of(MOCK_NORMAL_NUMBER));
+
+ when(mPhoneFactoryProxy.getPhones()).thenReturn(new Phone[] {mockLimitedServicePhone,
+ mockInservicePhone});
+
+ assertEquals(mockInservicePhone,
+ mTestConnectionService.getPhoneForNormalRoutedEmergencyCall(
+ NORMAL_ROUTED_EMERGENCY_NUMBER));
+ }
+
+ private void setupMockEmergencyNumbers(Phone mockPhone, List<EmergencyNumber> numbers) {
+ EmergencyNumberTracker emergencyNumberTracker = Mockito.mock(EmergencyNumberTracker.class);
+ // Yuck. There should really be a fake emergency number class which makes it easy to inject
+ // the numbers for testing.
+ ArrayMap<String, List<EmergencyNumber>> numbersMap = new ArrayMap<>();
+ for (EmergencyNumber number : numbers) {
+ when(emergencyNumberTracker.getEmergencyNumber(eq(number.getNumber())))
+ .thenReturn(number);
+ if (!numbersMap.containsKey(number.getNumber())) {
+ numbersMap.put(number.getNumber(), new ArrayList<>());
+ }
+ numbersMap.get(number.getNumber()).add(number);
+ }
+ // Double yuck.
+ for (Map.Entry<String, List<EmergencyNumber>> entry : numbersMap.entrySet()) {
+ when(emergencyNumberTracker.getEmergencyNumbers(eq(entry.getKey()))).thenReturn(
+ entry.getValue());
+ }
+ when(mockPhone.getEmergencyNumberTracker()).thenReturn(emergencyNumberTracker);
+ }
+
private void setupForDialForDomainSelection(Phone mockPhone, int domain, boolean isEmergency) {
if (isEmergency) {
doReturn(mEmergencyCallDomainSelectionConnection).when(mDomainSelectionResolver)
@@ -3107,10 +3685,14 @@
}
private void setupHandleToPhoneMap(PhoneAccountHandle handle, Phone phone) {
- // use subId 0
- when(mPhoneUtilsProxy.getSubIdForPhoneAccountHandle(eq(handle))).thenReturn(0);
- when(mSubscriptionManagerProxy.getPhoneId(eq(0))).thenReturn(0);
- when(mPhoneFactoryProxy.getPhone(eq(0))).thenReturn(phone);
+ // The specified handle has an id which is subID
+ doReturn(Integer.parseInt(handle.getId())).when(mPhoneUtilsProxy)
+ .getSubIdForPhoneAccountHandle(eq(handle));
+ // The specified sub id in the passed handle will correspond to the phone's phone id.
+ doReturn(phone.getPhoneId()).when(mSubscriptionManagerProxy)
+ .getPhoneId(eq(Integer.parseInt(handle.getId())));
+ int phoneId = phone.getPhoneId();
+ doReturn(phone).when(mPhoneFactoryProxy).getPhone(eq(phoneId));
}
private AsyncResult getSuppServiceNotification(int notificationType, int code) {
diff --git a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
index 9be85ed..c8ac7e9 100644
--- a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
@@ -52,6 +52,7 @@
import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN;
+import static android.telephony.PreciseDisconnectCause.SERVICE_OPTION_NOT_AVAILABLE;
import static com.android.services.telephony.domainselection.EmergencyCallDomainSelector.MSG_MAX_CELLULAR_TIMEOUT;
import static com.android.services.telephony.domainselection.EmergencyCallDomainSelector.MSG_NETWORK_SCAN_TIMEOUT;
@@ -75,6 +76,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkRequest;
import android.os.Handler;
@@ -99,7 +101,6 @@
import android.telephony.WwanSelectorCallback;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
-import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ProvisioningManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.TestableLooper;
@@ -139,6 +140,7 @@
@Mock private DomainSelectorBase.DestroyListener mDestroyListener;
@Mock private ProvisioningManager mProvisioningManager;
@Mock private CrossSimRedialingController mCsrdCtrl;
+ @Mock private Resources mResources;
private Context mContext;
@@ -188,6 +190,11 @@
public String getOpPackageName() {
return "";
}
+
+ @Override
+ public Resources getResources() {
+ return mResources;
+ }
};
if (Looper.myLooper() == null) {
@@ -207,6 +214,8 @@
when(mTelephonyManager.createForSubscriptionId(anyInt()))
.thenReturn(mTelephonyManager);
when(mTelephonyManager.getNetworkCountryIso()).thenReturn("");
+ when(mTelephonyManager.getSimState(anyInt())).thenReturn(TelephonyManager.SIM_STATE_READY);
+ when(mTelephonyManager.getActiveModemCount()).thenReturn(1);
mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
when(mCarrierConfigManager.getConfigForSubId(anyInt()))
@@ -253,6 +262,8 @@
}
}).when(mWwanSelectorCallback).onRequestEmergencyNetworkScan(
any(), anyInt(), any(), any());
+
+ when(mResources.getStringArray(anyInt())).thenReturn(null);
}
@After
@@ -279,6 +290,102 @@
}
@Test
+ public void testNoRedundantDomainSelectionFromInitialState() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+ unsolBarringInfoChanged(false);
+
+ processAllMessages();
+
+ verify(mTransportSelectorCallback, times(1)).onWwanSelected(any());
+ verify(mWwanSelectorCallback, times(1)).onDomainSelected(anyInt(), anyBoolean());
+ }
+
+ @Test
+ public void testNoUnexpectedTransportChangeFromInitialState() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_NON_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+ bindImsService(true);
+
+ processAllMessages();
+
+ verify(mTransportSelectorCallback, times(1)).onWwanSelected(any());
+ verify(mTransportSelectorCallback, times(0)).onWlanSelected(anyBoolean());
+ }
+
+ @Test
+ public void testNoRedundantScanRequestFromInitialState() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(
+ UNKNOWN, REGISTRATION_STATE_UNKNOWN, 0, false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+ unsolBarringInfoChanged(false);
+
+ processAllMessages();
+
+ verify(mTransportSelectorCallback, times(1)).onWwanSelected(any());
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), any(), any());
+ }
+
+ @Test
+ public void testNoRedundantTerminationFromInitialState() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
+ doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
+ .when(mTelephonyManager).getSimState(anyInt());
+ doReturn(true).when(mCsrdCtrl).isThereOtherSlot();
+ doReturn(new String[] {"jp"}).when(mResources).getStringArray(anyInt());
+
+ EmergencyRegResult regResult = getEmergencyRegResult(
+ UNKNOWN, REGISTRATION_STATE_UNKNOWN, 0, false, false, 0, 0, "", "", "jp");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+ unsolBarringInfoChanged(false);
+
+ verify(mTransportSelectorCallback, times(0)).onWlanSelected(anyBoolean());
+ verify(mTransportSelectorCallback, times(0)).onWwanSelected(any());
+ verify(mTransportSelectorCallback, times(1)).onSelectionTerminated(anyInt());
+ }
+
+ @Test
public void testDefaultCombinedImsRegisteredBarredSelectCs() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
@@ -335,6 +442,41 @@
}
@Test
+ public void testDefaultCombinedImsRegisteredSelectPsThenExtendedServiceRequestFails()
+ throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyPsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyCsDialed();
+
+ //Extended service request failed
+ SelectionAttributes.Builder builder =
+ new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setCsDisconnectCause(SERVICE_OPTION_NOT_AVAILABLE)
+ .setEmergency(true)
+ .setEmergencyRegResult(regResult);
+ attr = builder.build();
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyScanCsPreferred();
+ }
+
+ @Test
public void testDefaultCombinedImsNotRegisteredSelectCs() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -1000,6 +1142,31 @@
}
@Test
+ public void testSimLockEpsImsRegisteredBarredScanNoTimeoutWifi() throws Exception {
+ when(mTelephonyManager.getSimState(anyInt())).thenReturn(
+ TelephonyManager.SIM_STATE_PIN_REQUIRED);
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService(true);
+
+ verifyScanPsPreferred();
+
+ assertFalse(mDomainSelector.hasMessages(MSG_NETWORK_SCAN_TIMEOUT));
+ }
+
+ @Test
public void testVoWifiSosPdnRequiresSettingEnabled() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
@@ -1150,6 +1317,7 @@
doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
.when(mTelephonyManager).getSimState(anyInt());
doReturn(true).when(mCsrdCtrl).isThereOtherSlot();
+ doReturn(new String[] {"jp"}).when(mResources).getStringArray(anyInt());
EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
0, false, false, 0, 0, "", "", "jp");
@@ -1172,6 +1340,7 @@
doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
.when(mTelephonyManager).getSimState(anyInt());
doReturn(false).when(mCsrdCtrl).isThereOtherSlot();
+ doReturn(new String[] {"jp"}).when(mResources).getStringArray(anyInt());
EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
0, false, false, 0, 0, "", "", "jp");
@@ -1271,7 +1440,7 @@
setupForScanListTest(bundle);
- verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false));
}
@Test
@@ -1285,7 +1454,7 @@
setupForScanListTest(bundle);
- verifyPsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
+ verifyPsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false));
}
@Test
@@ -1300,7 +1469,7 @@
setupForScanListTest(bundle);
- verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
+ verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false));
}
@Test
@@ -1315,7 +1484,7 @@
setupForScanListTest(bundle);
- verifyCsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
+ verifyCsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false));
}
@@ -1330,7 +1499,7 @@
setupForScanListTest(bundle);
- verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false));
}
@Test
@@ -1344,7 +1513,7 @@
setupForScanListTest(bundle);
- verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false));
}
@Test
@@ -1360,7 +1529,7 @@
setupForScanListTest(bundle);
- verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
+ verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false));
}
@Test
@@ -1375,7 +1544,7 @@
setupForScanListTest(bundle);
- verifyCsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
+ verifyCsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false));
}
@Test
@@ -1392,7 +1561,7 @@
bindImsService();
processAllMessages();
- verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false));
}
@Test
@@ -1409,7 +1578,7 @@
bindImsService();
processAllMessages();
- verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false));
}
@Test
@@ -1427,7 +1596,7 @@
bindImsService();
processAllMessages();
- verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false, false));
+ verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false));
}
@Test
@@ -1444,7 +1613,7 @@
bindImsService();
processAllMessages();
- verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false));
}
@Test
@@ -1461,7 +1630,7 @@
bindImsService();
processAllMessages();
- verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false));
}
@Test
@@ -1480,7 +1649,7 @@
bindImsService();
processAllMessages();
- verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false, false));
+ verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false));
}
@Test
@@ -1496,7 +1665,7 @@
setupForScanListTest(bundle);
- List<Integer> networks = mDomainSelector.getNextPreferredNetworks(false, true, false);
+ List<Integer> networks = mDomainSelector.getNextPreferredNetworks(false, true);
assertFalse(networks.isEmpty());
assertTrue(networks.contains(EUTRAN));
@@ -1512,6 +1681,7 @@
public void testStartCrossStackTimer() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
EmergencyRegResult regResult = getEmergencyRegResult(
UNKNOWN, REGISTRATION_STATE_UNKNOWN, 0, false, false, 0, 0, "", "");
@@ -1652,36 +1822,6 @@
}
@Test
- public void testDefaultEpsImsRegisteredSelectPsEmergencyRegFailed() throws Exception {
- createSelector(SLOT_0_SUB_ID);
- unsolBarringInfoChanged(false);
-
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
- NetworkRegistrationInfo.DOMAIN_PS,
- true, true, 0, 0, "", "");
- SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
- mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
- processAllMessages();
-
- bindImsService();
-
- verifyPsDialed();
-
- attr = new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
- .setEmergency(true)
- .setEmergencyRegResult(regResult)
- .setPsDisconnectCause(
- new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED, 0, null))
- .build();
- mDomainSelector.reselectDomain(attr);
- processAllMessages();
-
- verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
- any(), anyInt(), any(), any());
- assertFalse(mAccessNetwork.contains(EUTRAN));
- }
-
- @Test
public void testMaxCellularTimeout() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
@@ -1706,6 +1846,20 @@
verify(mTransportSelectorCallback, times(1)).onWlanSelected(anyBoolean());
}
+ @Test
+ public void testSimLockNoMaxCellularTimeout() throws Exception {
+ when(mTelephonyManager.getSimState(anyInt())).thenReturn(
+ TelephonyManager.SIM_STATE_PIN_REQUIRED);
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
+ bundle.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, 20);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ setupForHandleScanResult();
+
+ assertFalse(mDomainSelector.hasMessages(MSG_NETWORK_SCAN_TIMEOUT));
+ assertFalse(mDomainSelector.hasMessages(MSG_MAX_CELLULAR_TIMEOUT));
+ }
@Test
public void testMaxCellularTimeoutScanTimeout() throws Exception {
@@ -1847,6 +2001,29 @@
verify(mTransportSelectorCallback, times(2)).onWlanSelected(anyBoolean());
}
+ @Test
+ public void testSimLockScanPsPreferredIncludingNr() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ when(mTelephonyManager.getSimState(anyInt())).thenReturn(
+ TelephonyManager.SIM_STATE_PIN_REQUIRED);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(
+ UNKNOWN, REGISTRATION_STATE_UNKNOWN, 0, false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), any(), any());
+ assertEquals(EUTRAN, (int) mAccessNetwork.get(0));
+ assertEquals(NGRAN, (int) mAccessNetwork.get(1));
+ }
+
private void setupForScanListTest(PersistableBundle bundle) throws Exception {
setupForScanListTest(bundle, false);
}
@@ -1921,7 +2098,7 @@
mDomainSelector = new EmergencyCallDomainSelector(
mContext, SLOT_0, subId, mHandlerThread.getLooper(),
mImsStateTracker, mDestroyListener, mCsrdCtrl);
-
+ mDomainSelector.clearResourceConfiguration();
replaceInstance(DomainSelectorBase.class,
"mWwanSelectorCallback", mDomainSelector, mWwanSelectorCallback);
}
diff --git a/tests/src/com/android/services/telephony/domainselection/ImsStateTrackerTest.java b/tests/src/com/android/services/telephony/domainselection/ImsStateTrackerTest.java
index 430adea..6519835 100644
--- a/tests/src/com/android/services/telephony/domainselection/ImsStateTrackerTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/ImsStateTrackerTest.java
@@ -33,6 +33,7 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
+import android.os.SystemClock;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.BarringInfo;
import android.telephony.ServiceState;
@@ -74,6 +75,7 @@
private static final int SUB_1 = 1;
private static final int SUB_2 = 2;
private static final long TIMEOUT_MS = 100;
+ private static final long MSG_PROCESS_DELAY_MS = 10;
@Mock private ImsMmTelManager mMmTelManager;
@Mock private ImsMmTelManager mMmTelManager2;
@@ -262,6 +264,9 @@
@Test
@SmallTest
public void testAddAndRemoveServiceStateListener() {
+ mImsStateTracker.getHandler().post(() -> {
+ SystemClock.sleep(MSG_PROCESS_DELAY_MS);
+ });
mImsStateTracker.updateServiceState(mServiceState);
mImsStateTracker.addServiceStateListener(mServiceStateListener);
mImsStateTracker.removeServiceStateListener(mServiceStateListener);
@@ -307,6 +312,9 @@
@Test
@SmallTest
public void testAddAndRemoveBarringInfoListener() {
+ mImsStateTracker.getHandler().post(() -> {
+ SystemClock.sleep(MSG_PROCESS_DELAY_MS);
+ });
mImsStateTracker.updateBarringInfo(mBarringInfo);
mImsStateTracker.addBarringInfoListener(mBarringInfoListener);
mImsStateTracker.removeBarringInfoListener(mBarringInfoListener);
diff --git a/tests/src/com/android/services/telephony/domainselection/OWNERS b/tests/src/com/android/services/telephony/domainselection/OWNERS
new file mode 100644
index 0000000..b9112be
--- /dev/null
+++ b/tests/src/com/android/services/telephony/domainselection/OWNERS
@@ -0,0 +1,8 @@
+# automatically inherit owners from fw/opt/telephony
+
+hwangoo@google.com
+forestchoi@google.com
+avinashmp@google.com
+mkoon@google.com
+seheele@google.com
+radhikaagrawal@google.com