Loading src/java/com/android/internal/telephony/satellite/SatelliteController.java +67 −5 Original line number Diff line number Diff line Loading @@ -4339,9 +4339,10 @@ public class SatelliteController extends Handler { mEntitlementPlmnListPerCarrier.put(subId, allowedPlmnList); mEntitlementBarredPlmnListPerCarrier.put(subId, barredPlmnList); mEntitlementDataPlanMapPerCarrier.put(subId, plmnDataPlanMap); mEntitlementServiceTypeMapPerCarrier.put(subId, plmnServiceTypeMap); mEntitlementDataServicePolicyMapPerCarrier.put(subId, plmnDataServicePolicyMap); mEntitlementVoiceServicePolicyMapPerCarrier.put(subId, plmnVoiceServicePolicyMap); updateAndNotifyChangesInCarrierRoamingNtnAvailableServices(subId, plmnServiceTypeMap); updatePlmnListPerCarrier(subId); configureSatellitePlmnForCarrier(subId); mSubscriptionManagerService.setSatelliteEntitlementPlmnList(subId, allowedPlmnList); Loading Loading @@ -8251,6 +8252,31 @@ public class SatelliteController extends Handler { .build(); } /** * The method will notify the change in the services update the * mEntitlementServiceTypeMapPerCarrier. * * @param subId : SubscriptionId * @param plmnServiceTypeMap : entitlement service map. */ private void updateAndNotifyChangesInCarrierRoamingNtnAvailableServices(int subId, Map<String, List<Integer>> plmnServiceTypeMap) { // If a service list is already cached, check it for changes int[] existingServices = getSupportedServicesOnCarrierRoamingNtn(subId); synchronized (mSupportedSatelliteServicesLock) { mEntitlementServiceTypeMapPerCarrier.put(subId, plmnServiceTypeMap); } int[] updatedServices = getSupportedServicesOnCarrierRoamingNtn(subId); if (existingServices.length > 0 && Arrays.equals(existingServices, updatedServices)) { plogd("No change in Entitlement service support data"); return; } if (mFeatureFlags.carrierRoamingNbIotNtn()) { updateLastNotifiedNtnAvailableServicesAndNotify(subId); evaluateCarrierRoamingNtnEligibilityChange(); } } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) protected void handleCarrierRoamingNtnAvailableServicesChanged(int subId) { if (!mFeatureFlags.carrierRoamingNbIotNtn()) { Loading @@ -8277,11 +8303,47 @@ public class SatelliteController extends Handler { phone.notifyCarrierRoamingNtnAvailableServicesChanged(services); } /** Return services that are supported on carrier roaming non-terrestrial network. */ private int[] getAvailableServicesWithEntitlementForSubId(int subId) { synchronized (mSupportedSatelliteServicesLock) { Map<String, List<Integer>> allowedServicesList = mEntitlementServiceTypeMapPerCarrier.get(subId); if (allowedServicesList != null && !allowedServicesList.isEmpty()) { Set<Integer> serviceTypes = new HashSet<>(); for (List<Integer> values : allowedServicesList.values()) { serviceTypes.addAll(values); } int[] result = new int[serviceTypes.size()]; int i = 0; for (int value : serviceTypes) { result[i++] = value; } return result; } else { return new int[0]; // Return an empty array if the map is null or empty } } } /** * Given a subscription ID, this returns the carriers' supported services on * non-terrestrial networks. * * @param subId Associated subscription ID. * return supported services at entitlement for the available carriers. Note: If available * services/allowed service type field is empty at entitlement, information from * {@link * CarrierConfigManager#KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY} * will be returned. */ public int[] getSupportedServicesOnCarrierRoamingNtn(int subId) { if (isSatelliteSupportedViaCarrier(subId)) { // TODO: b/377367448 Cleanup get supported satellite services to align with starlink. int[] services = getSupportedSatelliteServicesForCarrier(subId); if (isValidSubscriptionId(subId) && isSatelliteSupportedViaCarrier(subId)) { // check available services supported at entitlement for sub id int[] services = getAvailableServicesWithEntitlementForSubId(subId); logd("getAvailableServicesWithEntitlementForSubId: " + Arrays.toString(services)); if (services.length == 0) { services = getSupportedSatelliteServicesForCarrier(subId); } if (isP2PSmsDisallowedOnCarrierRoamingNtn(subId)) { services = Arrays.stream(services).filter( value -> value != NetworkRegistrationInfo.SERVICE_TYPE_SMS).toArray(); Loading tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java +153 −1 Original line number Diff line number Diff line Loading @@ -207,6 +207,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; Loading Loading @@ -6191,6 +6192,8 @@ public class SatelliteControllerTest extends TelephonyTest { public int selectedSatelliteSubId = -1; public boolean isSatelliteProvisioned; private boolean callOnlySuperMethod = false; TestSatelliteController( Context context, Looper looper, @NonNull FeatureFlags featureFlags) { super(context, looper, featureFlags); Loading Loading @@ -6282,8 +6285,12 @@ public class SatelliteControllerTest extends TelephonyTest { @Override protected void handleCarrierRoamingNtnAvailableServicesChanged(int subId) { if (callOnlySuperMethod) { super.handleCarrierRoamingNtnAvailableServicesChanged(subId); } else { isApplicationUpdated = true; } } @Override public boolean isApplicationSupportsP2P(String packageName) { Loading @@ -6292,6 +6299,9 @@ public class SatelliteControllerTest extends TelephonyTest { @Override public int[] getSupportedServicesOnCarrierRoamingNtn(int subId) { if (callOnlySuperMethod) { return super.getSupportedServicesOnCarrierRoamingNtn(subId); } return new int[]{3, 5}; } Loading Loading @@ -6373,6 +6383,10 @@ public class SatelliteControllerTest extends TelephonyTest { mSatelliteAccessAllowed = isAllowed; } } public void setCallOnlySuperMethod() { callOnlySuperMethod = true; } } @Test Loading Loading @@ -6684,4 +6698,142 @@ public class SatelliteControllerTest extends TelephonyTest { .getSatelliteDataServicePolicyForPlmn(SUB_ID, "00101"); assertEquals(SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED, dataSupportModeForPlmn); } @Test public void testNotifyCarrierRoamingNtnAvailableServicesChanged_noServices() throws Exception { when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true); when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true); mSatelliteControllerUT.setCallOnlySuperMethod(); List<String> overlayConfigPlmnList = new ArrayList<>(); replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig", mSatelliteControllerUT, overlayConfigPlmnList); mCarrierConfigBundle.putBoolean( CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true); List<String> entitlementPlmnList = Arrays.stream( new String[]{"00101", "00102", "00103", "00104"}).toList(); mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, entitlementPlmnList, new ArrayList<>(), new HashMap<>(), new HashMap<>() /*serviceTypeListMap*/, new HashMap<>(), new HashMap<>(), mIIntegerConsumer); verify(mPhone, times(1)).notifyCarrierRoamingNtnAvailableServicesChanged( (int[]) ArgumentMatchers.any()); } @Test public void testNotifyCarrierRoamingNtnAvailableServicesChanged() throws Exception { when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true); when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true); mSatelliteControllerUT.setCallOnlySuperMethod(); List<String> overlayConfigPlmnList = new ArrayList<>(); replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig", mSatelliteControllerUT, overlayConfigPlmnList); mCarrierConfigBundle.putBoolean( CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true); List<String> entitlementPlmnList = Arrays.stream( new String[]{"00101", "00102", "00103", "00104"}).toList(); List<String> barredPlmnList = new ArrayList<>(); Map<String, List<Integer>> serviceTypeListMap = Map.of("00101", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), "00102", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), "00103", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS)); mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap, new HashMap<>(), new HashMap<>(), mIIntegerConsumer); int[] expectedServices = new int[]{1, 2, 3}; int[] supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn( SUB_ID); assertArrayEquals(expectedServices, supportedServices); verify(mPhone, times(1)).notifyCarrierRoamingNtnAvailableServicesChanged( (int[]) ArgumentMatchers.any()); } @Test public void testNotifyCarrierRoamingNtnAvailableServicesChange_duplicateUpdates() throws Exception { when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true); when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true); mSatelliteControllerUT.setCallOnlySuperMethod(); List<String> overlayConfigPlmnList = new ArrayList<>(); replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig", mSatelliteControllerUT, overlayConfigPlmnList); mCarrierConfigBundle.putBoolean( CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true); List<String> entitlementPlmnList = Arrays.stream( new String[]{"00101", "00102", "00103", "00104"}).toList(); List<String> barredPlmnList = new ArrayList<>(); Map<String, List<Integer>> serviceTypeListMap = Map.of("00101", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), "00102", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), "00103", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS)); mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap, new HashMap<>(), new HashMap<>(), mIIntegerConsumer); int[] expectedServices = new int[]{1, 2, 3}; int[] supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn( SUB_ID); assertArrayEquals(expectedServices, supportedServices); verify(mPhone, times(1)).notifyCarrierRoamingNtnAvailableServicesChanged( (int[]) ArgumentMatchers.any()); mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap, new HashMap<>(), new HashMap<>(), mIIntegerConsumer); // There is no change in services between 2 calls, so notify should not invoke again. supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn(SUB_ID); assertArrayEquals(expectedServices, supportedServices); verify(mPhone, times(1)).notifyCarrierRoamingNtnAvailableServicesChanged( (int[]) ArgumentMatchers.any()); } @Test public void testNotifyCarrierRoamingNtnAvailableServicesChange_multipleUpdates() throws Exception { when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true); when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true); mSatelliteControllerUT.setCallOnlySuperMethod(); List<String> overlayConfigPlmnList = new ArrayList<>(); replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig", mSatelliteControllerUT, overlayConfigPlmnList); mCarrierConfigBundle.putBoolean( CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true); List<String> entitlementPlmnList = Arrays.stream( new String[]{"00101", "00102", "00103", "00104"}).toList(); List<String> barredPlmnList = new ArrayList<>(); Map<String, List<Integer>> serviceTypeListMap = Map.of("00101", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), "00102", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), "00103", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS)); mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap, new HashMap<>(), new HashMap<>(), mIIntegerConsumer); int[] expectedServices = new int[]{1, 2, 3}; int[] supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn( SUB_ID); assertArrayEquals(expectedServices, supportedServices); verify(mPhone, times(1)).notifyCarrierRoamingNtnAvailableServicesChanged( (int[]) ArgumentMatchers.any()); serviceTypeListMap = Map.of("00101", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), "00102", List.of(SERVICE_TYPE_SMS), "00103", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS)); mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap, new HashMap<>(), new HashMap<>(), mIIntegerConsumer); expectedServices = new int[]{1, 3}; supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn(SUB_ID); assertArrayEquals(expectedServices, supportedServices); // 2 times notify called due to previous and current changes verify(mPhone, times(2)).notifyCarrierRoamingNtnAvailableServicesChanged( (int[]) ArgumentMatchers.any()); } } Loading
src/java/com/android/internal/telephony/satellite/SatelliteController.java +67 −5 Original line number Diff line number Diff line Loading @@ -4339,9 +4339,10 @@ public class SatelliteController extends Handler { mEntitlementPlmnListPerCarrier.put(subId, allowedPlmnList); mEntitlementBarredPlmnListPerCarrier.put(subId, barredPlmnList); mEntitlementDataPlanMapPerCarrier.put(subId, plmnDataPlanMap); mEntitlementServiceTypeMapPerCarrier.put(subId, plmnServiceTypeMap); mEntitlementDataServicePolicyMapPerCarrier.put(subId, plmnDataServicePolicyMap); mEntitlementVoiceServicePolicyMapPerCarrier.put(subId, plmnVoiceServicePolicyMap); updateAndNotifyChangesInCarrierRoamingNtnAvailableServices(subId, plmnServiceTypeMap); updatePlmnListPerCarrier(subId); configureSatellitePlmnForCarrier(subId); mSubscriptionManagerService.setSatelliteEntitlementPlmnList(subId, allowedPlmnList); Loading Loading @@ -8251,6 +8252,31 @@ public class SatelliteController extends Handler { .build(); } /** * The method will notify the change in the services update the * mEntitlementServiceTypeMapPerCarrier. * * @param subId : SubscriptionId * @param plmnServiceTypeMap : entitlement service map. */ private void updateAndNotifyChangesInCarrierRoamingNtnAvailableServices(int subId, Map<String, List<Integer>> plmnServiceTypeMap) { // If a service list is already cached, check it for changes int[] existingServices = getSupportedServicesOnCarrierRoamingNtn(subId); synchronized (mSupportedSatelliteServicesLock) { mEntitlementServiceTypeMapPerCarrier.put(subId, plmnServiceTypeMap); } int[] updatedServices = getSupportedServicesOnCarrierRoamingNtn(subId); if (existingServices.length > 0 && Arrays.equals(existingServices, updatedServices)) { plogd("No change in Entitlement service support data"); return; } if (mFeatureFlags.carrierRoamingNbIotNtn()) { updateLastNotifiedNtnAvailableServicesAndNotify(subId); evaluateCarrierRoamingNtnEligibilityChange(); } } @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) protected void handleCarrierRoamingNtnAvailableServicesChanged(int subId) { if (!mFeatureFlags.carrierRoamingNbIotNtn()) { Loading @@ -8277,11 +8303,47 @@ public class SatelliteController extends Handler { phone.notifyCarrierRoamingNtnAvailableServicesChanged(services); } /** Return services that are supported on carrier roaming non-terrestrial network. */ private int[] getAvailableServicesWithEntitlementForSubId(int subId) { synchronized (mSupportedSatelliteServicesLock) { Map<String, List<Integer>> allowedServicesList = mEntitlementServiceTypeMapPerCarrier.get(subId); if (allowedServicesList != null && !allowedServicesList.isEmpty()) { Set<Integer> serviceTypes = new HashSet<>(); for (List<Integer> values : allowedServicesList.values()) { serviceTypes.addAll(values); } int[] result = new int[serviceTypes.size()]; int i = 0; for (int value : serviceTypes) { result[i++] = value; } return result; } else { return new int[0]; // Return an empty array if the map is null or empty } } } /** * Given a subscription ID, this returns the carriers' supported services on * non-terrestrial networks. * * @param subId Associated subscription ID. * return supported services at entitlement for the available carriers. Note: If available * services/allowed service type field is empty at entitlement, information from * {@link * CarrierConfigManager#KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY} * will be returned. */ public int[] getSupportedServicesOnCarrierRoamingNtn(int subId) { if (isSatelliteSupportedViaCarrier(subId)) { // TODO: b/377367448 Cleanup get supported satellite services to align with starlink. int[] services = getSupportedSatelliteServicesForCarrier(subId); if (isValidSubscriptionId(subId) && isSatelliteSupportedViaCarrier(subId)) { // check available services supported at entitlement for sub id int[] services = getAvailableServicesWithEntitlementForSubId(subId); logd("getAvailableServicesWithEntitlementForSubId: " + Arrays.toString(services)); if (services.length == 0) { services = getSupportedSatelliteServicesForCarrier(subId); } if (isP2PSmsDisallowedOnCarrierRoamingNtn(subId)) { services = Arrays.stream(services).filter( value -> value != NetworkRegistrationInfo.SERVICE_TYPE_SMS).toArray(); Loading
tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java +153 −1 Original line number Diff line number Diff line Loading @@ -207,6 +207,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; Loading Loading @@ -6191,6 +6192,8 @@ public class SatelliteControllerTest extends TelephonyTest { public int selectedSatelliteSubId = -1; public boolean isSatelliteProvisioned; private boolean callOnlySuperMethod = false; TestSatelliteController( Context context, Looper looper, @NonNull FeatureFlags featureFlags) { super(context, looper, featureFlags); Loading Loading @@ -6282,8 +6285,12 @@ public class SatelliteControllerTest extends TelephonyTest { @Override protected void handleCarrierRoamingNtnAvailableServicesChanged(int subId) { if (callOnlySuperMethod) { super.handleCarrierRoamingNtnAvailableServicesChanged(subId); } else { isApplicationUpdated = true; } } @Override public boolean isApplicationSupportsP2P(String packageName) { Loading @@ -6292,6 +6299,9 @@ public class SatelliteControllerTest extends TelephonyTest { @Override public int[] getSupportedServicesOnCarrierRoamingNtn(int subId) { if (callOnlySuperMethod) { return super.getSupportedServicesOnCarrierRoamingNtn(subId); } return new int[]{3, 5}; } Loading Loading @@ -6373,6 +6383,10 @@ public class SatelliteControllerTest extends TelephonyTest { mSatelliteAccessAllowed = isAllowed; } } public void setCallOnlySuperMethod() { callOnlySuperMethod = true; } } @Test Loading Loading @@ -6684,4 +6698,142 @@ public class SatelliteControllerTest extends TelephonyTest { .getSatelliteDataServicePolicyForPlmn(SUB_ID, "00101"); assertEquals(SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED, dataSupportModeForPlmn); } @Test public void testNotifyCarrierRoamingNtnAvailableServicesChanged_noServices() throws Exception { when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true); when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true); mSatelliteControllerUT.setCallOnlySuperMethod(); List<String> overlayConfigPlmnList = new ArrayList<>(); replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig", mSatelliteControllerUT, overlayConfigPlmnList); mCarrierConfigBundle.putBoolean( CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true); List<String> entitlementPlmnList = Arrays.stream( new String[]{"00101", "00102", "00103", "00104"}).toList(); mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, entitlementPlmnList, new ArrayList<>(), new HashMap<>(), new HashMap<>() /*serviceTypeListMap*/, new HashMap<>(), new HashMap<>(), mIIntegerConsumer); verify(mPhone, times(1)).notifyCarrierRoamingNtnAvailableServicesChanged( (int[]) ArgumentMatchers.any()); } @Test public void testNotifyCarrierRoamingNtnAvailableServicesChanged() throws Exception { when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true); when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true); mSatelliteControllerUT.setCallOnlySuperMethod(); List<String> overlayConfigPlmnList = new ArrayList<>(); replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig", mSatelliteControllerUT, overlayConfigPlmnList); mCarrierConfigBundle.putBoolean( CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true); List<String> entitlementPlmnList = Arrays.stream( new String[]{"00101", "00102", "00103", "00104"}).toList(); List<String> barredPlmnList = new ArrayList<>(); Map<String, List<Integer>> serviceTypeListMap = Map.of("00101", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), "00102", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), "00103", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS)); mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap, new HashMap<>(), new HashMap<>(), mIIntegerConsumer); int[] expectedServices = new int[]{1, 2, 3}; int[] supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn( SUB_ID); assertArrayEquals(expectedServices, supportedServices); verify(mPhone, times(1)).notifyCarrierRoamingNtnAvailableServicesChanged( (int[]) ArgumentMatchers.any()); } @Test public void testNotifyCarrierRoamingNtnAvailableServicesChange_duplicateUpdates() throws Exception { when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true); when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true); mSatelliteControllerUT.setCallOnlySuperMethod(); List<String> overlayConfigPlmnList = new ArrayList<>(); replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig", mSatelliteControllerUT, overlayConfigPlmnList); mCarrierConfigBundle.putBoolean( CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true); List<String> entitlementPlmnList = Arrays.stream( new String[]{"00101", "00102", "00103", "00104"}).toList(); List<String> barredPlmnList = new ArrayList<>(); Map<String, List<Integer>> serviceTypeListMap = Map.of("00101", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), "00102", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), "00103", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS)); mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap, new HashMap<>(), new HashMap<>(), mIIntegerConsumer); int[] expectedServices = new int[]{1, 2, 3}; int[] supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn( SUB_ID); assertArrayEquals(expectedServices, supportedServices); verify(mPhone, times(1)).notifyCarrierRoamingNtnAvailableServicesChanged( (int[]) ArgumentMatchers.any()); mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap, new HashMap<>(), new HashMap<>(), mIIntegerConsumer); // There is no change in services between 2 calls, so notify should not invoke again. supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn(SUB_ID); assertArrayEquals(expectedServices, supportedServices); verify(mPhone, times(1)).notifyCarrierRoamingNtnAvailableServicesChanged( (int[]) ArgumentMatchers.any()); } @Test public void testNotifyCarrierRoamingNtnAvailableServicesChange_multipleUpdates() throws Exception { when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true); when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true); mSatelliteControllerUT.setCallOnlySuperMethod(); List<String> overlayConfigPlmnList = new ArrayList<>(); replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig", mSatelliteControllerUT, overlayConfigPlmnList); mCarrierConfigBundle.putBoolean( CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true); mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true); List<String> entitlementPlmnList = Arrays.stream( new String[]{"00101", "00102", "00103", "00104"}).toList(); List<String> barredPlmnList = new ArrayList<>(); Map<String, List<Integer>> serviceTypeListMap = Map.of("00101", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), "00102", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), "00103", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS)); mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap, new HashMap<>(), new HashMap<>(), mIIntegerConsumer); int[] expectedServices = new int[]{1, 2, 3}; int[] supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn( SUB_ID); assertArrayEquals(expectedServices, supportedServices); verify(mPhone, times(1)).notifyCarrierRoamingNtnAvailableServicesChanged( (int[]) ArgumentMatchers.any()); serviceTypeListMap = Map.of("00101", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), "00102", List.of(SERVICE_TYPE_SMS), "00103", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS)); mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap, new HashMap<>(), new HashMap<>(), mIIntegerConsumer); expectedServices = new int[]{1, 3}; supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn(SUB_ID); assertArrayEquals(expectedServices, supportedServices); // 2 times notify called due to previous and current changes verify(mPhone, times(2)).notifyCarrierRoamingNtnAvailableServicesChanged( (int[]) ArgumentMatchers.any()); } }