Merge "Apply feature flag inject approach" into main
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 074de4a..5c8504a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -169,6 +169,9 @@
<!-- Needed to register for UWB state changes for satellite communication -->
<uses-permission android:name="android.permission.UWB_PRIVILEGED"/>
+ <!-- Needed to initiate configuration update -->
+ <uses-permission android:name="android.permission.UPDATE_CONFIG"/>
+
<!-- Needed to bind the domain selection service. -->
<uses-permission android:name="android.permission.BIND_DOMAIN_SELECTION_SERVICE" />
@@ -577,6 +580,16 @@
</intent-filter>
</receiver>
+ <!-- Update configuration data file -->
+ <receiver android:name="com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.os.action.UPDATE_CONFIG" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
<receiver
android:name="com.android.internal.telephony.uicc.ShowInstallAppNotificationReceiver"
android:exported="false"/>
diff --git a/assets/CarrierRestrictionOperatorDetails.json b/assets/CarrierRestrictionOperatorDetails.json
index f3da100..8602d4e 100644
--- a/assets/CarrierRestrictionOperatorDetails.json
+++ b/assets/CarrierRestrictionOperatorDetails.json
@@ -1,5 +1,6 @@
{
"_comment": "Operator should register with its application package name, carrierId and all the corresponding SHAIDs",
"_comment": "Example format :: << \"packageName\" : {\"carrierId\":<int>, \"callerSHA1Id\":[<SHAID1>, <SHAID2>]} >>",
- "com.vzw.hss.myverizon":{"carrierId":1839,"callerSHA1Id":["C58EE7871896786F8BF70EBDB137DE10074043E9","AE23A03436DF07B0CD70FE881CDA2EC1D21215D7B7B0CC68E67B67F5DF89526A"]}
+ "com.vzw.hss.myverizon":{"carrierId":1839,"callerSHA1Id":["C58EE7871896786F8BF70EBDB137DE10074043E9","AE23A03436DF07B0CD70FE881CDA2EC1D21215D7B7B0CC68E67B67F5DF89526A"]},
+ "com.google.android.apps.tycho":{"carrierId":1989,"callerSHA1Id":["B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB51465350","4C36AF4A5BDAD97C1F3D8B283416D244496C2AC5EAFE8226079EF6F676FD1859"]}
}
\ No newline at end of file
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index f24af53..2bd6ac9 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -617,7 +617,7 @@
<string name="ota_title_activate" msgid="4049645324841263423">"Aktivoi puhelin"</string>
<string name="ota_touch_activate" msgid="838764494319694754">"Sinun täytyy soittaa erityinen puhelu aktivoidaksesi puhelimesi palvelun. \n\nPaina Aktivoi ja aktivoi puhelimesi kuulemiesi ohjeiden avulla."</string>
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"Aktivoidaan…"</string>
- <string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Puhelimen mobiilitiedonsiirtopalvelua aktivoidaan.\n\nAktivointi voi kestää viisi minuuttia."</string>
+ <string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Puhelimen mobiilidatapalvelua aktivoidaan.\n\nAktivointi voi kestää viisi minuuttia."</string>
<string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"Ohitetaanko aktivointi?"</string>
<string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Jos ohitat aktivoinnin, et voi soittaa puheluita etkä muodostaa verkkoyhteyttä (voit tosin muodostaa yhteyden Wi-Fi-verkkoihin). Sinua pyydetään aktivoimaan puhelimesi aina kun käynnistät sen siihen saakka, että aktivoit sen."</string>
<string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"Ohita"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index a51c72d..78e4cfc 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -321,9 +321,9 @@
<string name="throttle_help" msgid="2624535757028809735">"למידע נוסף"</string>
<string name="throttle_status_subtext" msgid="1110276415078236687">"<xliff:g id="USED_0">%1$s</xliff:g> (<xliff:g id="USED_1">%2$d</xliff:g>%%) מתוך התקופה המרבית של <xliff:g id="USED_2">%3$s</xliff:g>\nהתקופה הבאה מתחילה בעוד <xliff:g id="USED_3">%4$d</xliff:g> ימים (<xliff:g id="USED_4">%5$s</xliff:g>)"</string>
<string name="throttle_data_usage_subtext" msgid="3185429653996709840">"<xliff:g id="USED_0">%1$s</xliff:g> (<xliff:g id="USED_1">%2$d</xliff:g>??) מתוך התקופה המרבית של<xliff:g id="USED_2">%3$s</xliff:g>"</string>
- <string name="throttle_data_rate_reduced_subtext" msgid="8369839346277847725">"<xliff:g id="USED_0">%1$s</xliff:g> חריגה מהמקסימום\nקצב הנתונים ירד ל-<xliff:g id="USED_1">%2$d</xliff:g> Kb לשנייה"</string>
+ <string name="throttle_data_rate_reduced_subtext" msgid="8369839346277847725">"<xliff:g id="USED_0">%1$s</xliff:g> חריגה מהמקסימום\nקצב הנתונים ירד ל-<xliff:g id="USED_1">%2$d</xliff:g>Kb לשנייה"</string>
<string name="throttle_time_frame_subtext" msgid="6462089615392402127">"<xliff:g id="USED_0">%1$d</xliff:g>?? מהמחזור חלפו\nהתקופה הבאה מתחילה בעוד <xliff:g id="USED_1">%2$d</xliff:g> ימים (<xliff:g id="USED_2">%3$s</xliff:g>)"</string>
- <string name="throttle_rate_subtext" msgid="7221971817325779535">"קצב הנתונים יורד ל-<xliff:g id="USED">%1$d</xliff:g> Kb לשנייה במקרה של חריגה ממגבלת השימוש בנתונים"</string>
+ <string name="throttle_rate_subtext" msgid="7221971817325779535">"קצב הנתונים יורד ל-<xliff:g id="USED">%1$d</xliff:g>Kb לשנייה במקרה של חריגה ממגבלת השימוש בנתונים"</string>
<string name="throttle_help_subtext" msgid="2817114897095534807">"למידע נוסף על מדיניות השימוש בנתונים ברשת הסלולרית של הספק שלך"</string>
<string name="cell_broadcast_sms" msgid="4053449797289031063">"SMS בשידור סלולרי"</string>
<string name="enable_disable_cell_bc_sms" msgid="4759958924031721350">"SMS בשידור סלולרי"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 76dee50..1201657 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -296,7 +296,7 @@
<string name="limited_sim_function_with_phone_num_notification_message" msgid="5928988883403677610">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> चे कॉल आणि डेटा सेवा <xliff:g id="PHONE_NUMBER">%2$s</xliff:g> वापरताना ब्लॉक केले जाऊ शकतात."</string>
<string name="limited_sim_function_notification_message" msgid="5338638075496721160">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> चे कॉल आणि डेटा सेवा दुसरे सिम वापरताना ब्लॉक केले जाऊ शकतात."</string>
<string name="sip_accounts_removed_notification_title" msgid="3528076957535736095">"आढळलेली आणि काढून टाकलेली कालबाह्य झालेली SIP खाती"</string>
- <string name="sip_accounts_removed_notification_message" msgid="1916856744869791592">"Android प्लॅटफॉर्मवर आता SIP कॉलिंगला सपोर्ट नाही.\nतुमची अस्तित्वात असलेली SIP खाती <xliff:g id="REMOVED_SIP_ACCOUNTS">%s</xliff:g> काढून टाकली आहेत.\nकृपया तुमच्या कॉलिंगसंबंधित डीफॉल्ट खात्याचे सेटिंग कंफर्म करा."</string>
+ <string name="sip_accounts_removed_notification_message" msgid="1916856744869791592">"Android प्लॅटफॉर्मवर आता SIP कॉलिंगला सपोर्ट नाही.\nतुमची अस्तित्वात असलेली SIP खाती <xliff:g id="REMOVED_SIP_ACCOUNTS">%s</xliff:g> काढून टाकली आहेत.\nकृपया तुमच्या कॉलिंगसंबंधित डीफॉल्ट खात्याचे सेटिंग कन्फर्म करा."</string>
<string name="sip_accounts_removed_notification_action" msgid="3772778402370555562">"सेटिंग्जवर जा"</string>
<string name="data_usage_title" msgid="8438592133893837464">"अॅप डेटा वापर"</string>
<string name="data_usage_template" msgid="6287906680674061783">"<xliff:g id="ID_2">%2$s</xliff:g> दरम्यान <xliff:g id="ID_1">%1$s</xliff:g> मोबाइल डेटा वापरला गेला"</string>
@@ -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="608045501232211303">"प्रत्यक्ष चॅनलची कॉंफिगरेशन:"</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/strings.xml b/res/values/strings.xml
index 61143c9..972e7cb 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1206,8 +1206,13 @@
<string name="incall_error_emergency_only">Not registered on network.</string>
<!-- In-call screen: call failure message displayed in an error dialog -->
<string name="incall_error_out_of_service">Mobile network not available.</string>
+ <!-- In-call screen: call failure message displayed in an error dialog if 2G is disabled -->
+ <string name="incall_error_out_of_service_2g">Mobile network not available.\n\nConnect to a wireless network to make a call.\n\n2G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable "Allow 2G" to continue.</string>
<!-- In-call screen: call failure message displayed in an error dialog -->
<string name="incall_error_out_of_service_wfc">Mobile network is not available. Connect to a wireless network to make a call.</string>
+ <!-- In-call screen: call failure message displayed in an error dialog if the user disabled 2G -->
+ <string name="incall_error_out_of_service_wfc_2g_user">Mobile network is not available.\n\nConnect to a wireless network to make a call.\n\n2G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable "Allow 2G" to continue.</string>
+
<!-- In-call screen: call failure message displayed in an error dialog -->
<string name="incall_error_no_phone_number_supplied">To place a call, enter a valid number.</string>
<!-- In-call screen: call failure message displayed in an error dialog -->
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index ef71016..9b71919 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -52,6 +52,7 @@
import android.service.carrier.CarrierIdentifier;
import android.service.carrier.CarrierService;
import android.service.carrier.ICarrierService;
+import android.telephony.AnomalyReporter;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
@@ -94,6 +95,7 @@
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
+import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -218,6 +220,10 @@
CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL
};
+ // UUID to report anomaly when config changed reported with subId that map to invalid phone
+ private static final String UUID_NOTIFY_CONFIG_CHANGED_WITH_INVALID_PHONE =
+ "d81cef11-c2f1-4d76-955d-7f50e8590c48";
+
// Handler to process various events.
//
// For each phoneId, the event sequence should be:
@@ -1483,9 +1489,14 @@
int phoneId = SubscriptionManager.getPhoneId(subscriptionId);
if (!SubscriptionManager.isValidPhoneId(phoneId)) {
- logd("Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId);
- throw new IllegalArgumentException(
- "Invalid phoneId " + phoneId + " for subId " + subscriptionId);
+ final String msg =
+ "Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId;
+ if (mFeatureFlags.addAnomalyWhenNotifyConfigChangedWithInvalidPhone()) {
+ AnomalyReporter.reportAnomaly(
+ UUID.fromString(UUID_NOTIFY_CONFIG_CHANGED_WITH_INVALID_PHONE), msg);
+ }
+ logd(msg);
+ throw new IllegalArgumentException(msg);
}
enforceTelephonyFeatureWithException(getCurrentPackageName(),
diff --git a/src/com/android/phone/ChangeIccPinScreen.java b/src/com/android/phone/ChangeIccPinScreen.java
index 5369aa3..0784495 100644
--- a/src/com/android/phone/ChangeIccPinScreen.java
+++ b/src/com/android/phone/ChangeIccPinScreen.java
@@ -18,12 +18,14 @@
import android.app.Activity;
import android.app.AlertDialog;
+import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.UserManager;
import android.text.method.DigitsKeyListener;
import android.util.Log;
import android.view.View;
@@ -46,12 +48,12 @@
private static final boolean DBG = false;
private static final int EVENT_PIN_CHANGED = 100;
-
+
private enum EntryState {
ES_PIN,
ES_PUK
}
-
+
private EntryState mState;
private static final int NO_ERROR = 0;
@@ -61,6 +63,8 @@
private static final int MIN_PIN_LENGTH = 4;
private static final int MAX_PIN_LENGTH = 8;
+ private UserManager mUserManager;
+ private boolean mDisallowedConfig;
private Phone mPhone;
private boolean mChangePin2;
private TextView mBadPinError;
@@ -91,49 +95,74 @@
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ mUserManager = this.getSystemService(UserManager.class);
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
+ mDisallowedConfig = true;
+ }
+
mPhone = PhoneGlobals.getPhone();
resolveIntent();
setContentView(R.layout.change_sim_pin_screen);
+ setupView();
+ mState = EntryState.ES_PIN;
+ }
+
+ private void setupView() {
mOldPin = (EditText) findViewById(R.id.old_pin);
- mOldPin.setKeyListener(DigitsKeyListener.getInstance());
- mOldPin.setMovementMethod(null);
- mOldPin.setOnClickListener(mClicked);
-
mNewPin1 = (EditText) findViewById(R.id.new_pin1);
- mNewPin1.setKeyListener(DigitsKeyListener.getInstance());
- mNewPin1.setMovementMethod(null);
- mNewPin1.setOnClickListener(mClicked);
-
mNewPin2 = (EditText) findViewById(R.id.new_pin2);
- mNewPin2.setKeyListener(DigitsKeyListener.getInstance());
- mNewPin2.setMovementMethod(null);
- mNewPin2.setOnClickListener(mClicked);
-
mBadPinError = (TextView) findViewById(R.id.bad_pin);
mMismatchError = (TextView) findViewById(R.id.mismatch);
-
mButton = (Button) findViewById(R.id.button);
- mButton.setOnClickListener(mClicked);
-
mScrollView = (ScrollView) findViewById(R.id.scroll);
-
mPUKCode = (EditText) findViewById(R.id.puk_code);
- mPUKCode.setKeyListener(DigitsKeyListener.getInstance());
- mPUKCode.setMovementMethod(null);
- mPUKCode.setOnClickListener(mClicked);
-
mPUKSubmit = (Button) findViewById(R.id.puk_submit);
- mPUKSubmit.setOnClickListener(mClicked);
-
mIccPUKPanel = (LinearLayout) findViewById(R.id.puk_panel);
-
int id = mChangePin2 ? R.string.change_pin2 : R.string.change_pin;
setTitle(getResources().getText(id));
-
- mState = EntryState.ES_PIN;
+
+ if (mDisallowedConfig) {
+ mOldPin.setEnabled(false);
+ mOldPin.setAlpha(.5f);
+
+ mNewPin1.setEnabled(false);
+ mNewPin1.setAlpha(.5f);
+
+ mNewPin2.setEnabled(false);
+ mNewPin2.setAlpha(.5f);
+
+ mButton.setEnabled(false);
+ mButton.setAlpha(.5f);
+
+ mPUKCode.setEnabled(false);
+ mPUKCode.setAlpha(.5f);
+
+ mPUKSubmit.setEnabled(false);
+ mPUKSubmit.setAlpha(.5f);
+ } else {
+ mOldPin.setKeyListener(DigitsKeyListener.getInstance());
+ mOldPin.setMovementMethod(null);
+ mOldPin.setOnClickListener(mClicked);
+
+ mNewPin1.setKeyListener(DigitsKeyListener.getInstance());
+ mNewPin1.setMovementMethod(null);
+ mNewPin1.setOnClickListener(mClicked);
+
+ mNewPin2.setKeyListener(DigitsKeyListener.getInstance());
+ mNewPin2.setMovementMethod(null);
+ mNewPin2.setOnClickListener(mClicked);
+
+ mButton.setOnClickListener(mClicked);
+
+ mPUKCode.setKeyListener(DigitsKeyListener.getInstance());
+ mPUKCode.setMovementMethod(null);
+ mPUKCode.setOnClickListener(mClicked);
+
+ mPUKSubmit.setOnClickListener(mClicked);
+ }
}
private void resolveIntent() {
diff --git a/src/com/android/phone/EnableIccPinScreen.java b/src/com/android/phone/EnableIccPinScreen.java
index 160978f..092fa64 100644
--- a/src/com/android/phone/EnableIccPinScreen.java
+++ b/src/com/android/phone/EnableIccPinScreen.java
@@ -17,10 +17,12 @@
package com.android.phone;
import android.app.Activity;
+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.text.TextUtils;
import android.text.method.DigitsKeyListener;
import android.util.Log;
@@ -41,11 +43,13 @@
private static final int ENABLE_ICC_PIN_COMPLETE = 100;
private static final boolean DBG = false;
+ private UserManager mUserManager;
private LinearLayout mPinFieldContainer;
private EditText mPinField;
private TextView mStatusField;
private boolean mEnable;
private Phone mPhone;
+ private boolean mDisallowedConfig = false;
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
@@ -64,6 +68,11 @@
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ mUserManager = this.getSystemService(UserManager.class);
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
+ mDisallowedConfig = true;
+ }
+
setContentView(R.layout.enable_sim_pin_screen);
setupView();
@@ -76,12 +85,20 @@
private void setupView() {
mPinField = (EditText) findViewById(R.id.pin);
- mPinField.setKeyListener(DigitsKeyListener.getInstance());
- mPinField.setMovementMethod(null);
- mPinField.setOnClickListener(mClicked);
-
mPinFieldContainer = (LinearLayout) findViewById(R.id.pinc);
mStatusField = (TextView) findViewById(R.id.status);
+
+ if (mDisallowedConfig) {
+ mPinField.setEnabled(false);
+ mPinField.setAlpha(.5f);
+
+ mPinFieldContainer.setEnabled(false);
+ mPinFieldContainer.setAlpha(.5f);
+ } else {
+ mPinField.setKeyListener(DigitsKeyListener.getInstance());
+ mPinField.setMovementMethod(null);
+ mPinField.setOnClickListener(mClicked);
+ }
}
private void showStatus(CharSequence statusMsg) {
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 839d8cb..e18818c 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -8504,7 +8504,8 @@
setNetworkSelectionModeAutomatic(subId);
Phone phone = getPhone(subId);
cleanUpAllowedNetworkTypes(phone, subId);
- setDataRoamingEnabled(subId, getDefaultDataRoamingEnabled(subId));
+ setDataRoamingEnabled(subId, phone == null ? false
+ : phone.getDataSettingsManager().isDefaultDataRoamingEnabled());
getPhone(subId).resetCarrierKeysForImsiEncryption();
}
// There has been issues when Sms raw table somehow stores orphan
@@ -10107,20 +10108,6 @@
}
/**
- * Returns true if the data roaming is enabled by default, i.e the system property
- * of {@link #DEFAULT_DATA_ROAMING_PROPERTY_NAME} is true or the config of
- * {@link CarrierConfigManager#KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL} is true.
- */
- private boolean getDefaultDataRoamingEnabled(int subId) {
- final CarrierConfigManager configMgr = (CarrierConfigManager)
- mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
- boolean isDataRoamingEnabled = TelephonyProperties.data_roaming().orElse(false);
- isDataRoamingEnabled |= configMgr.getConfigForSubId(subId).getBoolean(
- CarrierConfigManager.KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL);
- return isDataRoamingEnabled;
- }
-
- /**
* Returns the default network type for the given {@code subId}, if the default network type is
* not set, return {@link Phone#PREFERRED_NT_MODE}.
*/
diff --git a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
index 76032f8..36280e9 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
@@ -51,6 +51,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyCountryDetector;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.satellite.SatelliteConfig;
import com.android.internal.telephony.satellite.SatelliteController;
import com.android.phone.PhoneGlobals;
@@ -106,6 +107,7 @@
private static final int CMD_IS_SATELLITE_COMMUNICATION_ALLOWED = 1;
protected static final int EVENT_WAIT_FOR_CURRENT_LOCATION_TIMEOUT = 2;
protected static final int EVENT_KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT = 3;
+ protected static final int EVENT_CONFIG_DATA_UPDATED = 4;
private static SatelliteAccessController sInstance;
@@ -176,6 +178,8 @@
mCountryDetector = TelephonyCountryDetector.getInstance(context);
mSatelliteController = SatelliteController.getInstance();
loadOverlayConfigs(context);
+ mSatelliteController.registerForConfigUpdateChanged(this, EVENT_CONFIG_DATA_UPDATED,
+ context);
if (s2CellFile != null) {
mSatelliteS2CellFile = s2CellFile;
}
@@ -215,6 +219,9 @@
case EVENT_KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT:
cleanupOnDeviceAccessControllerResources();
break;
+ case EVENT_CONFIG_DATA_UPDATED:
+ updateSatelliteConfigData((Context) msg.obj);
+ break;
default:
logw("SatelliteAccessControllerHandler: unexpected message code: " + msg.what);
break;
@@ -338,6 +345,59 @@
return SystemClock.elapsedRealtimeNanos();
}
+ /**
+ * Update country codes, S2CellFile and satellite region allowed by ConfigUpdater
+ * or CarrierConfig
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public void updateSatelliteConfigData(Context context) {
+ logd("updateSatelliteConfigData");
+
+ SatelliteConfig satelliteConfig = mSatelliteController.getSatelliteConfig();
+ if (satelliteConfig != null && satelliteConfig.getSatelliteS2CellFile(context) != null) {
+ logd("Check mSatelliteS2CellFile from ConfigUpdater");
+ Path pathSatelliteS2CellFile = satelliteConfig.getSatelliteS2CellFile(context);
+ mSatelliteS2CellFile = pathSatelliteS2CellFile.toFile();
+ if (mSatelliteS2CellFile != null && !mSatelliteS2CellFile.exists()) {
+ loge("The satellite S2 cell file " + mSatelliteS2CellFile.getName()
+ + " does not exist");
+ mSatelliteS2CellFile = null;
+ }
+ }
+
+ if (mSatelliteS2CellFile == null) {
+ logd("Check mSatelliteS2CellFile from CarrierConfig");
+ String satelliteS2CellFileName = getSatelliteS2CellFileFromOverlayConfig(context);
+ mSatelliteS2CellFile = TextUtils.isEmpty(satelliteS2CellFileName)
+ ? null : new File(satelliteS2CellFileName);
+ if (mSatelliteS2CellFile != null && !mSatelliteS2CellFile.exists()) {
+ loge("The satellite S2 cell file " + mSatelliteS2CellFile.getName()
+ + " does not exist");
+ mSatelliteS2CellFile = null;
+ }
+ }
+
+ if (mSatelliteS2CellFile == null) {
+ logd("Since mSatelliteS2CellFile is null, don't need to refer other configurations");
+ return;
+ }
+
+ if (satelliteConfig != null
+ && !satelliteConfig.getDeviceSatelliteCountryCodes().isEmpty()) {
+ logd("update mSatelliteCountryCodes by ConfigUpdater");
+ mSatelliteCountryCodes = satelliteConfig.getDeviceSatelliteCountryCodes();
+ } else {
+ mSatelliteCountryCodes = getSatelliteCountryCodesFromOverlayConfig(context);
+ }
+
+ if (satelliteConfig != null && satelliteConfig.isSatelliteDataForAllowedRegion() != null) {
+ logd("update mIsSatelliteAllowAccessControl by ConfigUpdater");
+ mIsSatelliteAllowAccessControl = satelliteConfig.isSatelliteDataForAllowedRegion();
+ } else {
+ mIsSatelliteAllowAccessControl = getSatelliteAccessAllowFromOverlayConfig(context);
+ }
+ }
+
private void loadOverlayConfigs(@NonNull Context context) {
mSatelliteCountryCodes = getSatelliteCountryCodesFromOverlayConfig(context);
mIsSatelliteAllowAccessControl = getSatelliteAccessAllowFromOverlayConfig(context);
diff --git a/src/com/android/phone/security/SafetySourceReceiver.java b/src/com/android/phone/security/SafetySourceReceiver.java
index d2be1a1..76f8e72 100644
--- a/src/com/android/phone/security/SafetySourceReceiver.java
+++ b/src/com/android/phone/security/SafetySourceReceiver.java
@@ -28,8 +28,10 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.flags.Flags;
import com.android.phone.PhoneGlobals;
+import com.android.telephony.Rlog;
public class SafetySourceReceiver extends BroadcastReceiver {
+ private static final String TAG = "TelephonySafetySourceReceiver";
@Override
public void onReceive(Context context, Intent intent) {
@@ -72,6 +74,11 @@
@VisibleForTesting
public Phone getDefaultPhone() {
- return PhoneGlobals.getPhone();
+ try {
+ return PhoneGlobals.getPhone();
+ } catch (IllegalStateException e) {
+ Rlog.i(TAG, "Unable to get phone. Skipping safety source refresh: " + e.getMessage());
+ }
+ return null;
}
}
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index 91ecb93..ddcb5aa 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -23,12 +23,15 @@
import android.telecom.DisconnectCause;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import android.telephony.ims.ImsReasonInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.CallFailCause;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.FeatureFlagsImpl;
import com.android.phone.ImsUtil;
import com.android.phone.PhoneGlobals;
import com.android.phone.R;
@@ -86,7 +89,7 @@
public static DisconnectCause toTelecomDisconnectCause(int telephonyDisconnectCause,
String reason, int phoneId) {
return toTelecomDisconnectCause(telephonyDisconnectCause, CallFailCause.NOT_VALID,
- reason, phoneId, null, new FlagsAdapterImpl());
+ reason, phoneId, null, new FlagsAdapterImpl(), false);
}
/**
@@ -103,7 +106,27 @@
int telephonyDisconnectCause, int telephonyPreciseDisconnectCause, String reason,
int phoneId, ImsReasonInfo imsReasonInfo, FlagsAdapter featureFlags) {
return toTelecomDisconnectCause(telephonyDisconnectCause, telephonyPreciseDisconnectCause,
- reason, phoneId, imsReasonInfo, getCarrierConfigBundle(phoneId), featureFlags);
+ reason, phoneId, imsReasonInfo, getCarrierConfigBundle(phoneId), featureFlags,
+ false);
+ }
+
+ /**
+ * Converts from a disconnect code in {@link android.telephony.DisconnectCause} into a more
+ * generic {@link android.telecom.DisconnectCause}.object, possibly populated with a localized
+ * message and tone for Slot.
+ * @param telephonyDisconnectCause The code for the reason for the disconnect.
+ * @param telephonyPreciseDisconnectCause The code for the precise reason for the disconnect.
+ * @param reason Description of the reason for the disconnect, not intended for the user to see.
+ * @param phoneId To support localized message based on phoneId
+ * @param imsReasonInfo
+ */
+ public static DisconnectCause toTelecomDisconnectCause(
+ int telephonyDisconnectCause, int telephonyPreciseDisconnectCause, String reason,
+ int phoneId, ImsReasonInfo imsReasonInfo, FlagsAdapter featureFlags,
+ boolean shouldTreatAsEmergency) {
+ return toTelecomDisconnectCause(telephonyDisconnectCause, telephonyPreciseDisconnectCause,
+ reason, phoneId, imsReasonInfo, getCarrierConfigBundle(phoneId), featureFlags,
+ shouldTreatAsEmergency);
}
/**
@@ -116,19 +139,23 @@
static DisconnectCause toTelecomDisconnectCause(
int telephonyDisconnectCause, int telephonyPreciseDisconnectCause, String reason,
int phoneId, ImsReasonInfo imsReasonInfo, PersistableBundle carrierConfig,
- FlagsAdapter featureFlags) {
+ FlagsAdapter featureFlags, boolean shouldTreatAsEmergency) {
Context context = PhoneGlobals.getInstance();
- return new DisconnectCause(
- toTelecomDisconnectCauseCode(telephonyDisconnectCause, carrierConfig),
- toTelecomDisconnectCauseLabel(context, telephonyDisconnectCause,
- telephonyPreciseDisconnectCause, carrierConfig, featureFlags),
- toTelecomDisconnectCauseDescription(context, telephonyDisconnectCause, phoneId),
- toTelecomDisconnectReason(context, telephonyDisconnectCause, reason, phoneId),
- toTelecomDisconnectCauseTone(telephonyDisconnectCause, carrierConfig, featureFlags),
- telephonyDisconnectCause,
- telephonyPreciseDisconnectCause,
- imsReasonInfo);
+ return new DisconnectCause.Builder()
+ .setCode(toTelecomDisconnectCauseCode(telephonyDisconnectCause, carrierConfig))
+ .setLabel(toTelecomDisconnectCauseLabel(context, telephonyDisconnectCause,
+ telephonyPreciseDisconnectCause, carrierConfig, featureFlags))
+ .setDescription(toTelecomDisconnectCauseDescription(
+ context, telephonyDisconnectCause, phoneId, shouldTreatAsEmergency))
+ .setReason(toTelecomDisconnectReason(
+ context, telephonyDisconnectCause, reason, phoneId))
+ .setTone(toTelecomDisconnectCauseTone(
+ telephonyDisconnectCause, carrierConfig, featureFlags))
+ .setTelephonyDisconnectCause(telephonyDisconnectCause)
+ .setTelephonyPreciseDisconnectCause(telephonyPreciseDisconnectCause)
+ .setImsReasonInfo(imsReasonInfo)
+ .build();
}
/**
@@ -629,7 +656,8 @@
* Returns a description of the disconnect cause to be shown to the user.
*/
private static CharSequence toTelecomDisconnectCauseDescription(
- Context context, int telephonyDisconnectCause, int phoneId) {
+ Context context, int telephonyDisconnectCause, int phoneId,
+ boolean shouldTreatAsEmergency) {
if (context == null ) {
return "";
}
@@ -752,14 +780,31 @@
case android.telephony.DisconnectCause.OUT_OF_SERVICE:
// No network connection.
+ FeatureFlags mFeatureFlags = new FeatureFlagsImpl();
if (ImsUtil.shouldPromoteWfc(context, phoneId)) {
resourceId = R.string.incall_error_promote_wfc;
} else if (ImsUtil.isWfcModeWifiOnly(context, phoneId)) {
resourceId = R.string.incall_error_wfc_only_no_wireless_network;
} else if (ImsUtil.isWfcEnabled(context, phoneId)) {
- resourceId = R.string.incall_error_out_of_service_wfc;
+ if (!mFeatureFlags.showCallFailNotificationFor2gToggle()) {
+ resourceId = R.string.incall_error_out_of_service_wfc;
+ break;
+ }
+ if (is2gDisabled(phoneId) && !shouldTreatAsEmergency) {
+ resourceId = R.string.incall_error_out_of_service_wfc_2g_user;
+ } else {
+ resourceId = R.string.incall_error_out_of_service_wfc;
+ }
} else {
- resourceId = R.string.incall_error_out_of_service;
+ if (!mFeatureFlags.showCallFailNotificationFor2gToggle()) {
+ resourceId = R.string.incall_error_out_of_service;
+ break;
+ }
+ if (is2gDisabled(phoneId) && !shouldTreatAsEmergency) {
+ resourceId = R.string.incall_error_out_of_service_2g;
+ } else {
+ resourceId = R.string.incall_error_out_of_service;
+ }
}
break;
@@ -982,4 +1027,18 @@
return config;
}
+ /**
+ * Returns true if 2G is disabled.
+ */
+ protected static boolean is2gDisabled(int phoneId) {
+ Phone phone = PhoneFactory.getPhone(phoneId);
+ if (phone == null) {
+ return false;
+ }
+ long bitmask2g = TelephonyManager.NETWORK_CLASS_BITMASK_2G;
+ long currentlyAllowedNetworkTypes = phone.getAllowedNetworkTypes(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
+ boolean is2gEnabled = (currentlyAllowedNetworkTypes & bitmask2g) != 0;
+ return !is2gEnabled;
+ }
}
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 7749a2c..5bfad6b 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -2561,7 +2561,8 @@
preciseDisconnectCause,
mOriginalConnection.getVendorDisconnectCause(),
getPhone().getPhoneId(), imsReasonInfo,
- new FlagsAdapterImpl()));
+ new FlagsAdapterImpl(),
+ shouldTreatAsEmergencyCall()));
close();
}
break;
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 2abf1e2..67b32df 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -141,6 +141,9 @@
// existing call.
private static final int DEFAULT_DSDA_OUTGOING_CALL_HOLD_TIMEOUT_MS = 2000;
+ // Timeout to wait for the termination of incoming call before continue with the emergency call.
+ private static final int DEFAULT_REJECT_INCOMING_CALL_TIMEOUT_MS = 10 * 1000; // 10 seconds.
+
// If configured, reject attempts to dial numbers matching this pattern.
private static final Pattern CDMA_ACTIVATION_CODE_REGEX_PATTERN =
Pattern.compile("\\*228[0-9]{0,2}");
@@ -706,6 +709,20 @@
}
}
+ private static class OnDisconnectListener extends
+ com.android.internal.telephony.Connection.ListenerBase {
+ private final CompletableFuture<Boolean> mFuture;
+
+ OnDisconnectListener(CompletableFuture<Boolean> future) {
+ mFuture = future;
+ }
+
+ @Override
+ public void onDisconnect(int cause) {
+ mFuture.complete(true);
+ }
+ };
+
private final DomainSelectionConnection.DomainSelectionConnectionCallback
mEmergencyDomainSelectionConnectionCallback =
new DomainSelectionConnection.DomainSelectionConnectionCallback() {
@@ -1252,27 +1269,9 @@
final Connection resultConnection = getTelephonyConnection(request, numberToDial,
true, handle, phone);
- CompletableFuture<Void> maybeHoldFuture = CompletableFuture.completedFuture(null);
- if (mTelephonyManagerProxy.isConcurrentCallsPossible()
- && shouldHoldForEmergencyCall(phone)) {
- // If the PhoneAccountHandle was adjusted on building the TelephonyConnection,
- // the relevant PhoneAccountHandle will be updated in resultConnection.
- PhoneAccountHandle phoneAccountHandle =
- resultConnection.getPhoneAccountHandle() == null
- ? request.getAccountHandle() : resultConnection.getPhoneAccountHandle();
- Conferenceable c = maybeHoldCallsOnOtherSubs(phoneAccountHandle);
- if (c != null) {
- maybeHoldFuture = delayDialForOtherSubHold(phone, c, (success) -> {
- Log.i(this, "onCreateOutgoingConn emergency-"
- + " delayDialForOtherSubHold success = " + success);
- if (!success) {
- // Terminates the existing call to make way for the emergency call.
- hangup(c, android.telephony.DisconnectCause
- .OUTGOING_EMERGENCY_CALL_PLACED);
- }
- });
- }
- }
+ CompletableFuture<Void> maybeHoldFuture =
+ checkAndHoldCallsOnOtherSubsForEmergencyCall(request,
+ resultConnection, phone);
Consumer<Boolean> ddsSwitchConsumer = (result) -> {
Log.i(this, "onCreateOutgoingConn emergency-"
+ " delayDialForDdsSwitch result = " + result);
@@ -1284,6 +1283,32 @@
}
}
+ private CompletableFuture<Void> checkAndHoldCallsOnOtherSubsForEmergencyCall(
+ ConnectionRequest request, Connection resultConnection, Phone phone) {
+ CompletableFuture<Void> maybeHoldFuture = CompletableFuture.completedFuture(null);
+ if (mTelephonyManagerProxy.isConcurrentCallsPossible()
+ && shouldHoldForEmergencyCall(phone)) {
+ // If the PhoneAccountHandle was adjusted on building the TelephonyConnection,
+ // the relevant PhoneAccountHandle will be updated in resultConnection.
+ PhoneAccountHandle phoneAccountHandle =
+ resultConnection.getPhoneAccountHandle() == null
+ ? request.getAccountHandle() : resultConnection.getPhoneAccountHandle();
+ Conferenceable c = maybeHoldCallsOnOtherSubs(phoneAccountHandle);
+ if (c != null) {
+ maybeHoldFuture = delayDialForOtherSubHold(phone, c, (success) -> {
+ Log.i(this, "checkAndHoldCallsOnOtherSubsForEmergencyCall"
+ + " delayDialForOtherSubHold success = " + success);
+ if (!success) {
+ // Terminates the existing call to make way for the emergency call.
+ hangup(c, android.telephony.DisconnectCause
+ .OUTGOING_EMERGENCY_CALL_PLACED);
+ }
+ });
+ }
+ }
+ return maybeHoldFuture;
+ }
+
private Connection placeOutgoingConnection(ConnectionRequest request,
Connection resultConnection, Phone phone) {
// If there was a failure, the resulting connection will not be a TelephonyConnection,
@@ -2431,6 +2456,32 @@
Log.i(this, "placeEmergencyConnection");
mIsEmergencyCallPending = true;
+ mEmergencyConnection = (TelephonyConnection) resultConnection;
+ }
+
+ CompletableFuture<Void> maybeHoldFuture =
+ checkAndHoldCallsOnOtherSubsForEmergencyCall(request, resultConnection, phone);
+ maybeHoldFuture.thenRun(() -> placeEmergencyConnectionInternal(resultConnection,
+ phone, request, numberToDial, isTestEmergencyNumber, needToTurnOnRadio));
+
+ // Non TelephonyConnection type instance means dialing failure.
+ return resultConnection;
+ }
+
+ @SuppressWarnings("FutureReturnValueIgnored")
+ private void placeEmergencyConnectionInternal(final Connection resultConnection,
+ final Phone phone, final ConnectionRequest request,
+ final String numberToDial, final boolean isTestEmergencyNumber,
+ final boolean needToTurnOnRadio) {
+
+ if (mEmergencyConnection == null) {
+ Log.i(this, "placeEmergencyConnectionInternal dialing canceled");
+ return;
+ }
+
+ if (resultConnection instanceof TelephonyConnection) {
+ Log.i(this, "placeEmergencyConnectionInternal");
+
((TelephonyConnection) resultConnection).addTelephonyConnectionListener(
mEmergencyConnectionListener);
@@ -2438,7 +2489,6 @@
mEmergencyStateTracker = EmergencyStateTracker.getInstance();
}
- mEmergencyConnection = (TelephonyConnection) resultConnection;
CompletableFuture<Integer> future = mEmergencyStateTracker.startEmergencyCall(
phone, resultConnection, isTestEmergencyNumber);
future.thenAccept((result) -> {
@@ -2464,8 +2514,6 @@
}
});
}
- // Non TelephonyConnection type instance means dialing failure.
- return resultConnection;
}
@SuppressWarnings("FutureReturnValueIgnored")
@@ -2527,8 +2575,13 @@
}
Bundle extras = request.getExtras();
extras.putInt(PhoneConstants.EXTRA_DIAL_DOMAIN, result);
- placeOutgoingConnection(request, resultConnection, phone);
- mIsEmergencyCallPending = false;
+ CompletableFuture<Void> rejectFuture = checkAndRejectIncomingCall(phone, (ret) -> {
+ if (!ret) {
+ Log.i(this, "createEmergencyConnection reject incoming call failed");
+ }
+ });
+ rejectFuture.thenRun(() -> placeEmergencyConnectionOnSelectedDomain(request,
+ resultConnection, phone));
}, mDomainSelectionMainExecutor);
}
@@ -2543,10 +2596,26 @@
Log.i(this, "dialCsEmergencyCall dialing canceled");
return;
}
- placeOutgoingConnection(request, resultConnection, phone);
+ CompletableFuture<Void> future = checkAndRejectIncomingCall(phone, (ret) -> {
+ if (!ret) {
+ Log.i(this, "dialCsEmergencyCall reject incoming call failed");
+ }
+ });
+ future.thenRun(() -> placeEmergencyConnectionOnSelectedDomain(request,
+ resultConnection, phone));
});
}
+ private void placeEmergencyConnectionOnSelectedDomain(ConnectionRequest request,
+ TelephonyConnection resultConnection, Phone phone) {
+ if (mEmergencyConnection == null) {
+ Log.i(this, "placeEmergencyConnectionOnSelectedDomain dialing canceled");
+ return;
+ }
+ placeOutgoingConnection(request, resultConnection, phone);
+ mIsEmergencyCallPending = false;
+ }
+
private void releaseEmergencyCallDomainSelection(boolean cancel, boolean isActive) {
if (mEmergencyCallDomainSelectionConnection != null) {
if (cancel) mEmergencyCallDomainSelectionConnection.cancelSelection();
@@ -2796,11 +2865,29 @@
return false;
}
- private void onEmergencyRedialOnDomain(TelephonyConnection connection,
+ private void onEmergencyRedialOnDomain(final TelephonyConnection connection,
final Phone phone, @NetworkRegistrationInfo.Domain int domain) {
Log.i(this, "onEmergencyRedialOnDomain phoneId=" + phone.getPhoneId()
+ ", domain=" + DomainSelectionService.getDomainName(domain));
+ final Bundle extras = new Bundle();
+ extras.putInt(PhoneConstants.EXTRA_DIAL_DOMAIN, domain);
+
+ CompletableFuture<Void> future = checkAndRejectIncomingCall(phone, (ret) -> {
+ if (!ret) {
+ Log.i(this, "onEmergencyRedialOnDomain reject incoming call failed");
+ }
+ });
+ future.thenRun(() -> onEmergencyRedialOnDomainInternal(connection, phone, extras));
+ }
+
+ private void onEmergencyRedialOnDomainInternal(TelephonyConnection connection,
+ Phone phone, Bundle extras) {
+ if (mEmergencyConnection == null) {
+ Log.i(this, "onEmergencyRedialOnDomainInternal dialing canceled");
+ return;
+ }
+
String number = connection.getAddress().getSchemeSpecificPart();
// Indicates undetectable emergency number with DialArgs
@@ -2809,12 +2896,9 @@
if (connection.getEmergencyServiceCategory() != null) {
isEmergency = true;
eccCategory = connection.getEmergencyServiceCategory();
- Log.i(this, "onEmergencyRedialOnDomain eccCategory=" + eccCategory);
+ Log.i(this, "onEmergencyRedialOnDomainInternal eccCategory=" + eccCategory);
}
- Bundle extras = new Bundle();
- extras.putInt(PhoneConstants.EXTRA_DIAL_DOMAIN, domain);
-
com.android.internal.telephony.Connection originalConnection =
connection.getOriginalConnection();
try {
@@ -2829,14 +2913,20 @@
connection::registerForCallEvents);
}
} catch (CallStateException e) {
- Log.e(this, e, "onEmergencyRedialOnDomain, exception: " + e);
+ Log.e(this, e, "onEmergencyRedialOnDomainInternal, exception: " + e);
+ onLocalHangup(connection);
+ connection.unregisterForCallEvents();
+ handleCallStateException(e, connection, phone);
+ return;
}
if (originalConnection == null) {
- Log.d(this, "onEmergencyRedialOnDomain, phone.dial returned null");
- connection.setDisconnected(
+ Log.d(this, "onEmergencyRedialOnDomainInternal, phone.dial returned null");
+ onLocalHangup(connection);
+ connection.setTelephonyConnectionDisconnected(
mDisconnectCauseFactory.toTelecomDisconnectCause(
android.telephony.DisconnectCause.ERROR_UNSPECIFIED,
"unknown error"));
+ connection.close();
} else {
connection.setOriginalConnection(originalConnection);
}
@@ -3384,6 +3474,52 @@
}
/**
+ * If needed, block until an incoming call is disconnected for outgoing emergency call,
+ * or timeout expires.
+ * @param phone The Phone to reject the incoming call
+ * @param completeConsumer The consumer to call once rejecting incoming call has been
+ * completed. {@code true} result if the operation commpletes successfully, or
+ * {@code false} if the operation timed out/failed.
+ */
+ private CompletableFuture<Void> checkAndRejectIncomingCall(Phone phone,
+ Consumer<Boolean> completeConsumer) {
+ if (phone == null) {
+ // Unexpected inputs
+ Log.i(this, "checkAndRejectIncomingCall phone is null");
+ completeConsumer.accept(false);
+ return CompletableFuture.completedFuture(null);
+ }
+
+ Call ringingCall = phone.getRingingCall();
+ if (ringingCall == null || !ringingCall.isRinging()) {
+ completeConsumer.accept(true);
+ return CompletableFuture.completedFuture(null);
+ }
+ Log.i(this, "checkAndRejectIncomingCall found a ringing call");
+
+ try {
+ ringingCall.hangup();
+ CompletableFuture<Boolean> future = new CompletableFuture<>();
+ com.android.internal.telephony.Connection cn = ringingCall.getLatestConnection();
+ cn.addListener(new OnDisconnectListener(future));
+ // A timeout that will complete the future to not block the outgoing call indefinitely.
+ CompletableFuture<Boolean> timeout = new CompletableFuture<>();
+ phone.getContext().getMainThreadHandler().postDelayed(
+ () -> timeout.complete(false), DEFAULT_REJECT_INCOMING_CALL_TIMEOUT_MS);
+ // Ensure that the Consumer is completed on the main thread.
+ return future.acceptEitherAsync(timeout, completeConsumer,
+ phone.getContext().getMainExecutor()).exceptionally((ex) -> {
+ Log.w(this, "checkAndRejectIncomingCall - exceptionally= " + ex);
+ return null;
+ });
+ } catch (Exception e) {
+ Log.w(this, "checkAndRejectIncomingCall - exception= " + e.getMessage());
+ completeConsumer.accept(false);
+ return CompletableFuture.completedFuture(null);
+ }
+ }
+
+ /**
* Get the Phone to use for an emergency call of the given emergency number address:
* a) If there are multiple Phones with the Subscriptions that support the emergency number
* address, and one of them is the default voice Phone, consider the default voice phone
diff --git a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
index b790e8a..962cbf1 100644
--- a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
@@ -85,6 +85,7 @@
import android.telephony.TransportSelectorCallback;
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;
@@ -160,6 +161,7 @@
private @RadioAccessNetworkType List<Integer> mLastPreferredNetworks;
private CancellationSignal mCancelSignal;
+ private EmergencyRegistrationResult mLastRegResult;
// Members for carrier configuration
private @RadioAccessNetworkType int[] mImsRatsConfig;
@@ -296,6 +298,7 @@
return;
}
+ mLastRegResult = result;
removeMessages(MSG_NETWORK_SCAN_TIMEOUT);
onWwanNetworkTypeSelected(getAccessNetworkType(result));
mCancelSignal = null;
@@ -335,11 +338,11 @@
private void reselectDomain() {
logi("reselectDomain tryCsWhenPsFails=" + mTryCsWhenPsFails);
- int cause = mSelectionAttributes.getCsDisconnectCause();
+ int cause = getDisconnectCause();
mCrossSimRedialingController.notifyCallFailure(cause);
- if (cause == EMERGENCY_PERM_FAILURE
- || cause == EMERGENCY_TEMP_FAILURE) {
+ if ((cause == EMERGENCY_PERM_FAILURE || cause == EMERGENCY_TEMP_FAILURE)
+ && mCrossSimRedialingController.isThereOtherSlot()) {
logi("reselectDomain should redial on the other subscription");
terminateSelectionForCrossSimRedialing(cause == EMERGENCY_PERM_FAILURE);
return;
@@ -394,6 +397,25 @@
mDomainSelected = false;
}
+ private int getDisconnectCause() {
+ int cause = mSelectionAttributes.getCsDisconnectCause();
+
+ ImsReasonInfo reasonInfo = mSelectionAttributes.getPsDisconnectCause();
+ if (reasonInfo != null) {
+ switch (reasonInfo.getCode()) {
+ case ImsReasonInfo.CODE_EMERGENCY_TEMP_FAILURE:
+ cause = EMERGENCY_TEMP_FAILURE;
+ break;
+ case ImsReasonInfo.CODE_EMERGENCY_PERM_FAILURE:
+ cause = EMERGENCY_PERM_FAILURE;
+ break;
+ default:
+ break;
+ }
+ }
+ return cause;
+ }
+
private void reselectDomainInternal() {
post(() -> {
if (mDestroyed) return;
@@ -426,6 +448,7 @@
logi("selectDomain attr=" + attr);
mTransportSelectorCallback = cb;
mSelectionAttributes = attr;
+ mLastRegResult = mSelectionAttributes.getEmergencyRegistrationResult();
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
mModemCount = tm.getActiveModemCount();
@@ -481,7 +504,26 @@
*/
private void updateCarrierConfiguration() {
CarrierConfigManager configMgr = mContext.getSystemService(CarrierConfigManager.class);
- PersistableBundle b = configMgr.getConfigForSubId(getSubId());
+ PersistableBundle b = configMgr.getConfigForSubId(getSubId(),
+ KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ KEY_EMERGENCY_OVER_IMS_ROAMING_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,
+ KEY_EMERGENCY_OVER_CS_ROAMING_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,
+ KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY,
+ KEY_EMERGENCY_DOMAIN_PREFERENCE_ROAMING_INT_ARRAY,
+ KEY_PREFER_IMS_EMERGENCY_WHEN_VOICE_CALLS_ON_CS_BOOL,
+ KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT,
+ KEY_EMERGENCY_SCAN_TIMER_SEC_INT,
+ KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT,
+ KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT,
+ KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL,
+ KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT,
+ KEY_EMERGENCY_CALL_SETUP_TIMER_ON_CURRENT_NETWORK_SEC_INT,
+ KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL,
+ KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL,
+ KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL,
+ KEY_SCAN_LIMITED_SERVICE_AFTER_VOLTE_FAILURE_BOOL,
+ KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY);
if (b == null) {
b = CarrierConfigManager.getDefaultConfig();
}
@@ -675,6 +717,12 @@
mPsNetworkType = getSelectablePsNetworkType(false);
logi("selectDomain limited service ps=" + accessNetworkTypeToString(mPsNetworkType)
+ ", cs=" + accessNetworkTypeToString(mCsNetworkType));
+ if (!isInRoaming()
+ && (mPreferredNetworkScanType
+ == CarrierConfigManager.ImsEmergency.SCAN_TYPE_FULL_SERVICE)) {
+ requestScan(true);
+ return;
+ }
// If NGRAN, request scan to trigger emergency registration.
if (mPsNetworkType == EUTRAN) {
onWwanNetworkTypeSelected(mPsNetworkType);
@@ -864,10 +912,13 @@
} else if (csPreferred || mLastNetworkType == EUTRAN || mLastNetworkType == NGRAN) {
if (!csPreferred && mLastNetworkType == NGRAN && mLtePreferredAfterNrFailure) {
// LTE is preferred after dialing over NR failed.
- List<Integer> imsRats = getImsNetworkTypeConfiguration();
- imsRats.remove(Integer.valueOf(NGRAN));
- preferredNetworks = generatePreferredNetworks(imsRats,
+ preferredNetworks = generatePreferredNetworks(getImsNetworkTypeConfiguration(),
getCsNetworkTypeConfiguration());
+ // Make NGRAN have the lowest priority
+ if (preferredNetworks.contains(NGRAN)) {
+ preferredNetworks.remove(Integer.valueOf(NGRAN));
+ preferredNetworks.add(NGRAN);
+ }
} else if (csPriority > NOT_SUPPORTED) {
// PS tried, generate the list with CS preferred.
preferredNetworks = generatePreferredNetworks(getCsNetworkTypeConfiguration(),
@@ -1250,8 +1301,7 @@
tm = tm.createForSubscriptionId(getSubId());
String netIso = tm.getNetworkCountryIso();
- EmergencyRegistrationResult regResult =
- mSelectionAttributes.getEmergencyRegistrationResult();
+ EmergencyRegistrationResult regResult = mLastRegResult;
if (regResult != null) {
if (regResult.getRegState() == REGISTRATION_STATE_HOME) return false;
if (regResult.getRegState() == REGISTRATION_STATE_ROAMING) return true;
diff --git a/testapps/GbaTestApp/res/values-mr/strings.xml b/testapps/GbaTestApp/res/values-mr/strings.xml
index 75aaf5f..f8e8992 100644
--- a/testapps/GbaTestApp/res/values-mr/strings.xml
+++ b/testapps/GbaTestApp/res/values-mr/strings.xml
@@ -3,9 +3,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
<string name="label_settings" msgid="8030871890526865502">"सेटिंग्ज"</string>
- <string name="label_carrier" msgid="1470455313066422804">"वाहक कॉंफिगरेशन"</string>
- <string name="label_service" msgid="2668963955237345578">"सेवा कॉंफिगरेशन"</string>
- <string name="label_test" msgid="8425079572898571918">"चाचणी कॉंफिगरेशन"</string>
+ <string name="label_carrier" msgid="1470455313066422804">"वाहकाचे कॉन्फिगरेशन"</string>
+ <string name="label_service" msgid="2668963955237345578">"सेवेचे कॉन्फिगरेशन"</string>
+ <string name="label_test" msgid="8425079572898571918">"चाचणीचे कॉन्फिगरेशन"</string>
<string name="button_name_running" msgid="4557363091224858010">"रन करत आहे"</string>
<string name="button_name_exit" msgid="8025683733431538975">"बाहेर पडा"</string>
<string name="label_test_result" msgid="892984695972956196">"चाचणी परिणाम"</string>
diff --git a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
index c44b347..e6f70aa 100644
--- a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
+++ b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
@@ -23,6 +23,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
@@ -31,7 +32,11 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -57,6 +62,8 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyCountryDetector;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.satellite.SatelliteConfig;
+import com.android.internal.telephony.satellite.SatelliteConfigParser;
import com.android.internal.telephony.satellite.SatelliteController;
import org.junit.After;
@@ -70,6 +77,8 @@
import java.io.File;
import java.lang.reflect.Field;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -531,6 +540,42 @@
assertTrue(mQueriedSatelliteAllowed);
}
+ @Test
+ public void testUpdateSatelliteConfigData() {
+ // Verify the case when the configParser is not exist.
+ SatelliteConfigParser spyConfigParserNull =
+ spy(new SatelliteConfigParser((byte[]) null));
+ doReturn(spyConfigParserNull).when(mMockSatelliteController).getSatelliteConfigParser();
+ mSatelliteAccessControllerUT.updateSatelliteConfigData(mMockContext);
+
+ assertNull(spyConfigParserNull.getConfig());
+
+ // Verify the case when the configParser is exist but empty.
+ SatelliteConfigParser spyConfigParserEmpty =
+ spy(new SatelliteConfigParser("test".getBytes()));
+ doReturn(spyConfigParserEmpty).when(mMockSatelliteController).getSatelliteConfigParser();
+ mSatelliteAccessControllerUT.updateSatelliteConfigData(mMockContext);
+
+ assertNull(spyConfigParserEmpty.getConfig());
+
+ // Verify the case when the configParser is exist and valid data
+ SatelliteConfig mockSatelliteConfig = mock(SatelliteConfig.class);
+ final String filePath = "/data/user_de/0/com.android.phone/app_satellite/s2_cell_file";
+ Path targetSatS2FilePath = Paths.get(filePath);
+ doReturn(false).when(mockSatelliteConfig).isFileExist(any());
+ doReturn(targetSatS2FilePath).when(mockSatelliteConfig)
+ .copySatS2FileToPhoneDirectory(any(), any());
+ doReturn(Arrays.asList("US")).when(mockSatelliteConfig).getDeviceSatelliteCountryCodes();
+ doReturn(false).when(mockSatelliteConfig).isSatelliteDataForAllowedRegion();
+ doReturn(targetSatS2FilePath).when(mockSatelliteConfig).getSatelliteS2CellFile(any());
+ doReturn(mockSatelliteConfig).when(mMockSatelliteController).getSatelliteConfig();
+
+ mSatelliteAccessControllerUT.updateSatelliteConfigData(mMockContext);
+ verify(mockSatelliteConfig, times(0)).getDeviceSatelliteCountryCodes();
+ verify(mockSatelliteConfig, times(0)).isSatelliteDataForAllowedRegion();
+ verify(mockSatelliteConfig, times(2)).getSatelliteS2CellFile(any());
+ }
+
private void clearAllInvocations() {
clearInvocations(mMockSatelliteController);
clearInvocations(mMockSatelliteOnDeviceAccessController);
diff --git a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
index e5f7fd3..71a23e6 100644
--- a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
+++ b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
@@ -152,7 +152,8 @@
android.telecom.DisconnectCause tcCause =
DisconnectCauseUtil.toTelecomDisconnectCause(
DisconnectCause.BUSY, -1 /* precise label is NOT given */,
- EMPTY_STRING, PHONE_ID, null, getBundleWithBusyToneArray(), mFeatureFlags);
+ EMPTY_STRING, PHONE_ID, null, getBundleWithBusyToneArray(), mFeatureFlags,
+ false);
assertBusyCauseWithTargetLabel(R.string.callFailed_userBusy, tcCause);
}
@@ -170,7 +171,8 @@
android.telecom.DisconnectCause tcCause =
DisconnectCauseUtil.toTelecomDisconnectCause(DisconnectCause.BUSY,
CallFailCause.USER_BUSY /* Telephony defined a precise label */,
- EMPTY_STRING, PHONE_ID, null, getBundleWithBusyToneArray(), mFeatureFlags);
+ EMPTY_STRING, PHONE_ID, null, getBundleWithBusyToneArray(), mFeatureFlags,
+ false);
// 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);
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index f0e900a..e791d3c 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -325,6 +325,10 @@
@After
public void tearDown() throws Exception {
+ if (mTestConnectionService != null
+ && mTestConnectionService.getEmergencyConnection() != null) {
+ mTestConnectionService.onLocalHangup(mTestConnectionService.getEmergencyConnection());
+ }
mTestConnectionService = null;
super.tearDown();
}
@@ -1990,6 +1994,27 @@
}
/**
+ * For DSDA devices with AP domain selection service enabled, placing an outgoing call
+ * on a 2nd sub will hold the existing ACTIVE connection on the first sub.
+ */
+ @Test
+ @SmallTest
+ public void testHoldOnOtherSubForVirtualDsdaDeviceWithDomainSelectionEnabled() {
+ when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+
+ 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.
*/
@@ -2267,8 +2292,7 @@
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
- Connection nc = Mockito.mock(Connection.class);
- doReturn(nc).when(mPhone0).dial(anyString(), any(), any());
+ doReturn(mInternalConnection).when(mPhone0).dial(anyString(), any(), any());
verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
DialArgs dialArgs = argsCaptor.getValue();
@@ -2296,8 +2320,131 @@
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
- Connection nc = Mockito.mock(Connection.class);
- doReturn(nc).when(mPhone0).dial(anyString(), any(), any());
+ doReturn(mInternalConnection).when(mPhone0).dial(anyString(), any(), any());
+
+ 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 testDomainSelectionRedialFailedWithException() throws Exception {
+ setupForCallTest();
+
+ int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
+ int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
+ int selectedDomain = DOMAIN_CS;
+
+ TestTelephonyConnection c = setupForReDialForDomainSelection(
+ mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
+
+ CallStateException cse = new CallStateException(CallStateException.ERROR_CALLING_DISABLED,
+ "Calling disabled via ro.telephony.disable-call property");
+ doThrow(cse).when(mPhone0).dial(anyString(), any(), any());
+
+ assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
+ android.telephony.DisconnectCause.NOT_VALID));
+ verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
+ verify(mEmergencyCallDomainSelectionConnection).cancelSelection();
+ verify(mEmergencyStateTracker).endCall(any());
+ }
+
+ @Test
+ public void testDomainSelectionRejectIncoming() throws Exception {
+ setupForCallTest();
+
+ int selectedDomain = DOMAIN_CS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+
+ doReturn(mInternalConnection2).when(mCall).getLatestConnection();
+ doReturn(true).when(mCall).isRinging();
+ doReturn(mCall).when(mPhone0).getRingingCall();
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ ArgumentCaptor<android.telecom.Connection> connectionCaptor =
+ ArgumentCaptor.forClass(android.telecom.Connection.class);
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
+ verify(mEmergencyStateTracker)
+ .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+
+ android.telecom.Connection tc = connectionCaptor.getValue();
+
+ assertNotNull(tc);
+ assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
+ assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
+
+ ArgumentCaptor<Connection.Listener> listenerCaptor =
+ ArgumentCaptor.forClass(Connection.Listener.class);
+
+ verify(mInternalConnection2).addListener(listenerCaptor.capture());
+ verify(mCall).hangup();
+ verify(mPhone0, never()).dial(anyString(), any(), any());
+
+ Connection.Listener listener = listenerCaptor.getValue();
+
+ assertNotNull(listener);
+
+ listener.onDisconnect(0);
+
+ 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 testDomainSelectionRedialRejectIncoming() throws Exception {
+ setupForCallTest();
+
+ int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
+ int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
+ int selectedDomain = DOMAIN_CS;
+
+ TestTelephonyConnection c = setupForReDialForDomainSelection(
+ mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
+
+ doReturn(mInternalConnection2).when(mCall).getLatestConnection();
+ doReturn(true).when(mCall).isRinging();
+ doReturn(mCall).when(mPhone0).getRingingCall();
+
+ assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
+ android.telephony.DisconnectCause.NOT_VALID));
+ verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
+
+ ArgumentCaptor<Connection.Listener> listenerCaptor =
+ ArgumentCaptor.forClass(Connection.Listener.class);
+
+ verify(mInternalConnection2).addListener(listenerCaptor.capture());
+ verify(mCall).hangup();
+ verify(mPhone0, never()).dial(anyString(), any(), any());
+
+ Connection.Listener listener = listenerCaptor.getValue();
+
+ assertNotNull(listener);
+
+ listener.onDisconnect(0);
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
DialArgs dialArgs = argsCaptor.getValue();
@@ -2621,6 +2768,7 @@
setupForDialForDomainSelection(mPhone0, selectedDomain, true);
doReturn(mPhone0).when(mImsPhone).getDefaultPhone();
+ doReturn(mInternalConnection).when(mPhone0).dial(anyString(), any(), any());
TestTelephonyConnection c = setupForReDialForDomainSelection(
mImsPhone, selectedDomain, preciseDisconnectCause, disconnectCause, false);
@@ -2671,6 +2819,7 @@
setupForDialForDomainSelection(mPhone0, selectedDomain, true);
doReturn(mPhone0).when(mImsPhone).getDefaultPhone();
+ doReturn(mInternalConnection).when(mPhone0).dial(anyString(), any(), any());
TestTelephonyConnection c = setupForReDialForDomainSelection(
mImsPhone, selectedDomain, preciseDisconnectCause, disconnectCause, false);
diff --git a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
index 39f01a2..0735c3f 100644
--- a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
@@ -71,6 +71,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyVararg;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
@@ -234,7 +235,7 @@
when(mTelephonyManager.getActiveModemCount()).thenReturn(1);
mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
- when(mCarrierConfigManager.getConfigForSubId(anyInt()))
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg()))
.thenReturn(getDefaultPersistableBundle());
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
@@ -280,6 +281,8 @@
any(), anyInt(), anyBoolean(), any(), any());
when(mResources.getStringArray(anyInt())).thenReturn(null);
+
+ doReturn(false).when(mCsrdCtrl).isThereOtherSlot();
}
@After
@@ -333,7 +336,7 @@
CarrierConfigManager.ImsEmergency.DOMAIN_PS_NON_3GPP,
};
bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -396,7 +399,7 @@
CarrierConfigManager.ImsEmergency.DOMAIN_CS
};
bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
@@ -658,7 +661,7 @@
public void testAirplaneRequiresRegCombinedImsNotRegisteredSelectPs() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -687,7 +690,7 @@
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putIntArray(KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,
new int[0]);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -964,7 +967,7 @@
CarrierConfigManager.ImsEmergency.DOMAIN_CS
};
bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -998,7 +1001,7 @@
CarrierConfigManager.ImsEmergency.DOMAIN_CS
};
bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -1023,7 +1026,7 @@
CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP
};
bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -1349,7 +1352,7 @@
public void testVoLteOnEpsImsNotRegisteredSelectPs() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -1372,7 +1375,7 @@
public void testVoLteOffEpsImsNotRegisteredScanCsPreferred() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
// Disable VoLTE.
when(mMmTelManager.isAdvancedCallingSettingEnabled()).thenReturn(false);
@@ -1398,7 +1401,7 @@
public void testRequiresRegEpsImsNotRegisteredScanCsPreferred() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -1422,7 +1425,7 @@
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -1445,7 +1448,7 @@
throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -1467,7 +1470,7 @@
public void testDefaultEpsImsRegisteredBarredScanTimeoutWifi() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
mResultConsumer = null;
createSelector(SLOT_0_SUB_ID);
@@ -1511,7 +1514,7 @@
TelephonyManager.SIM_STATE_PIN_REQUIRED);
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
@@ -1536,7 +1539,7 @@
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
bundle.putInt(KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT, VOWIFI_REQUIRES_SETTING_ENABLED);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
@@ -1576,7 +1579,7 @@
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
bundle.putInt(KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT, VOWIFI_REQUIRES_VALID_EID);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
@@ -1823,7 +1826,7 @@
public void testFullService() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT, SCAN_TYPE_FULL_SERVICE);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
mResultConsumer = null;
createSelector(SLOT_0_SUB_ID);
@@ -1854,7 +1857,7 @@
public void testFullServiceInRoaming() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT, SCAN_TYPE_FULL_SERVICE);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
@@ -1879,7 +1882,7 @@
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT,
SCAN_TYPE_FULL_SERVICE_FOLLOWED_BY_LIMITED_SERVICE);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
mResultConsumer = null;
createSelector(SLOT_0_SUB_ID);
@@ -2160,7 +2163,7 @@
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_SCAN_LIMITED_SERVICE_AFTER_VOLTE_FAILURE_BOOL,
true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -2219,6 +2222,7 @@
public void testCrossStackTimerTempFailure() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
+ doReturn(true).when(mCsrdCtrl).isThereOtherSlot();
EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
REGISTRATION_STATE_HOME,
@@ -2243,12 +2247,48 @@
processAllMessages();
verify(mCsrdCtrl).notifyCallFailure(eq(PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE));
+ verify(mTransportSelectorCallback)
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_TEMP_FAILURE));
+ }
+
+ @Test
+ public void testCrossStackTimerTempFailureNoValidSubscription() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+ doReturn(false).when(mCsrdCtrl).isThereOtherSlot();
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+
+ attr = new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
+ .setEmergency(true)
+ .setEmergencyRegistrationResult(regResult)
+ .setCsDisconnectCause(PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE)
+ .build();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mCsrdCtrl).notifyCallFailure(eq(PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE));
+ verify(mTransportSelectorCallback, never())
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_TEMP_FAILURE));
}
@Test
public void testCrossStackTimerPermFailure() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
+ doReturn(true).when(mCsrdCtrl).isThereOtherSlot();
EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
REGISTRATION_STATE_HOME,
@@ -2273,6 +2313,41 @@
processAllMessages();
verify(mCsrdCtrl).notifyCallFailure(eq(PreciseDisconnectCause.EMERGENCY_PERM_FAILURE));
+ verify(mTransportSelectorCallback)
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_PERM_FAILURE));
+ }
+
+ @Test
+ public void testCrossStackTimerPermFailureNoValidSubscription() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+ doReturn(false).when(mCsrdCtrl).isThereOtherSlot();
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+
+ attr = new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
+ .setEmergency(true)
+ .setEmergencyRegistrationResult(regResult)
+ .setCsDisconnectCause(PreciseDisconnectCause.EMERGENCY_PERM_FAILURE)
+ .build();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mCsrdCtrl).notifyCallFailure(eq(PreciseDisconnectCause.EMERGENCY_PERM_FAILURE));
+ verify(mTransportSelectorCallback, never())
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_PERM_FAILURE));
}
@Test
@@ -2341,7 +2416,7 @@
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);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
setupForHandleScanResult();
@@ -2366,7 +2441,7 @@
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);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
setupForHandleScanResult();
@@ -2390,7 +2465,7 @@
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);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
setupForHandleScanResult();
@@ -2403,7 +2478,7 @@
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);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
setupForHandleScanResult();
@@ -2428,7 +2503,7 @@
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
bundle.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, 5);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -2482,7 +2557,7 @@
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
bundle.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, 5);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -2561,7 +2636,7 @@
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);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
setupForHandleScanResult();
@@ -2587,7 +2662,7 @@
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
bundle.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, 20);
bundle.putInt(KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT, 2);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
setupForHandleScanResult();
@@ -2747,12 +2822,33 @@
}
@Test
+ public void testDefaultLimitedServiceScanTypeFullService() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT, SCAN_TYPE_FULL_SERVICE);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_UNKNOWN,
+ 0, false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPreferred(DomainSelectionService.SCAN_TYPE_FULL_SERVICE, EUTRAN);
+ }
+
+ @Test
public void testScanLtePreferredAfterNgranFailure() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
new int[] { NGRAN, EUTRAN });
bundle.putBoolean(KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -2773,10 +2869,11 @@
verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
any(), anyInt(), anyBoolean(), any(), any());
- assertEquals(3, mAccessNetwork.size());
+ assertEquals(4, mAccessNetwork.size());
assertEquals(EUTRAN, (int) mAccessNetwork.get(0));
assertEquals(UTRAN, (int) mAccessNetwork.get(1));
assertEquals(GERAN, (int) mAccessNetwork.get(2));
+ assertEquals(NGRAN, (int) mAccessNetwork.get(3));
}
@Test
@@ -3006,12 +3103,64 @@
any(), anyInt(), anyBoolean(), any(), any());
}
+ @Test
+ public void testIsInRoaming() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ int[] domainPreferenceRoam = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_ROAMING_INT_ARRAY, domainPreferenceRoam);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+ doReturn("").when(mTelephonyManager).getNetworkCountryIso();
+ doReturn("us").when(mTelephonyManager).getSimCountryIso();
+
+ mResultConsumer = null;
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegistrationResult 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(), eq(false), any(), any());
+ assertEquals(1, mAccessNetwork.size());
+ assertEquals(EUTRAN, (int) mAccessNetwork.get(0));
+ assertNotNull(mResultConsumer);
+
+ regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "", "zz");
+ mResultConsumer.accept(regResult);
+ processAllMessages();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, times(2)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), eq(false), any(), any());
+ assertEquals(3, mAccessNetwork.size());
+ assertEquals(UTRAN, (int) mAccessNetwork.get(0));
+ assertEquals(GERAN, (int) mAccessNetwork.get(1));
+ assertEquals(EUTRAN, (int) mAccessNetwork.get(2));
+ }
+
private void setupForScanListTest(PersistableBundle bundle) throws Exception {
setupForScanListTest(bundle, false);
}
private void setupForScanListTest(PersistableBundle bundle, boolean psFailed) throws Exception {
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);