Merge "Convert the app signature check to use SHA-256 instead of SHA1." into main
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 819d39b..61ffb02 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -538,7 +538,7 @@
<string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"通話を発信するには、モバイル ネットワークを ON にし、機内モードまたはバッテリー セーバー モードを OFF にしてください。"</string>
<string name="incall_error_power_off" product="default" msgid="8131672264311208673">"電話をかけるには機内モードをオフにしてください。"</string>
<string name="incall_error_power_off_wfc" msgid="9125661184694727052">"電話をかけるには、機内モードをオフにするか無線ネットワークに接続してください。"</string>
- <string name="incall_error_power_off_thermal" product="default" msgid="8695809601655300168"><b>"スマートフォンが熱くなりすぎています"</b>\n\n"この通話を完了できません。スマートフォンの熱が冷めてから、もう一度お試しください。\n\n緊急通報は通常どおり発信できます。"</string>
+ <string name="incall_error_power_off_thermal" product="default" msgid="8695809601655300168"><b>"スマートフォンが熱くなっています"</b>\n\n"この通話を完了できません。スマートフォンの熱が冷めてから、もう一度お試しください。\n\n緊急通報は通常どおり発信できます。"</string>
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"緊急通報以外の通話を発信するには、緊急通報待機モードを終了してください。"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"ご加入の通信サービスがありません"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"モバイルネットワークが利用できません。"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index ed3e472..6cd806b 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -485,7 +485,7 @@
<string name="simContacts_title" msgid="2714029230160136647">"Contacten selecteren om te importeren"</string>
<string name="simContacts_airplaneMode" msgid="4654884030631503808">"Zet de vliegtuigmodus uit om contacten van de simkaart te importeren."</string>
<string name="enable_pin" msgid="967674051730845376">"SIM pincode aan-/uitzetten"</string>
- <string name="change_pin" msgid="3657869530942905790">"Pincode simkaart wijzigen"</string>
+ <string name="change_pin" msgid="3657869530942905790">"Pincode van simkaart wijzigen"</string>
<string name="enter_pin_text" msgid="3182311451978663356">"Pincode simkaart:"</string>
<string name="oldPinLabel" msgid="8618515202411987721">"Oude pincode"</string>
<string name="newPinLabel" msgid="3585899083055354732">"Nieuwe pincode"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 476ab89..397c5c8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1245,7 +1245,9 @@
<!-- In-call screen: call failure message displayed in an error dialog when the user is connected to a wireless network, but wifi calling is turned off. [CHAR_LIMIT=NONE] -->
<string name="incall_error_promote_wfc">Enable Wi-Fi calling to make a call.</string>
<!-- In-call screen: call failure message displayed in an error dialog when the satellite modem is on. [CHAR_LIMIT=NONE] -->
- <string name="incall_error_satellite_enabled">Disable satellite mode to make a call.</string>
+ <string name="incall_error_satellite_enabled">To make a call, first end the satellite connection.</string>
+ <!-- In-call screen: call failure message displayed in an error dialog when device is connected to carrier roaming satellite network [CHAR_LIMIT=NONE] -->
+ <string name="incall_error_carrier_roaming_satellite_mode">You can send and receive messages without a mobile or Wi-Fi network.</string>
<!-- Hint for the button of emergency information -->
<string name="emergency_information_hint">Emergency information</string>
diff --git a/src/com/android/phone/ImsProvisioningController.java b/src/com/android/phone/ImsProvisioningController.java
index b2e34ae..d2c720b 100644
--- a/src/com/android/phone/ImsProvisioningController.java
+++ b/src/com/android/phone/ImsProvisioningController.java
@@ -70,6 +70,7 @@
import com.android.ims.RcsFeatureManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.PhoneConfigurationManager;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.util.HandlerExecutor;
import com.android.telephony.Rlog;
@@ -92,6 +93,7 @@
@VisibleForTesting
protected static final int EVENT_MULTI_SIM_CONFIGURATION_CHANGE = 3;
private static final int EVENT_PROVISIONING_VALUE_CHANGED = 4;
+ private static final int EVENT_NOTIFY_INIT_PROVISIONED_VALUE = 5;
// Provisioning Keys that are handled via AOSP cache and not sent to the ImsService
private static final int[] LOCAL_IMS_CONFIG_KEYS = {
@@ -121,6 +123,11 @@
CAPABILITY_TYPE_CALL_COMPOSER
};
+ private static final int[] LOCAL_RCS_CAPABILITY = {
+ CAPABILITY_TYPE_OPTIONS_UCE,
+ CAPABILITY_TYPE_PRESENCE_UCE
+ };
+
/**
* map the MmTelCapabilities.MmTelCapability and
* CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VOICE_INT
@@ -199,6 +206,7 @@
private final SparseArray<ProvisioningCallbackManager> mProvisioningCallbackManagersSlotMap =
new SparseArray<>();
private final ImsProvisioningLoader mImsProvisioningLoader;
+ private final FeatureFlags mFeatureFlags;
private int mNumSlot;
@@ -253,6 +261,18 @@
+ " value : " + (int) msg.obj);
updateCapabilityTechFromKey(msg.arg1, msg.arg2, (int) msg.obj);
break;
+ case EVENT_NOTIFY_INIT_PROVISIONED_VALUE:
+ int slotId = msg.arg1;
+ int subId = msg.arg2;
+ IFeatureProvisioningCallback callback =
+ (IFeatureProvisioningCallback) msg.obj;
+ log("slotId " + slotId + " subId " + subId
+ + " callback " + (callback != null));
+
+ // Notify MmTel Provisioning Status
+ notifyMmTelProvisioningStatus(slotId, subId, callback);
+ notifyRcsProvisioningStatus(slotId, subId, callback);
+ break;
default:
log("unknown message " + msg);
break;
@@ -508,6 +528,13 @@
// notify provisioning key value to ImsService
setInitialProvisioningKeys(mSubId);
+
+ if (mFeatureFlags.notifyInitialImsProvisioningStatus()) {
+ // Notify MmTel provisioning value based on capability and radio tech.
+ if (mProvisioningCallbackManagersSlotMap.get(mSlotId).hasCallblacks()) {
+ notifyMmTelProvisioningStatus(mSlotId, mSubId, null);
+ }
+ }
} else {
// wait until subId is valid
mRequiredNotify = true;
@@ -740,6 +767,13 @@
// notify provisioning key value to ImsService
setInitialProvisioningKeys(mSubId);
+
+ if (mFeatureFlags.notifyInitialImsProvisioningStatus()) {
+ if (mProvisioningCallbackManagersSlotMap.get(mSlotId).hasCallblacks()) {
+ // Notify RCS provisioning value based on capability and radio tech.
+ notifyRcsProvisioningStatus(mSlotId, mSubId, null);
+ }
+ }
} else {
// wait until subId is valid
mRequiredNotify = true;
@@ -828,7 +862,7 @@
@VisibleForTesting
public ImsProvisioningController(PhoneGlobals app, int numSlot, Looper looper,
MmTelFeatureConnector mmTelFeatureConnector, RcsFeatureConnector rcsFeatureConnector,
- ImsProvisioningLoader imsProvisioningLoader) {
+ ImsProvisioningLoader imsProvisioningLoader, FeatureFlags featureFlags) {
log("ImsProvisioningController");
mApp = app;
mNumSlot = numSlot;
@@ -841,6 +875,7 @@
mTelephonyRegistryManager.addOnSubscriptionsChangedListener(
mSubChangedListener, mHandler::post);
mImsProvisioningLoader = imsProvisioningLoader;
+ mFeatureFlags = featureFlags;
PhoneConfigurationManager.registerForMultiSimConfigChange(mHandler,
EVENT_MULTI_SIM_CONFIGURATION_CHANGE, null);
@@ -924,7 +959,8 @@
* create an instance
*/
@VisibleForTesting
- public static ImsProvisioningController make(PhoneGlobals app, int numSlot) {
+ public static ImsProvisioningController make(PhoneGlobals app, int numSlot,
+ FeatureFlags featureFlags) {
synchronized (ImsProvisioningController.class) {
if (sInstance == null) {
Rlog.i(TAG, "ImsProvisioningController created");
@@ -932,7 +968,7 @@
handlerThread.start();
sInstance = new ImsProvisioningController(app, numSlot, handlerThread.getLooper(),
ImsManager::getConnector, RcsFeatureManager::getConnector,
- new ImsProvisioningLoader(app));
+ new ImsProvisioningLoader(app), featureFlags);
}
}
return sInstance;
@@ -966,6 +1002,11 @@
try {
mProvisioningCallbackManagersSlotMap.get(slotId).registerCallback(callback);
log("Feature Provisioning Callback registered.");
+
+ if (mFeatureFlags.notifyInitialImsProvisioningStatus()) {
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_NOTIFY_INIT_PROVISIONED_VALUE,
+ getSlotId(subId), subId, (Object) callback));
+ }
} catch (NullPointerException e) {
logw("can not access callback manager to add callback");
}
@@ -1639,6 +1680,90 @@
return true;
}
+ private void notifyMmTelProvisioningStatus(int slotId, int subId,
+ @Nullable IFeatureProvisioningCallback callback) {
+ int value = ImsProvisioningLoader.STATUS_NOT_SET;
+ int[] techArray;
+ for (int capability : LOCAL_MMTEL_CAPABILITY) {
+ techArray = getTechsFromCarrierConfig(subId, capability, /*isMmTle*/true);
+ if (techArray == null) {
+ continue;
+ }
+
+ for (int radioTech : techArray) {
+ value = mImsProvisioningLoader.getProvisioningStatus(subId, FEATURE_MMTEL,
+ capability, radioTech);
+ if (value == ImsProvisioningLoader.STATUS_NOT_SET) {
+ // Not yet provisioned
+ continue;
+ }
+
+ value = (value == ImsProvisioningLoader.STATUS_PROVISIONED)
+ ? PROVISIONING_VALUE_ENABLED : PROVISIONING_VALUE_DISABLED;
+
+ // Notify all registered callbacks
+ if (callback == null) {
+ mProvisioningCallbackManagersSlotMap.get(slotId)
+ .notifyProvisioningCapabilityChanged(
+ new FeatureProvisioningData(
+ capability,
+ radioTech,
+ getBoolValue(value),
+ /*isMmTle*/true));
+ } else {
+ try {
+ callback.onFeatureProvisioningChanged(capability, radioTech,
+ getBoolValue(value));
+ } catch (RemoteException e) {
+ logw("notifyMmTelProvisioningStatus callback is not available");
+ }
+ }
+ }
+ }
+ }
+
+ private void notifyRcsProvisioningStatus(int slotId, int subId,
+ @Nullable IFeatureProvisioningCallback callback) {
+ int value = ImsProvisioningLoader.STATUS_NOT_SET;
+ int[] techArray;
+ for (int capability : LOCAL_RCS_CAPABILITY) {
+ techArray = getTechsFromCarrierConfig(subId, capability, /*isMmTle*/false);
+ if (techArray == null) {
+ continue;
+ }
+
+ for (int radioTech : techArray) {
+ value = mImsProvisioningLoader.getProvisioningStatus(subId, FEATURE_RCS,
+ capability, radioTech);
+ if (value == ImsProvisioningLoader.STATUS_NOT_SET) {
+ // Not yet provisioned
+ continue;
+ }
+
+ value = (value == ImsProvisioningLoader.STATUS_PROVISIONED)
+ ? PROVISIONING_VALUE_ENABLED : PROVISIONING_VALUE_DISABLED;
+
+ // Notify all registered callbacks
+ if (callback == null) {
+ mProvisioningCallbackManagersSlotMap.get(slotId)
+ .notifyProvisioningCapabilityChanged(
+ new FeatureProvisioningData(
+ capability,
+ radioTech,
+ getBoolValue(value),
+ /*isMmTle*/false));
+ } else {
+ try {
+ callback.onRcsFeatureProvisioningChanged(capability, radioTech,
+ getBoolValue(value));
+ } catch (RemoteException e) {
+ logw("notifyRcsProvisioningStatus callback is not available");
+ }
+ }
+ }
+ }
+ }
+
private void log(String s) {
Rlog.d(TAG, s);
}
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index c3d7305..0c97cc2 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -91,6 +91,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Global state for the telephony subsystem when running in the primary
@@ -189,13 +190,15 @@
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})
+ ROAMING_NOTIFICATION_REASON_DEFAULT_DATA_SUBS_CHANGED,
+ ROAMING_NOTIFICATION_REASON_DISCONNECTED_SINGLE_NETWORK})
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;
+ private static final int ROAMING_NOTIFICATION_REASON_DISCONNECTED_SINGLE_NETWORK = 5;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -214,6 +217,14 @@
private int mCurrentRoamingNotification = ROAMING_NOTIFICATION_NO_NOTIFICATION;
/**
+ * If true, update roaming notifications after the Internet is completely disconnected. If
+ * carrier allows only a single data network, wait until the Internet connection is completely
+ * disconnected and then update the roaming notification once more to check if
+ * ONLY_ALLOWED_SINGLE_NETWORK disallow reason is disappeared.
+ */
+ private AtomicBoolean mWaitForInternetDisconnection = new AtomicBoolean(false);
+
+ /**
* Reasons that have already shown notification to prevent duplicate shows for the same reason.
*/
private ArraySet<String> mShownNotificationReasons = new ArraySet<>();
@@ -252,7 +263,8 @@
private FeatureFlags mFeatureFlags = new FeatureFlagsImpl();
private class PhoneAppCallback extends TelephonyCallback implements
- TelephonyCallback.ServiceStateListener {
+ TelephonyCallback.ServiceStateListener,
+ TelephonyCallback.DataConnectionStateListener {
private final int mSubId;
PhoneAppCallback(int subId) {
@@ -266,6 +278,23 @@
handleServiceStateChanged(serviceState, mSubId);
}
+ @Override
+ public void onDataConnectionStateChanged(int state, int networkType) {
+ if (mSubId == mDefaultDataSubId && state == TelephonyManager.DATA_DISCONNECTED) {
+ // onDataConnectionStateChanged is an event about the state of exact DataNetwork,
+ // but since the DataNetwork of internet may not have been completely removed from
+ // the DataNetworkController list, The post handler event expects the internet data
+ // network to be completely removed from the DataNetworkController list.
+ mHandler.post(() -> {
+ if (mWaitForInternetDisconnection.compareAndSet(true, false)) {
+ Log.d(LOG_TAG, "onDisconnectedInternetDataNetwork.");
+ updateDataRoamingStatus(
+ ROAMING_NOTIFICATION_REASON_DISCONNECTED_SINGLE_NETWORK);
+ }
+ });
+ }
+ }
+
public int getSubId() {
return mSubId;
}
@@ -611,7 +640,8 @@
mTelephonyRcsService.initialize();
imsRcsController.setRcsService(mTelephonyRcsService);
mImsProvisioningController =
- ImsProvisioningController.make(this, PhoneFactory.getPhones().length);
+ ImsProvisioningController.make(this, PhoneFactory.getPhones().length,
+ mFeatureFlags);
}
// Create the CallNotifier singleton, which handles
@@ -1006,10 +1036,9 @@
* 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.
+ * @param notificationReason to inform which event is called for notification update.
*/
- private void updateDataRoamingStatus(@RoamingNotificationReason int reason) {
- if (VDBG) Log.v(LOG_TAG, "updateDataRoamingStatus");
+ private void updateDataRoamingStatus(@RoamingNotificationReason int notificationReason) {
Phone phone = getPhone(mDefaultDataSubId);
if (phone == null) {
Log.w(LOG_TAG, "Can't get phone with sub id = " + mDefaultDataSubId);
@@ -1022,20 +1051,59 @@
return;
}
+ List<DataDisallowedReason> disallowReasons = phone.getDataNetworkController()
+ .getInternetDataDisallowedReasons();
+
+ if (mFeatureFlags.roamingNotificationForSingleDataNetwork()) {
+ if (disallowReasons.contains(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK)
+ && disallowReasons.contains(DataDisallowedReason.ROAMING_DISABLED)
+ && (notificationReason == ROAMING_NOTIFICATION_REASON_DATA_SETTING_CHANGED
+ || notificationReason
+ == ROAMING_NOTIFICATION_REASON_DATA_ROAMING_SETTING_CHANGED)) {
+ // If the ONLY_ALLOWED_SINGLE_NETWORK disallow reason has not yet been removed due
+ // to a change in mobile_data (including roaming_data) settings, update roaming
+ // notification again after the Internet is completely disconnected to check
+ // ONLY_ALLOWED_SINGLE_NETWORK disallow reason is removed.
+ mWaitForInternetDisconnection.set(true);
+ Log.d(LOG_TAG, "updateDataRoamingStatus,"
+ + " wait for internet disconnection for single data network");
+ } else if (!disallowReasons.contains(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK)
+ && mWaitForInternetDisconnection.compareAndSet(true, false)) {
+ // If the ONLY_ALLOWED_SINGLE_NETWORK disallow reason has been removed,
+ // no longer wait for Internet disconnection.
+ Log.d(LOG_TAG, "updateDataRoamingStatus,"
+ + " cancel to wait for internet disconnection for single data network");
+ }
+ }
+
+ updateDataRoamingStatus(notificationReason, disallowReasons, serviceState);
+ }
+
+ /**
+ * 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 notificationReason to inform which event is called for notification update.
+ * @param disallowReasons List of reasons why internet data is not allowed. An empty list if
+ * internet is allowed.
+ * @param serviceState Service state from phone
+ */
+ private void updateDataRoamingStatus(@RoamingNotificationReason int notificationReason,
+ List<DataDisallowedReason> disallowReasons, ServiceState serviceState) {
+
+ if (VDBG) Log.v(LOG_TAG, "updateDataRoamingStatus");
String roamingNumeric = serviceState.getOperatorNumeric();
String roamingNumericReason = "RoamingNumeric=" + roamingNumeric;
- String callingReason = "CallingReason=" + reason;
+ String callingReason = "CallingReason=" + notificationReason;
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));
+ dataAllowed = disallowReasons.isEmpty();
+ notAllowedDueToRoamingOff = (disallowReasons.size() == 1
+ && disallowReasons.contains(DataDisallowedReason.ROAMING_DISABLED));
StringBuilder sb = new StringBuilder("updateDataRoamingStatus");
sb.append(" dataAllowed=").append(dataAllowed);
- sb.append(", reasons=").append(reasons);
+ sb.append(", disallowReasons=").append(disallowReasons);
sb.append(", dataIsNowRoaming=").append(dataIsNowRoaming);
sb.append(", ").append(roamingNumericReason);
sb.append(", ").append(callingReason);
@@ -1046,8 +1114,8 @@
// 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) {
+ if (notificationReason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED
+ || notificationReason == ROAMING_NOTIFICATION_REASON_SERVICE_STATE_CHANGED) {
shownInThisNumeric = mShownNotificationReasons.contains(roamingNumericReason);
}
// Determine if a notification has never been shown by given calling reason.
@@ -1058,7 +1126,7 @@
mShownNotificationReasons.add(roamingNumericReason);
}
if (!shownForThisReason
- && reason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED) {
+ && notificationReason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED) {
mShownNotificationReasons.add(callingReason);
}
// No need to show it again if we never cancelled it explicitly.
@@ -1085,7 +1153,7 @@
mShownNotificationReasons.add(roamingNumericReason);
}
if (!shownForThisReason
- && reason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED) {
+ && notificationReason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED) {
mShownNotificationReasons.add(callingReason);
}
boolean shouldShowRoamingNotification = shouldShowRoamingNotification(roamingNumeric);
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 26e9185..2779bdb 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -13033,7 +13033,7 @@
}
if (isAllowed) {
mSatelliteController.requestSatelliteEnabled(
- subId, enableSatellite, enableDemoMode, callback);
+ subId, enableSatellite, enableDemoMode, isEmergency, callback);
} else {
result.accept(SATELLITE_RESULT_ACCESS_BARRED);
}
@@ -13044,7 +13044,7 @@
} else {
// No need to check if satellite is allowed at current location when disabling satellite
mSatelliteController.requestSatelliteEnabled(
- subId, enableSatellite, enableDemoMode, callback);
+ subId, enableSatellite, enableDemoMode, isEmergency, callback);
}
}
diff --git a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementApi.java b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementApi.java
index 45482ec..6c55709 100644
--- a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementApi.java
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementApi.java
@@ -61,7 +61,8 @@
SatelliteEntitlementResponse satelliteEntitlementResponse =
new SatelliteEntitlementResponse(response);
return new SatelliteEntitlementResult(satelliteEntitlementResponse.getEntitlementStatus(),
- satelliteEntitlementResponse.getPlmnAllowed());
+ satelliteEntitlementResponse.getPlmnAllowed(),
+ satelliteEntitlementResponse.getPlmnBarredList());
}
@NonNull
diff --git a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementController.java b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementController.java
index accae32..d193a7d 100644
--- a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementController.java
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementController.java
@@ -429,7 +429,8 @@
updateSatelliteEntitlementStatus(subId,
mSatelliteEntitlementResultPerSub.get(subId).getEntitlementStatus()
== SATELLITE_ENTITLEMENT_STATUS_ENABLED,
- mSatelliteEntitlementResultPerSub.get(subId).getAllowedPLMNList());
+ mSatelliteEntitlementResultPerSub.get(subId).getAllowedPLMNList(),
+ mSatelliteEntitlementResultPerSub.get(subId).getBarredPLMNList());
stopExponentialBackoff(subId);
mRetryCountPerSub.remove(subId);
}
@@ -528,9 +529,9 @@
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
public void updateSatelliteEntitlementStatus(int subId, boolean enabled,
- List<String> plmnAllowedList) {
+ List<String> plmnAllowedList, List<String> plmnBarredList) {
SatelliteController.getInstance().onSatelliteEntitlementStatusUpdated(subId, enabled,
- plmnAllowedList, null);
+ plmnAllowedList, plmnBarredList, null);
}
private static void logd(String log) {
diff --git a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponse.java b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponse.java
index b877bee..97cb355 100644
--- a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponse.java
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponse.java
@@ -97,7 +97,6 @@
* Get the PLMNBarredList from the response
* @return The PLMNs Barred List
*/
- @VisibleForTesting
public List<String> getPlmnBarredList() {
return mPlmnBarredList.stream().map(String::new).collect(Collectors.toList());
}
@@ -137,7 +136,10 @@
mPlmnBarredList = new ArrayList<>();
JSONArray jsonArray = jsonToken.getJSONArray(PLMN_BARRED_KEY);
for (int i = 0; i < jsonArray.length(); i++) {
- mPlmnBarredList.add(jsonArray.getJSONObject(i).getString(PLMN_KEY));
+ String plmn = jsonArray.getJSONObject(i).getString(PLMN_KEY);
+ if (!TextUtils.isEmpty(plmn)) {
+ mPlmnBarredList.add(plmn);
+ }
}
}
} catch (JSONException e) {
diff --git a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResult.java b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResult.java
index 3289232..014e28e 100644
--- a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResult.java
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResult.java
@@ -53,17 +53,25 @@
* item of the satellite configuration received from the entitlement server.
*/
private List<SatelliteNetworkInfo> mAllowedSatelliteNetworkInfoList;
+ /**
+ * List consisting of the PLMN in the PLMNBarred item of the satellite configuration received
+ * from the entitlement server
+ */
+ private List<String> mBarredPlmnList;
/**
* Store the result of the satellite entitlement response.
*
* @param entitlementStatus The entitlement status.
* @param allowedSatelliteNetworkInfoList The allowedSatelliteNetworkInfoList
+ * @param barredPlmnList The barred plmn list
*/
public SatelliteEntitlementResult(@SatelliteEntitlementStatus int entitlementStatus,
- List<SatelliteNetworkInfo> allowedSatelliteNetworkInfoList) {
+ List<SatelliteNetworkInfo> allowedSatelliteNetworkInfoList,
+ List<String> barredPlmnList) {
mEntitlementStatus = entitlementStatus;
mAllowedSatelliteNetworkInfoList = allowedSatelliteNetworkInfoList;
+ mBarredPlmnList = barredPlmnList;
}
/**
@@ -86,6 +94,15 @@
}
/**
+ * Get the plmn barred list
+ *
+ * @return The plmn barred list.
+ */
+ public List<String> getBarredPLMNList() {
+ return mBarredPlmnList.stream().map(String::new).collect(Collectors.toList());
+ }
+
+ /**
* Get the default SatelliteEntitlementResult. EntitlementStatus set to
* `SATELLITE_ENTITLEMENT_STATUS_DISABLED` and SatelliteNetworkInfo list set to empty.
*
@@ -93,6 +110,6 @@
*/
public static SatelliteEntitlementResult getDefaultResult() {
return new SatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_DISABLED,
- new ArrayList<>());
+ new ArrayList<>(), new ArrayList<>());
}
}
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index d1961fd..48786dc 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -32,6 +32,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.flags.FeatureFlagsImpl;
+import com.android.internal.telephony.satellite.SatelliteController;
import com.android.phone.ImsUtil;
import com.android.phone.PhoneGlobals;
import com.android.phone.R;
@@ -457,7 +458,7 @@
resourceId = R.string.callFailed_wfc_service_not_available_in_this_location;
break;
case android.telephony.DisconnectCause.SATELLITE_ENABLED:
- resourceId = R.string.incall_error_satellite_enabled;
+ resourceId = getSatelliteErrorString();
break;
default:
break;
@@ -641,7 +642,7 @@
resourceId = R.string.clh_incall_error_out_of_service_txt;
break;
case android.telephony.DisconnectCause.SATELLITE_ENABLED:
- resourceId = R.string.clh_callFailed_satelliteEnabled_txt;
+ resourceId = getSatelliteErrorString();
break;
default:
resourceId = R.string.clh_card_title_call_ended_txt;
@@ -885,7 +886,7 @@
resourceId = R.string.callFailed_wfc_service_not_available_in_this_location;
break;
case android.telephony.DisconnectCause.SATELLITE_ENABLED:
- resourceId = R.string.incall_error_satellite_enabled;
+ resourceId = getSatelliteErrorString();
break;
default:
break;
@@ -929,6 +930,8 @@
return DisconnectCause.REASON_IMS_ACCESS_BLOCKED;
case android.telephony.DisconnectCause.OUTGOING_EMERGENCY_CALL_PLACED:
return DisconnectCause.REASON_EMERGENCY_CALL_PLACED;
+ case android.telephony.DisconnectCause.SATELLITE_ENABLED:
+ return reason;
}
// If no specific code-mapping found, then fall back to using the reason.
@@ -1041,4 +1044,11 @@
boolean is2gEnabled = (currentlyAllowedNetworkTypes & bitmask2g) != 0;
return !is2gEnabled;
}
+
+ private static Integer getSatelliteErrorString() {
+ if (SatelliteController.getInstance().isSatelliteEnabled()) {
+ return R.string.incall_error_satellite_enabled;
+ }
+ return R.string.incall_error_carrier_roaming_satellite_mode;
+ }
}
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 228fb4e..f71ea9a 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -149,6 +149,10 @@
private static final Pattern CDMA_ACTIVATION_CODE_REGEX_PATTERN =
Pattern.compile("\\*228[0-9]{0,2}");
+ private static final String DISCONNECT_REASON_SATELLITE_ENABLED = "SATELLITE_ENABLED";
+ private static final String DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE =
+ "CARRIER_ROAMING_SATELLITE_MODE";
+
private final TelephonyConnectionServiceProxy mTelephonyConnectionServiceProxy =
new TelephonyConnectionServiceProxy() {
@Override
@@ -1245,15 +1249,23 @@
}
if (!isEmergencyNumber) {
- if ((mSatelliteController.isSatelliteEnabled()
- || isCallDisallowedDueToSatellite(phone))
- && (imsPhone == null || !imsPhone.canMakeWifiCall())) {
- Log.d(this, "onCreateOutgoingConnection, cannot make call in satellite mode.");
+ if (mSatelliteController.isSatelliteEnabled()) {
+ Log.d(this, "onCreateOutgoingConnection, cannot make call in "
+ + "satellite mode.");
return Connection.createFailedConnection(
mDisconnectCauseFactory.toTelecomDisconnectCause(
android.telephony.DisconnectCause.SATELLITE_ENABLED,
- "Call failed because satellite modem is enabled."));
+ DISCONNECT_REASON_SATELLITE_ENABLED));
+ } else if (isCallDisallowedDueToSatellite(phone)
+ && (imsPhone == null || !imsPhone.canMakeWifiCall())) {
+ Log.d(this, "onCreateOutgoingConnection, cannot make call "
+ + "when device is connected to carrier roaming satellite network");
+ return Connection.createFailedConnection(
+ mDisconnectCauseFactory.toTelecomDisconnectCause(
+ android.telephony.DisconnectCause.SATELLITE_ENABLED,
+ DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE));
}
+
final Connection resultConnection = getTelephonyConnection(request, numberToDial,
false, handle, phone);
if (isAdhocConference) {
@@ -2800,6 +2812,25 @@
.findFirst().orElse(null);
}
+ /**
+ * Determines the phone with which emergency callback mode was set.
+ * @return The {@link Phone} with which emergency callback mode was set,
+ * or {@code null} if none was found.
+ */
+ @VisibleForTesting
+ public Phone getPhoneInEmergencyCallbackMode() {
+ if (!mDomainSelectionResolver.isDomainSelectionSupported()) {
+ // This is applicable for the AP domain selection service.
+ return null;
+ }
+ if (mEmergencyStateTracker == null) {
+ mEmergencyStateTracker = EmergencyStateTracker.getInstance();
+ }
+ return Stream.of(mPhoneFactoryProxy.getPhones())
+ .filter(p -> mEmergencyStateTracker.isInEcm(p))
+ .findFirst().orElse(null);
+ }
+
private boolean isVoiceInService(Phone phone, boolean imsVoiceCapable) {
// Dialing normal call is available.
if (phone.isWifiCallingEnabled()) {
@@ -3303,6 +3334,15 @@
return normalRoutingPhone;
}
+ if (mDomainSelectionResolver.isDomainSelectionSupported()) {
+ Phone phoneInEcm = getPhoneInEmergencyCallbackMode();
+ if (phoneInEcm != null) {
+ Log.i(this, "getPhoneForAccount: in ECBM, using phoneId=%d/subId=%d",
+ phoneInEcm.getPhoneId(), phoneInEcm.getSubId());
+ return phoneInEcm;
+ }
+ }
+
// 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
diff --git a/testapps/TestSatelliteApp/AndroidManifest.xml b/testapps/TestSatelliteApp/AndroidManifest.xml
index fb30bf3..eaddf95 100644
--- a/testapps/TestSatelliteApp/AndroidManifest.xml
+++ b/testapps/TestSatelliteApp/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2023 The Android Open Source Project
+ ~ Copyright (C) 2024 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.
@@ -46,6 +46,7 @@
<activity android:name=".Provisioning" />
<activity android:name=".MultipleSendReceive" />
<activity android:name=".SendReceive" />
+ <activity android:name=".NbIotSatellite" />
<activity android:name=".TestSatelliteWrapper" />
</application>
</manifest>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_NbIotSatellite.xml b/testapps/TestSatelliteApp/res/layout/activity_NbIotSatellite.xml
new file mode 100644
index 0000000..c33522e
--- /dev/null
+++ b/testapps/TestSatelliteApp/res/layout/activity_NbIotSatellite.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 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"
+ android:paddingEnd="4dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:layout_weight="0"
+ android:textColor="@android:color/holo_blue_dark"
+ android:textSize="20sp"
+ android:text="@string/NbIotSatellite"/>
+ <Button
+ android:id="@+id/testRegisterForSupportedStateChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/testRegisterForSupportedStateChanged"/>
+ <Button
+ android:id="@+id/testUnregisterForSupportedStateChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/testUnregisterForSupportedStateChanged"/>
+ <Button
+ android:id="@+id/testRequestIsSupported"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/testRequestIsSupported"/>
+ <Button
+ android:id="@+id/reportSatelliteSupportedFromModem"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/reportSatelliteSupportedFromModem"/>
+ <Button
+ android:id="@+id/reportSatelliteNotSupportedFromModem"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/reportSatelliteNotSupportedFromModem"/>
+ <Button
+ android:id="@+id/showCurrentSatelliteSupportedStated"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/showCurrentSatelliteSupportedStated"/>
+ <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:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/Back"/>
+ <TextView
+ android:id="@+id/text_id"
+ android:layout_width="300dp"
+ android:layout_height="200dp"
+ android:textColor="@android:color/holo_blue_light"
+ android:textSize="15sp" />
+</LinearLayout>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_SatelliteControl.xml b/testapps/TestSatelliteApp/res/layout/activity_SatelliteControl.xml
index 6a79412..6aec1da 100644
--- a/testapps/TestSatelliteApp/res/layout/activity_SatelliteControl.xml
+++ b/testapps/TestSatelliteApp/res/layout/activity_SatelliteControl.xml
@@ -119,6 +119,12 @@
android:layout_height="wrap_content"
android:paddingRight="4dp"
android:text="@string/isRequestIsSatelliteEnabledForCarrier"/>
+ <Button
+ android:id="@+id/getIsEmergency"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/getIsEmergency"/>
<Button
android:id="@+id/Back"
android:onClick="Back"
diff --git a/testapps/TestSatelliteApp/res/layout/activity_SatelliteTestApp.xml b/testapps/TestSatelliteApp/res/layout/activity_SatelliteTestApp.xml
index 0753b82..5ba7946 100644
--- a/testapps/TestSatelliteApp/res/layout/activity_SatelliteTestApp.xml
+++ b/testapps/TestSatelliteApp/res/layout/activity_SatelliteTestApp.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2023 The Android Open Source Project
+ ~ Copyright (C) 2024 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.
@@ -65,9 +65,17 @@
android:paddingRight="4dp"
android:text="@string/SendReceive"/>
<Button
+ android:id="@+id/NbIotSatellite"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/NbIotSatellite"/>
+ <Button
android:id="@+id/TestSatelliteWrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:paddingStart="4dp"
android:paddingEnd="4dp"
android:text="@string/TestSatelliteWrapper"/>
</LinearLayout>
diff --git a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
index 20f5ca8..df2aaf7 100644
--- a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
+++ b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2023 The Android Open Source Project
+ ~ Copyright (C) 2024 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.
@@ -21,6 +21,7 @@
<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="NbIotSatellite">NB IoT Satellite modem interface test</string>
<string name="enableSatellite">enableSatellite</string>
<string name="disableSatellite">disableSatellite</string>
@@ -30,6 +31,7 @@
<string name="requestSatelliteCapabilities">requestSatelliteCapabilities</string>
<string name="requestIsSatelliteCommunicationAllowedForCurrentLocation">requestIsSatelliteCommunicationAllowedForCurrentLocation</string>
<string name="requestTimeForNextSatelliteVisibility">requestTimeForNextSatelliteVisibility</string>
+ <string name="getIsEmergency">getIsEmergency</string>
<string name="pollPendingSatelliteDatagrams">pollPendingSatelliteDatagrams</string>
<string name="sendSatelliteDatagram">sendSatelliteDatagram</string>
@@ -82,6 +84,13 @@
<string name="isSatelliteEnabledForCarrier">isSatelliteEnabledForCarrier</string>
<string name="isRequestIsSatelliteEnabledForCarrier">isRequestIsSatelliteEnabledForCarrier</string>
+ <string name="testRegisterForSupportedStateChanged">testRegisterForSupportedStateChanged</string>
+ <string name="testUnregisterForSupportedStateChanged">testUnregisterForSupportedStateChanged</string>
+ <string name="testRequestIsSupported">testRequestIsSupported</string>
+ <string name="reportSatelliteSupportedFromModem">reportSatelliteSupportedFromModem</string>
+ <string name="reportSatelliteNotSupportedFromModem">reportSatelliteNotSupportedFromModem</string>
+ <string name="showCurrentSatelliteSupportedStated">showCurrentSatelliteSupportedStated</string>
+
<string name="Back">Back</string>
<string name="ClearLog">Clear Log</string>
</resources>
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/NbIotSatellite.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/NbIotSatellite.java
new file mode 100644
index 0000000..17646f0
--- /dev/null
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/NbIotSatellite.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2024 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_RESULT_SUCCESS;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.OutcomeReceiver;
+import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteSupportedStateCallback;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Activity related to NB IoT satellite APIs.
+ */
+public class NbIotSatellite extends Activity {
+
+ private static final String TAG = "NbIotSatellite";
+ private static final String MY_SHARED_PREF = "MySharedPref";
+ private static final String SHARED_PREF_KEY = "supported_stated";
+ TextView mTextView;
+ private boolean mSatelliteSupported = false;
+ public static TestSatelliteService sSatelliteService;
+ private SatelliteManager mSatelliteManager;
+ private TestSatelliteSupportedStateCallback mSatelliteSupportedStateCallback;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ sSatelliteService = SatelliteTestApp.getTestSatelliteService();
+ mSatelliteManager = getSystemService(SatelliteManager.class);
+
+ setContentView(R.layout.activity_NbIotSatellite);
+ findViewById(R.id.testRegisterForSupportedStateChanged)
+ .setOnClickListener(this::testRegisterForSupportedStateChanged);
+ findViewById(R.id.testUnregisterForSupportedStateChanged)
+ .setOnClickListener(this::testUnregisterForSupportedStateChanged);
+ findViewById(R.id.testRequestIsSupported)
+ .setOnClickListener(this::testRequestIsSupported);
+ findViewById(R.id.reportSatelliteSupportedFromModem)
+ .setOnClickListener(this::reportSatelliteSupportedFromModem);
+ findViewById(R.id.reportSatelliteNotSupportedFromModem)
+ .setOnClickListener(this::reportSatelliteNotSupportedFromModem);
+ findViewById(R.id.showCurrentSatelliteSupportedStated)
+ .setOnClickListener(this::showCurrentSatelliteSupportedStated);
+ findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(NbIotSatellite.this, SatelliteTestApp.class));
+ }
+ });
+
+ mTextView = findViewById(R.id.text_id);
+ }
+
+ protected class TestSatelliteSupportedStateCallback implements SatelliteSupportedStateCallback {
+ @Override
+ public void onSatelliteSupportedStateChanged(boolean supported) {
+ mSatelliteSupported = supported;
+ updateLogMessage("onSatelliteSupportedStateChanged: "
+ + (mSatelliteSupported ? "Satellite is supported"
+ : "Satellite is not supported"));
+ Log.d(TAG, "onSatelliteSupportedStateChanged(): supported="
+ + mSatelliteSupported);
+ }
+ }
+
+ @SuppressLint("MissingPermission")
+ private void testRegisterForSupportedStateChanged(View view) {
+ if (mSatelliteSupportedStateCallback == null) {
+ mSatelliteSupportedStateCallback = new TestSatelliteSupportedStateCallback();
+ }
+ int result = mSatelliteManager.registerForSupportedStateChanged(Runnable::run,
+ mSatelliteSupportedStateCallback);
+
+ if (result == SATELLITE_RESULT_SUCCESS) {
+ updateLogMessage("testRegisterForSupportedStateChanged(): "
+ + "registered mSatelliteSupportedStateCallback");
+ } else {
+ updateLogMessage("Failed to registerForSupportedStateChanged(), reason=" + result);
+ }
+ }
+
+ @SuppressLint("MissingPermission")
+ private void testUnregisterForSupportedStateChanged(View view) {
+ if (mSatelliteSupportedStateCallback != null) {
+ mSatelliteManager.unregisterForSupportedStateChanged(mSatelliteSupportedStateCallback);
+ mSatelliteSupportedStateCallback = null;
+ updateLogMessage("testUnregisterForSupportedStateChanged(): unregister callback.");
+ } else {
+ updateLogMessage("testUnregisterForSupportedStateChanged(): ignored, "
+ + "mSatelliteSupportedStateCallback is already null");
+ }
+ }
+
+ private void testRequestIsSupported(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);
+ updateLogMessage("Status for requestIsSupported result: "
+ + enabled.get());
+ }
+
+ @Override
+ public void onError(SatelliteManager.SatelliteException exception) {
+ errorCode.set(exception.getErrorCode());
+ updateLogMessage("Status for requestIsSupported error : "
+ + SatelliteErrorUtils.mapError(errorCode.get()));
+ }
+ };
+ mSatelliteManager.requestIsSupported(Runnable::run, mReceiver);
+ }
+
+ private void showCurrentSatelliteSupportedStated(View view) {
+ boolean mModemSupportedState = sSatelliteService.getSatelliteSupportedState();
+ updateLogMessage("reported supported state is " + mSatelliteSupported
+ + ", modem supported state is " + mModemSupportedState);
+ }
+
+ private void reportSatelliteSupportedFromModem(View view) {
+ sSatelliteService.updateSatelliteSupportedState(true);
+ }
+
+ private void reportSatelliteNotSupportedFromModem(View view) {
+ sSatelliteService.updateSatelliteSupportedState(false);
+ }
+
+ // 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", mSatelliteSupported);
+
+ // Setting the fetched data
+ mSatelliteSupported = 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(MY_SHARED_PREF, MODE_PRIVATE);
+ SharedPreferences.Editor myEdit = sharedPreferences.edit();
+
+ // write all the data entered by the user in SharedPreference and apply
+ myEdit.putBoolean(SHARED_PREF_KEY, mSatelliteSupported);
+ myEdit.apply();
+ }
+
+ private void updateLogMessage(String message) {
+ runOnUiThread(() -> mTextView.setText(message));
+ }
+
+ protected void onDestroy() {
+ super.onDestroy();
+ SharedPreferences sharedPreferences = getSharedPreferences(MY_SHARED_PREF, MODE_PRIVATE);
+
+ final SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit();
+ sharedPrefsEditor.remove(SHARED_PREF_KEY);
+ sharedPrefsEditor.apply();
+ }
+}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java
index dd7b825..a03f04e 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java
@@ -81,6 +81,8 @@
.setOnClickListener(this::isSatelliteEnabledForCarrierApp);
findViewById(R.id.isRequestIsSatelliteEnabledForCarrier)
.setOnClickListener(this::isRequestIsSatelliteEnabledForCarrierApp);
+ findViewById(R.id.getIsEmergency)
+ .setOnClickListener(this::getIsEmergencyApp);
findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
@@ -92,8 +94,8 @@
private void enableSatelliteApp(View view) {
LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
mSatelliteManager.requestEnabled(
- new EnableRequestAttributes.Builder(true).setDemoMode(true).build(),
- Runnable::run, error::offer);
+ new EnableRequestAttributes.Builder(true).setDemoMode(true).setEmergencyMode(true)
+ .build(), Runnable::run, error::offer);
TextView textView = findViewById(R.id.text_id);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
@@ -374,4 +376,11 @@
+ SatelliteTestApp.getTestSatelliteService()
.isRequestIsSatelliteEnabledForCarrier());
}
+
+ private void getIsEmergencyApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("[SatelliteService] getIsEmergencyApp= "
+ + SatelliteTestApp.getTestSatelliteService()
+ .getIsEmergency());
+ }
}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
index c8ee5fa..7c4ae00 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -89,6 +89,13 @@
startActivity(intent);
}
});
+ findViewById(R.id.NbIotSatellite).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SatelliteTestApp.this, NbIotSatellite.class);
+ startActivity(intent);
+ }
+ });
findViewById(R.id.TestSatelliteWrapper).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java
index ed9fa10..d79240e 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -100,6 +100,7 @@
private List<String> mAllPlmnList = new ArrayList<>();
private boolean mIsSatelliteEnabledForCarrier;
private boolean mIsRequestIsSatelliteEnabledForCarrier;
+ private boolean mIsEmergnecy;
/**
* Create TestSatelliteService using the Executor specified for methods being called from
@@ -117,6 +118,7 @@
mIsCellularModemEnabledMode = false;
mIsSatelliteEnabledForCarrier = false;
mIsRequestIsSatelliteEnabledForCarrier = false;
+ mIsEmergnecy = false;
}
/**
@@ -184,8 +186,9 @@
@Override
public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
- @NonNull IIntegerConsumer errorCallback) {
- logd("requestSatelliteEnabled: mErrorCode=" + mErrorCode + " enable = " + enableSatellite);
+ boolean isEmergency, @NonNull IIntegerConsumer errorCallback) {
+ logd("requestSatelliteEnabled: mErrorCode=" + mErrorCode + " enable = " + enableSatellite
+ + " isEmergency=" + isEmergency);
if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
runWithExecutor(() -> errorCallback.accept(mErrorCode));
return;
@@ -196,6 +199,7 @@
} else {
disableSatellite(errorCallback);
}
+ mIsEmergnecy = isEmergency;
}
private void enableSatellite(@NonNull IIntegerConsumer errorCallback) {
@@ -467,6 +471,16 @@
}
/**
+ * Helper method to report satellite supported from modem side for testing purpose.
+ * @param supported whether satellite is supported from modem or not.
+ */
+ public void sendOnSatelliteSupportedStateChanged(boolean supported) {
+ logd("sendOnSatelliteSupportedStateChanged: supported=" + supported);
+ mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
+ listener.onSatelliteSupportedStateChanged(supported)));
+ }
+
+ /**
* Helper method to verify that the satellite modem is properly configured to receive
* requests.
*
@@ -565,6 +579,26 @@
return mIsRequestIsSatelliteEnabledForCarrier;
}
+ public boolean getIsEmergency() {
+ return mIsEmergnecy;
+ }
+
+ /**
+ * Helper methoid to provide a way to set supported state from test application to mock modem.
+ * @param supported whether satellite is supported by modem or not.
+ */
+ public void updateSatelliteSupportedState(boolean supported) {
+ logd("updateSatelliteSupportedState: supported=" + supported);
+ mIsSupported = supported;
+ mRemoteListeners.values().forEach(listener -> runWithExecutor(
+ () -> listener.onSatelliteSupportedStateChanged(mIsSupported)));
+
+ }
+
+ public boolean getSatelliteSupportedState() {
+ return mIsSupported;
+ }
+
/**
* Log the message to the radio buffer with {@code DEBUG} priority.
*
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
index 4f0679d..27967f4 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
@@ -248,7 +248,7 @@
String message = "Received SatelliteCapabillities : "
+ SatelliteCapabilities;
logd(message);
- runOnUiThread(() -> addLogMessage(message));
+ addLogMessage(message);
};
}
@@ -281,7 +281,7 @@
@NonNull NtnSignalStrengthWrapper ntnSignalStrength) {
String message = "Received NTN SignalStrength : " + ntnSignalStrength.getLevel();
logd(message);
- runOnUiThread(() -> addLogMessage(message));
+ addLogMessage(message);
}
}
@@ -317,7 +317,7 @@
}
Consumer<Integer> callback = result -> {
- runOnUiThread(() -> addLogMessage("requestAttachEnabledForCarrier result: " + result));
+ addLogMessage("requestAttachEnabledForCarrier result: " + result);
logd("requestAttachEnabledForCarrier result: " + result);
};
@@ -342,7 +342,7 @@
}
Consumer<Integer> callback = result -> {
- runOnUiThread(() -> addLogMessage("requestAttachEnabledForCarrier result: " + result));
+ addLogMessage("requestAttachEnabledForCarrier result: " + result);
logd("requestAttachEnabledForCarrier result: " + result);
};
@@ -409,7 +409,7 @@
int reason = SatelliteManagerWrapper.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER;
Consumer<Integer> callback = result -> {
- runOnUiThread(() -> addLogMessage("addAttachRestrictionForCarrier result: " + result));
+ addLogMessage("addAttachRestrictionForCarrier result: " + result);
logd("addAttachRestrictionForCarrier result: " + result);
};
@@ -436,8 +436,7 @@
int reason = SatelliteManagerWrapper.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER;
Consumer<Integer> callback = result -> {
- runOnUiThread(
- () -> addLogMessage("removeAttachRestrictionForCarrier result: " + result));
+ addLogMessage("removeAttachRestrictionForCarrier result: " + result);
logd("removeAttachRestrictionForCarrier result: " + result);
};
@@ -569,9 +568,11 @@
}
private void addLogMessage(String message) {
- mLogMessages.add(message);
- mAdapter.notifyDataSetChanged();
- mLogListView.setSelection(mAdapter.getCount() - 1);
+ runOnUiThread(() -> {
+ mLogMessages.add(message);
+ mAdapter.notifyDataSetChanged();
+ mLogListView.setSelection(mAdapter.getCount() - 1);
+ });
}
private static void logd(String message) {
diff --git a/tests/src/com/android/phone/ImsProvisioningControllerTest.java b/tests/src/com/android/phone/ImsProvisioningControllerTest.java
index e12be53..6599f03 100644
--- a/tests/src/com/android/phone/ImsProvisioningControllerTest.java
+++ b/tests/src/com/android/phone/ImsProvisioningControllerTest.java
@@ -77,6 +77,7 @@
import com.android.ims.ImsConfig;
import com.android.ims.ImsManager;
import com.android.ims.RcsFeatureManager;
+import com.android.internal.telephony.flags.FeatureFlags;
import org.junit.After;
import org.junit.Before;
@@ -169,6 +170,9 @@
@Mock
IBinder mIbinder1;
+ @Mock
+ FeatureFlags mFeatureFlags;
+
private SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener;
private Handler mHandler;
@@ -192,7 +196,7 @@
TestImsProvisioningController() {
super(mPhone, 2, mHandlerThread.getLooper(),
mMmTelFeatureConnector, mRcsFeatureConnector,
- mImsProvisioningLoader);
+ mImsProvisioningLoader, mFeatureFlags);
}
protected int getSubId(int slotId) {
@@ -369,8 +373,6 @@
}
// verify other interactions
- verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
- verifyNoMoreInteractions(mIFeatureProvisioningCallback1);
verifyNoMoreInteractions(mImsConfig);
}
@@ -408,8 +410,6 @@
verify(mImsConfig, times(1)).setConfig(eq(key), anyInt());
// verify other interactions
- verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
- verifyNoMoreInteractions(mIFeatureProvisioningCallback1);
verifyNoMoreInteractions(mImsConfig);
}
@@ -926,8 +926,6 @@
verify(mImsConfig, times(1)).setConfig(
eq(KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE), eq(PROVISIONING_VALUE_ENABLED));
- verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
- verifyNoMoreInteractions(mIFeatureProvisioningCallback1);
verifyNoMoreInteractions(mImsConfig);
verifyNoMoreInteractions(mImsProvisioningLoader);
}
@@ -1849,6 +1847,184 @@
verifyNoMoreInteractions(mImsConfig);
}
+ @Test
+ @SmallTest
+ public void initialNotifyMmTelProvisioningStatusWhenCallbackRegistered() throws Exception {
+ when(mFeatureFlags.notifyInitialImsProvisioningStatus()).thenReturn(true);
+
+ createImsProvisioningController();
+
+ // Provisioning required for capability on all network type
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY,
+ RADIO_TECHS);
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY,
+ RADIO_TECHS);
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_UT_INT_ARRAY,
+ RADIO_TECHS);
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_SMS_INT_ARRAY,
+ RADIO_TECHS);
+ setCarrierConfig(mSubId0,
+ CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_CALL_COMPOSER_INT_ARRAY, RADIO_TECHS);
+
+ // Stored provisioning Status
+ mMmTelProvisioningStorage = new int[][] {
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_LTE, 0},
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_IWLAN, 1},
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_CROSS_SIM, 1},
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_NR, 1},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_LTE, 0},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_IWLAN, 0},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_CROSS_SIM, 1},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_NR, 1},
+ {CAPABILITY_TYPE_UT, REGISTRATION_TECH_LTE, 0},
+ {CAPABILITY_TYPE_UT, REGISTRATION_TECH_IWLAN, 0},
+ {CAPABILITY_TYPE_UT, REGISTRATION_TECH_CROSS_SIM, 0},
+ {CAPABILITY_TYPE_UT, REGISTRATION_TECH_NR, 0},
+ {CAPABILITY_TYPE_SMS, REGISTRATION_TECH_LTE, 1},
+ {CAPABILITY_TYPE_SMS, REGISTRATION_TECH_IWLAN, 1},
+ {CAPABILITY_TYPE_SMS, REGISTRATION_TECH_CROSS_SIM, 1},
+ {CAPABILITY_TYPE_SMS, REGISTRATION_TECH_NR, 1},
+ {CAPABILITY_TYPE_CALL_COMPOSER, REGISTRATION_TECH_LTE, 1},
+ {CAPABILITY_TYPE_CALL_COMPOSER, REGISTRATION_TECH_IWLAN, 1},
+ {CAPABILITY_TYPE_CALL_COMPOSER, REGISTRATION_TECH_CROSS_SIM, 0},
+ {CAPABILITY_TYPE_CALL_COMPOSER, REGISTRATION_TECH_NR, 1}
+ };
+
+ try {
+ mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+ mSubId0, mIFeatureProvisioningCallback0);
+ } catch (Exception e) {
+ throw new AssertionError("not expected exception", e);
+ }
+ processAllMessages();
+
+ for (int[] capa: mMmTelProvisioningStorage) {
+ verify(mIFeatureProvisioningCallback0, times(1))
+ .onFeatureProvisioningChanged(eq(capa[0]), eq(capa[1]), eq(capa[2] == 1));
+ }
+ }
+
+ @Test
+ @SmallTest
+ public void initialNotifyRcsProvisioningStatusWhenCallbackRegistered() throws Exception {
+ when(mFeatureFlags.notifyInitialImsProvisioningStatus()).thenReturn(true);
+
+ createImsProvisioningController();
+
+ // Provisioning required capability : PRESENCE, tech : all
+ setCarrierConfig(mSubId0,
+ CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY, RADIO_TECHS);
+
+ // Stored provisioning Status
+ mRcsProvisioningStorage = new int[][]{
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_LTE, 1},
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_IWLAN, 1},
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_CROSS_SIM, 0},
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_NR, 1}
+ };
+
+ try {
+ mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+ mSubId0, mIFeatureProvisioningCallback0);
+ } catch (Exception e) {
+ throw new AssertionError("not expected exception", e);
+ }
+ processAllMessages();
+
+ for (int[] capa: mRcsProvisioningStorage) {
+ verify(mIFeatureProvisioningCallback0, times(1))
+ .onRcsFeatureProvisioningChanged(eq(capa[0]), eq(capa[1]), eq(capa[2] == 1));
+ }
+ }
+
+ @Test
+ @SmallTest
+ public void initialNotifyMmTelProvisioningStatusWhenImsServiceConnected() throws Exception {
+ when(mFeatureFlags.notifyInitialImsProvisioningStatus()).thenReturn(true);
+
+ createImsProvisioningController();
+
+ // Provisioning required for capability on all network type
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY,
+ RADIO_TECHS);
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY,
+ RADIO_TECHS);
+
+ // Stored provisioning Status
+ mMmTelProvisioningStorage = new int[][] {
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_LTE, 1},
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_IWLAN, 1},
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_CROSS_SIM, 1},
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_NR, 1},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_LTE, 1},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_IWLAN, 0},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_CROSS_SIM, 0},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_NR, 1},
+ };
+
+ try {
+ mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+ mSubId0, mIFeatureProvisioningCallback0);
+ } catch (Exception e) {
+ throw new AssertionError("not expected exception", e);
+ }
+ processAllMessages();
+
+ // clear interactions
+ clearInvocations(mIFeatureProvisioningCallback0);
+
+ // ImsService connected
+ mMmTelConnectorListener0.getValue().connectionReady(mImsManager, mSubId0);
+
+ for (int[] capa: mMmTelProvisioningStorage) {
+ verify(mIFeatureProvisioningCallback0, times(1))
+ .onFeatureProvisioningChanged(eq(capa[0]), eq(capa[1]), eq(capa[2] == 1));
+ }
+
+ verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
+ }
+
+ @Test
+ @SmallTest
+ public void initialNotifyRcsProvisioningStatusWhenRcsServiceConnected() throws Exception {
+ when(mFeatureFlags.notifyInitialImsProvisioningStatus()).thenReturn(true);
+
+ createImsProvisioningController();
+
+ // Provisioning required capability : PRESENCE, tech : all
+ setCarrierConfig(mSubId0,
+ CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY, RADIO_TECHS);
+
+ // Stored provisioning Status
+ mRcsProvisioningStorage = new int[][]{
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_LTE, 1},
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_IWLAN, 0},
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_CROSS_SIM, 0},
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_NR, 1}
+ };
+
+ try {
+ mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+ mSubId0, mIFeatureProvisioningCallback0);
+ } catch (Exception e) {
+ throw new AssertionError("not expected exception", e);
+ }
+ processAllMessages();
+
+ // clear interactions
+ clearInvocations(mIFeatureProvisioningCallback0);
+
+ // ImsService connected
+ mRcsConnectorListener0.getValue().connectionReady(mRcsFeatureManager, mSubId0);
+
+ for (int[] capa: mRcsProvisioningStorage) {
+ verify(mIFeatureProvisioningCallback0, times(1))
+ .onRcsFeatureProvisioningChanged(eq(capa[0]), eq(capa[1]), eq(capa[2] == 1));
+ }
+
+ verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
+ }
+
private void createImsProvisioningController() throws Exception {
if (Looper.myLooper() == null) {
Looper.prepare();
diff --git a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java
index 18a0284..dd9ea65 100644
--- a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java
+++ b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java
@@ -79,6 +79,7 @@
private static final int[] ACTIVE_SUB_ID = {SUB_ID};
private static final int DEFAULT_QUERY_REFRESH_DAY = 30;
private static final List<String> PLMN_ALLOWED_LIST = Arrays.asList("31026", "302820");
+ private static final List<String> PLMN_BARRED_LIST = Arrays.asList("12345", "98765");
@Mock
CarrierConfigManager mCarrierConfigManager;
@Mock
@@ -166,7 +167,7 @@
verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
- anyBoolean(), anyList(), any());
+ anyBoolean(), anyList(), anyList(), any());
mCarrierConfigBundle.putBoolean(
CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
@@ -177,7 +178,7 @@
verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
- anyBoolean(), anyList(), any());
+ anyBoolean(), anyList(), anyList(), any());
replaceInstance(SatelliteEntitlementController.class, "mExponentialBackoffPerSub",
mSatelliteEntitlementController, new HashMap<>());
@@ -188,7 +189,7 @@
verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
- anyBoolean(), anyList(), any());
+ anyBoolean(), anyList(), anyList(), any());
setInternetConnected(true);
// Verify don't start the query when last query refresh time is not expired.
@@ -197,18 +198,19 @@
verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
- anyBoolean(), anyList(), any());
+ anyBoolean(), anyList(), anyList(), any());
// Verify start the query when isQueryAvailable return true
setLastQueryTime(0L);
doReturn(mSatelliteEntitlementResult).when(
mSatelliteEntitlementApi).checkEntitlementStatus();
- setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST);
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
+ PLMN_BARRED_LIST);
mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
verify(mSatelliteEntitlementApi).checkEntitlementStatus();
verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(anyInt(),
- anyBoolean(), anyList(), any());
+ anyBoolean(), anyList(), anyList(), any());
}
@Test
@@ -221,7 +223,7 @@
verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
// Verify don't call the updateSatelliteEntitlementStatus.
verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
- anyBoolean(), anyList(), any());
+ anyBoolean(), anyList(), anyList(), any());
// Verify call the checkSatelliteEntitlementStatus with invalid response.
setIsQueryAvailableTrue();
@@ -234,26 +236,27 @@
verify(mSatelliteEntitlementApi).checkEntitlementStatus();
// Verify call the updateSatelliteEntitlementStatus with satellite service is disabled
- // and empty PLMNAllowed
+ // , empty PLMNAllowed and empty PLMNBarred.
verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID),
- eq(false), eq(new ArrayList<>()), any());
+ eq(false), eq(new ArrayList<>()), eq(new ArrayList<>()), any());
// Verify call the checkSatelliteEntitlementStatus with the subscribed result.
clearInvocationsForMock();
setIsQueryAvailableTrue();
doReturn(mSatelliteEntitlementResult).when(
mSatelliteEntitlementApi).checkEntitlementStatus();
- setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST);
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
+ PLMN_BARRED_LIST);
mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
verify(mSatelliteEntitlementApi).checkEntitlementStatus();
- // Verify call the updateSatelliteEntitlementStatus with satellite service is enable and
- // availablePLMNAllowedList
+ // Verify call the updateSatelliteEntitlementStatus with satellite service is enable,
+ // availablePLMNAllowedList and availablePLMNBarredList.
verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
- eq(PLMN_ALLOWED_LIST), any());
+ eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
- // Change subId and verify call the updateSatelliteEntitlementStatus with satellite
- // service is enable and availablePLMNAllowedList
+ // Change subId and verify call the updateSatelliteEntitlementStatus with satellite
+ // service is enable, availablePLMNAllowedList and availablePLMNBarredList
clearInvocationsForMock();
doReturn(new int[]{SUB_ID_2}).when(mMockSubscriptionManagerService).getActiveSubIdList(
true);
@@ -261,7 +264,43 @@
verify(mSatelliteEntitlementApi).checkEntitlementStatus();
verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID_2), eq(true),
- eq(PLMN_ALLOWED_LIST), any());
+ eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+
+ // Verify call the updateSatelliteEntitlementStatus with satellite service is enable,
+ // availablePLMNAllowedList and empty plmn barred list.
+ clearInvocationsForMock();
+ setIsQueryAvailableTrue();
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
+ new ArrayList<>());
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
+ eq(PLMN_ALLOWED_LIST), eq(new ArrayList<>()), any());
+
+ // Verify call the updateSatelliteEntitlementStatus with satellite service is enable,
+ // empty PLMNAllowedList and PLMNBarredList.
+ clearInvocationsForMock();
+ setIsQueryAvailableTrue();
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, new ArrayList<>(),
+ new ArrayList<>());
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
+ eq(new ArrayList<>()), eq(new ArrayList<>()), any());
+
+ // Verify call the updateSatelliteEntitlementStatus with satellite service is enable,
+ // empty PLMNAllowedList and availablePLMNBarredList.
+ clearInvocationsForMock();
+ setIsQueryAvailableTrue();
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, new ArrayList<>(),
+ PLMN_BARRED_LIST);
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
+ eq(new ArrayList<>()), eq(PLMN_BARRED_LIST), any());
}
@Test
@@ -277,7 +316,8 @@
// Verify the called the checkSatelliteEntitlementStatus when Internet is connected.
setInternetConnected(true);
setLastQueryTime(0L);
- setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST);
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
+ PLMN_BARRED_LIST);
networkCallback.onAvailable(mockNetwork);
mTestableLooper.processAllMessages();
@@ -285,7 +325,7 @@
verify(mSatelliteEntitlementApi).checkEntitlementStatus();
// Verify call the updateSatelliteEntitlementStatus with satellite service is available.
verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
- eq(PLMN_ALLOWED_LIST), any());
+ eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
}
@Test
@@ -294,13 +334,14 @@
// occurred and Internet is connected.
setInternetConnected(true);
setLastQueryTime(0L);
- setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST);
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
+ PLMN_BARRED_LIST);
triggerCarrierConfigChanged();
verify(mSatelliteEntitlementApi).checkEntitlementStatus();
// Verify call the updateSatelliteEntitlementStatus with satellite service is available.
verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
- eq(PLMN_ALLOWED_LIST), any());
+ eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
}
private void triggerCarrierConfigChanged() {
@@ -344,9 +385,10 @@
}
private void setSatelliteEntitlementResult(int entitlementStatus,
- List<String> plmnAllowedList) {
+ List<String> plmnAllowedList, List<String> plmnBarredList) {
doReturn(entitlementStatus).when(mSatelliteEntitlementResult).getEntitlementStatus();
doReturn(plmnAllowedList).when(mSatelliteEntitlementResult).getAllowedPLMNList();
+ doReturn(plmnBarredList).when(mSatelliteEntitlementResult).getBarredPLMNList();
}
private void setLastQueryTime(Long lastQueryTime) throws Exception {
diff --git a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponseTest.java b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponseTest.java
index 13d43c8..8e45a73 100644
--- a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponseTest.java
+++ b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponseTest.java
@@ -136,27 +136,55 @@
assertTrue(response.getPlmnBarredList().size() == 2);
assertEquals(TEST_PLMN_BARRED_LIST, response.getPlmnBarredList());
+ // Received the body without plmn barred key.
+ response = new SatelliteEntitlementResponse(
+ getChangedAllowedPLMNListResponse(TEST_PLMN_DATA_PLAN_TYPE_LIST.get(0).mPlmn,
+ TEST_PLMN_DATA_PLAN_TYPE_LIST.get(1).mPlmn));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 2);
+ assertTrue(response.getPlmnBarredList().size() == 0);
+
String plmn = "123456";
- // Received 123456 and empty string list
+ // Received the allowed plmn list set as 123456, empty string
response = new SatelliteEntitlementResponse(
- getChangedPLMNListResponse(plmn, ""));
+ getChangedAllowedPLMNListResponse(plmn, ""));
assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
assertTrue(response.getPlmnAllowed().size() == 1);
assertEquals(plmn, response.getPlmnAllowed().get(0).mPlmn);
- // Received empty string and 123456 list
+ // Received the allowed plmn list set as 123456, empty string
response = new SatelliteEntitlementResponse(
- getChangedPLMNListResponse("", plmn));
+ getChangedAllowedPLMNListResponse("", plmn));
assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
assertTrue(response.getPlmnAllowed().size() == 1);
assertEquals(plmn, response.getPlmnAllowed().get(0).mPlmn);
- // Received all empty strings list
+ // RReceived the allowed plmn list set as empty strings
response = new SatelliteEntitlementResponse(
- getChangedPLMNListResponse("", ""));
+ getChangedAllowedPLMNListResponse("", ""));
assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
assertTrue(response.getPlmnAllowed().size() == 0);
+ // Received the barred plmn list set as 123456, empty string
+ response = new SatelliteEntitlementResponse(
+ getChangedBarredPLMNListResponse(plmn, ""));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnBarredList().size() == 1);
+ assertEquals(plmn, response.getPlmnBarredList().get(0));
+
+ // Received the barred plmn list set as empty string, 123456
+ response = new SatelliteEntitlementResponse(
+ getChangedBarredPLMNListResponse("", plmn));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnBarredList().size() == 1);
+ assertEquals(plmn, response.getPlmnBarredList().get(0));
+
+ // Received the barred plmn list set as empty strings
+ response = new SatelliteEntitlementResponse(
+ getChangedBarredPLMNListResponse("", ""));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnBarredList().size() == 0);
+
// Received null
response = new SatelliteEntitlementResponse(null);
assertEquals(SATELLITE_ENTITLEMENT_STATUS_DISABLED, response.getEntitlementStatus());
@@ -190,7 +218,12 @@
+ "{\"PLMN\":\"" + secondPlmn + "\",\"DataPlanType\":\"metered\"}]";
}
- private String getChangedPLMNListResponse(String firstPlmn, String secondPlmn) {
+ private String getBarredPlmns(String firstPlmn, String secondPlmn) {
+ return ",\"PLMNBarred\":[{\"PLMN\":\"" + firstPlmn + "\"}," + "{\"PLMN\":\"" + secondPlmn
+ + "\"}]";
+ }
+
+ private String getChangedAllowedPLMNListResponse(String firstPlmn, String secondPlmn) {
return "{\"VERS\":{\"version\":\"1\",\"validity\":\"172800\"},"
+ "\"TOKEN\":{\"token\":\"ASH127AHHA88SF\"},\""
+ ServiceEntitlement.APP_SATELLITE_ENTITLEMENT + "\":{"
@@ -198,4 +231,15 @@
+ getAllowedPlmns(firstPlmn, secondPlmn)
+ "}}";
}
+
+ private String getChangedBarredPLMNListResponse(String firstPlmn, String secondPlmn) {
+ return "{\"VERS\":{\"version\":\"1\",\"validity\":\"172800\"},"
+ + "\"TOKEN\":{\"token\":\"ASH127AHHA88SF\"},\""
+ + ServiceEntitlement.APP_SATELLITE_ENTITLEMENT + "\":{"
+ + "\"EntitlementStatus\":\"" + SATELLITE_ENTITLEMENT_STATUS_ENABLED + "\""
+ + ",\"PLMNAllowed\":[{\"PLMN\":\"31026\",\"DataPlanType\":\"unmetered\"},"
+ + "{\"PLMN\":\"302820\",\"DataPlanType\":\"metered\"}]"
+ + getBarredPlmns(firstPlmn, secondPlmn)
+ + "}}";
+ }
}
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index bad3b4e..2b805c3 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -224,6 +224,9 @@
private static final Uri TEST_ADDRESS = Uri.parse("tel:+16505551212");
private static final String TELECOM_CALL_ID1 = "TC1";
private static final String TEST_EMERGENCY_NUMBER = "911";
+ private static final String DISCONNECT_REASON_SATELLITE_ENABLED = "SATELLITE_ENABLED";
+ private static final String DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE =
+ "CARRIER_ROAMING_SATELLITE_MODE";
private android.telecom.Connection mConnection;
@Mock TelephonyConnectionService.TelephonyManagerProxy mTelephonyManagerProxy;
@@ -3475,6 +3478,7 @@
DisconnectCause disconnectCause = mConnection.getDisconnectCause();
assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
disconnectCause.getTelephonyDisconnectCause());
+ assertEquals(DISCONNECT_REASON_SATELLITE_ENABLED, disconnectCause.getReason());
}
@Test
@@ -3492,6 +3496,7 @@
DisconnectCause disconnectCause = mConnection.getDisconnectCause();
assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
disconnectCause.getTelephonyDisconnectCause());
+ assertEquals(DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE, disconnectCause.getReason());
// Call is supported while using satellite
when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
@@ -3518,6 +3523,7 @@
DisconnectCause disconnectCause = mConnection.getDisconnectCause();
assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
disconnectCause.getTelephonyDisconnectCause());
+ assertEquals(DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE, disconnectCause.getReason());
// Call is supported when device is connected to satellite within hysteresis time
setupForCallTest();
@@ -3735,6 +3741,30 @@
NORMAL_ROUTED_EMERGENCY_NUMBER));
}
+ /**
+ * Verify where there are two sims, we choose the sim in emergency callback mode for the
+ * next emergency call.
+ */
+ @Test
+ public void testGetPhoneInEmergencyCallbackModeMultiSim() {
+ Phone mockPhone1 = Mockito.mock(Phone.class);
+ Phone mockPhone2 = Mockito.mock(Phone.class);
+
+ when(mPhoneFactoryProxy.getPhones()).thenReturn(
+ new Phone[] {mockPhone1, mockPhone2});
+
+ doReturn(false).when(mEmergencyStateTracker).isInEcm(eq(mockPhone1));
+ doReturn(true).when(mEmergencyStateTracker).isInEcm(eq(mockPhone2));
+
+ // Only applicable for AP domain seleciton service
+ assertNull(mTestConnectionService.getPhoneInEmergencyCallbackMode());
+
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+
+ assertEquals(mockPhone2,
+ mTestConnectionService.getPhoneInEmergencyCallbackMode());
+ }
+
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