Use network country code to disallow satellite
Bug: 358375489
Flag: com.android.internal.telephony.flags.oem_enabled_satellite_flag
Test: atest SatelliteAccessControllerTest(http://ab/I91500010308418737-passed)
Test: Manually verified the pixel satellite is not supported when the network-mcc is not in the allowed list. (more details are at b/358375489#comment4)
Change-Id: I8de6860313253af12ebb1961dc468ca80d2dd9ef
diff --git a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
index 75a1fb4..1e3aa2f 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
@@ -771,7 +771,8 @@
mConfigUpdaterMetricsStats.reportConfigUpdateSuccess();
}
- private void loadOverlayConfigs(@NonNull Context context) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected void loadOverlayConfigs(@NonNull Context context) {
mSatelliteCountryCodes = getSatelliteCountryCodesFromOverlayConfig(context);
mIsSatelliteAllowAccessControl = getSatelliteAccessAllowFromOverlayConfig(context);
String satelliteS2CellFileName = getSatelliteS2CellFileFromOverlayConfig(context);
@@ -911,6 +912,30 @@
}
}
+ /**
+ * At country borders, a multi-SIM device might connect to multiple cellular base
+ * stations and thus might have multiple different MCCs.
+ * In such cases, framework is not sure whether the region should be disallowed or not,
+ * and thus the geofence data will be used to decide whether to allow satellite.
+ */
+ private boolean isRegionDisallowed(List<String> networkCountryIsoList) {
+ if (networkCountryIsoList.isEmpty()) {
+ plogd("isRegionDisallowed : true : it's not sure if empty is disallowed");
+ return false;
+ }
+
+ for (String countryCode : networkCountryIsoList) {
+ if (isSatelliteAccessAllowedForLocation(List.of(countryCode))) {
+ plogd("isRegionDisallowed : false : Country Code " + countryCode
+ + " is in the list from the configuration");
+ return false;
+ }
+ }
+
+ plogd("isRegionDisallowed : true : " + networkCountryIsoList);
+ return true;
+ }
+
private void handleIsSatelliteSupportedResult(int resultCode, Bundle resultData) {
plogd("handleIsSatelliteSupportedResult: resultCode=" + resultCode);
synchronized (mLock) {
@@ -925,7 +950,19 @@
sendSatelliteAllowResultToReceivers(resultCode, bundle, false);
} else {
plogd("Satellite is supported");
- checkSatelliteAccessRestrictionUsingGPS();
+ List<String> networkCountryIsoList =
+ mCountryDetector.getCurrentNetworkCountryIso();
+ if (isRegionDisallowed(networkCountryIsoList)) {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED, false);
+ mAccessControllerMetricsStats.setAccessControlType(
+ SatelliteConstants.ACCESS_CONTROL_TYPE_NETWORK_COUNTRY_CODE)
+ .setCountryCodes(networkCountryIsoList);
+ sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle,
+ false);
+ } else {
+ checkSatelliteAccessRestrictionUsingGPS();
+ }
}
} else {
ploge("KEY_SATELLITE_SUPPORTED does not exist.");
@@ -1336,7 +1373,8 @@
return true;
}
- private boolean isSatelliteAccessAllowedForLocation(
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected boolean isSatelliteAccessAllowedForLocation(
@NonNull List<String> networkCountryIsoList) {
if (isSatelliteAllowAccessControl()) {
// The current country is unidentified, we're uncertain and thus returning false
diff --git a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
index cbca7b7..87c73ac 100644
--- a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
+++ b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
@@ -115,8 +115,14 @@
public class SatelliteAccessControllerTest {
private static final String TAG = "SatelliteAccessControllerTest";
private static final String[] TEST_SATELLITE_COUNTRY_CODES = {"US", "CA", "UK"};
+ private static final String[] TEST_SATELLITE_COUNTRY_CODES_EMPTY = {""};
+ private static final String TEST_SATELLITE_COUNTRY_CODE_US = "US";
+ private static final String TEST_SATELLITE_COUNTRY_CODE_KR = "KR";
+ private static final String TEST_SATELLITE_COUNTRY_CODE_JP = "JP";
+
private static final String TEST_SATELLITE_S2_FILE = "sat_s2_file.dat";
private static final boolean TEST_SATELLITE_ALLOW = true;
+ private static final boolean TEST_SATELLITE_NOT_ALLOW = false;
private static final int TEST_LOCATION_FRESH_DURATION_SECONDS = 10;
private static final long TEST_LOCATION_FRESH_DURATION_NANOS =
TimeUnit.SECONDS.toNanos(TEST_LOCATION_FRESH_DURATION_SECONDS);
@@ -332,6 +338,269 @@
}
@Test
+ public void testIsSatelliteAccessAllowedForLocation() {
+ when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+
+ // Test disallowList case
+ when(mMockResources.getBoolean(
+ com.android.internal.R.bool.config_oem_enabled_satellite_access_allow))
+ .thenReturn(TEST_SATELLITE_NOT_ALLOW);
+
+ // configuration is EMPTY then we return true with any network country code.
+ when(mMockResources.getStringArray(
+ com.android.internal.R.array.config_oem_enabled_satellite_country_codes))
+ .thenReturn(TEST_SATELLITE_COUNTRY_CODES_EMPTY);
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ assertTrue(mSatelliteAccessControllerUT
+ .isSatelliteAccessAllowedForLocation(List.of(TEST_SATELLITE_COUNTRY_CODE_US)));
+ assertTrue(mSatelliteAccessControllerUT
+ .isSatelliteAccessAllowedForLocation(List.of(TEST_SATELLITE_COUNTRY_CODE_JP)));
+
+ // configuration is ["US", "CA", "UK"]
+ // - if network country code is ["US"] or ["US","KR"] or [EMPTY] return false;
+ // - if network country code is ["KR"] return true;
+ when(mMockResources.getStringArray(
+ com.android.internal.R.array.config_oem_enabled_satellite_country_codes))
+ .thenReturn(TEST_SATELLITE_COUNTRY_CODES);
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ assertFalse(mSatelliteAccessControllerUT.isSatelliteAccessAllowedForLocation(List.of()));
+ assertFalse(mSatelliteAccessControllerUT
+ .isSatelliteAccessAllowedForLocation(List.of(TEST_SATELLITE_COUNTRY_CODE_US)));
+ assertFalse(mSatelliteAccessControllerUT.isSatelliteAccessAllowedForLocation(
+ List.of(TEST_SATELLITE_COUNTRY_CODE_US, TEST_SATELLITE_COUNTRY_CODE_KR)));
+ assertTrue(mSatelliteAccessControllerUT
+ .isSatelliteAccessAllowedForLocation(List.of(TEST_SATELLITE_COUNTRY_CODE_KR)));
+
+ // Test allowList case
+ when(mMockResources.getBoolean(
+ com.android.internal.R.bool.config_oem_enabled_satellite_access_allow))
+ .thenReturn(TEST_SATELLITE_ALLOW);
+
+ // configuration is [EMPTY] then return false in case of any network country code
+ when(mMockResources.getStringArray(
+ com.android.internal.R.array.config_oem_enabled_satellite_country_codes))
+ .thenReturn(TEST_SATELLITE_COUNTRY_CODES_EMPTY);
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ assertFalse(mSatelliteAccessControllerUT
+ .isSatelliteAccessAllowedForLocation(List.of(TEST_SATELLITE_COUNTRY_CODE_US)));
+ assertFalse(mSatelliteAccessControllerUT
+ .isSatelliteAccessAllowedForLocation(List.of(TEST_SATELLITE_COUNTRY_CODE_JP)));
+
+ // configuration is ["US", "CA", "UK"]
+ // - if network country code is [EMPTY] or ["US","KR"] or [KR] return false;
+ // - if network country code is ["US"] return true;
+ when(mMockResources.getStringArray(
+ com.android.internal.R.array.config_oem_enabled_satellite_country_codes))
+ .thenReturn(TEST_SATELLITE_COUNTRY_CODES);
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ assertFalse(mSatelliteAccessControllerUT.isSatelliteAccessAllowedForLocation(List.of()));
+ assertFalse(mSatelliteAccessControllerUT
+ .isSatelliteAccessAllowedForLocation(List.of(TEST_SATELLITE_COUNTRY_CODE_KR)));
+ assertFalse(mSatelliteAccessControllerUT.isSatelliteAccessAllowedForLocation(
+ List.of(TEST_SATELLITE_COUNTRY_CODE_US, TEST_SATELLITE_COUNTRY_CODE_KR)));
+ assertTrue(mSatelliteAccessControllerUT
+ .isSatelliteAccessAllowedForLocation(List.of(TEST_SATELLITE_COUNTRY_CODE_US)));
+ }
+
+ @Test
+ public void testIsRegionDisallowed() throws Exception {
+ // setup to make the return value of mQueriedSatelliteAllowed 'true'
+ when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ when(mMockContext.getResources()).thenReturn(mMockResources);
+ when(mMockResources.getBoolean(
+ com.android.internal.R.bool.config_oem_enabled_satellite_access_allow))
+ .thenReturn(TEST_SATELLITE_ALLOW);
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ doReturn(true).when(mMockLocationManager).isLocationEnabled();
+ when(mMockSatelliteOnDeviceAccessController.isSatCommunicationAllowedAtLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class))).thenReturn(true);
+ replaceInstance(SatelliteAccessController.class, "mCachedAccessRestrictionMap",
+ mSatelliteAccessControllerUT, mMockCachedAccessRestrictionMap);
+ doReturn(true).when(mMockCachedAccessRestrictionMap).containsKey(any());
+ doReturn(true).when(mMockCachedAccessRestrictionMap).get(any());
+
+ // get allowed country codes EMPTY from resources
+ when(mMockResources.getStringArray(
+ com.android.internal.R.array.config_oem_enabled_satellite_country_codes))
+ .thenReturn(TEST_SATELLITE_COUNTRY_CODES_EMPTY);
+
+ // allow case that network country codes [US] with [EMPTY] configuration
+ // location will not be compared and mQueriedSatelliteAllowed will be set false
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso())
+ .thenReturn(List.of(TEST_SATELLITE_COUNTRY_CODE_US));
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(0)).containsKey(any());
+ assertFalse(mQueriedSatelliteAllowed);
+
+ // allow case that network country codes [EMPTY] with [EMPTY] configuration
+ // location will be compared and mQueriedSatelliteAllowed will be set true
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(List.of());
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(1)).containsKey(any());
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // get allowed country codes [US, CA, UK] from resources
+ when(mMockResources.getStringArray(
+ com.android.internal.R.array.config_oem_enabled_satellite_country_codes))
+ .thenReturn(TEST_SATELLITE_COUNTRY_CODES);
+
+ // allow case that network country codes [US, CA, UK] with [US, CA, UK] configuration
+ // location will be compared and mQueriedSatelliteAllowed will be set true
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso())
+ .thenReturn(List.of(TEST_SATELLITE_COUNTRY_CODES));
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(1)).containsKey(any());
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // allow case that network country codes [US] with [US, CA, UK] configuration
+ // location will be compared and mQueriedSatelliteAllowed will be set true
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso())
+ .thenReturn(List.of(TEST_SATELLITE_COUNTRY_CODE_US));
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(1)).containsKey(any());
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // allow case that network country codes [US, KR] with [US, CA, UK] configuration
+ // location will be compared and mQueriedSatelliteAllowed will be set true
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(
+ List.of(TEST_SATELLITE_COUNTRY_CODE_US, TEST_SATELLITE_COUNTRY_CODE_KR));
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(1)).containsKey(any());
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // allow case that network country codes [US] with [EMPTY] configuration
+ // location will be compared and mQueriedSatelliteAllowed will be set true
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(List.of());
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(1)).containsKey(any());
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // allow case that network country codes [KR, JP] with [US, CA, UK] configuration
+ // location will not be compared and mQueriedSatelliteAllowed will be set false
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(
+ List.of(TEST_SATELLITE_COUNTRY_CODE_KR, TEST_SATELLITE_COUNTRY_CODE_JP));
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(0)).containsKey(any());
+ assertFalse(mQueriedSatelliteAllowed);
+
+ // allow case that network country codes [KR] with [US, CA, UK] configuration
+ // location will not be compared and mQueriedSatelliteAllowed will be set false
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso())
+ .thenReturn(List.of(TEST_SATELLITE_COUNTRY_CODE_KR));
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(0)).containsKey(any());
+ assertFalse(mQueriedSatelliteAllowed);
+
+
+ // set disallowed list case
+ when(mMockResources.getBoolean(
+ com.android.internal.R.bool.config_oem_enabled_satellite_access_allow))
+ .thenReturn(TEST_SATELLITE_NOT_ALLOW);
+ // get disallowed country codes list [EMPTY] from resources
+ when(mMockResources.getStringArray(
+ com.android.internal.R.array.config_oem_enabled_satellite_country_codes))
+ .thenReturn(TEST_SATELLITE_COUNTRY_CODES_EMPTY);
+
+ // disallow case that network country codes [US] with [EMPTY] configuration
+ // location will be compared and mQueriedSatelliteAllowed will be set true
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso())
+ .thenReturn(List.of(TEST_SATELLITE_COUNTRY_CODE_US));
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(1)).containsKey(any());
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // get disallowed country codes list ["US", "CA", "UK"] from resources
+ when(mMockResources.getStringArray(
+ com.android.internal.R.array.config_oem_enabled_satellite_country_codes))
+ .thenReturn(TEST_SATELLITE_COUNTRY_CODES);
+
+ // disallow case that network country codes [EMPTY] with [US, CA, UK] configuration
+ // location will be compared and mQueriedSatelliteAllowed will be set true
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso())
+ .thenReturn(List.of(TEST_SATELLITE_COUNTRY_CODES_EMPTY));
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(1)).containsKey(any());
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // disallow case that network country codes [US, JP] with [US, CA, UK] configuration
+ // location will be compared and mQueriedSatelliteAllowed will be set true
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(
+ List.of(TEST_SATELLITE_COUNTRY_CODE_US, TEST_SATELLITE_COUNTRY_CODE_JP));
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(1)).containsKey(any());
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // disallow case that network country codes [JP] with [US, CA, UK] configuration
+ // location will be compared and mQueriedSatelliteAllowed will be set true
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso())
+ .thenReturn(List.of(TEST_SATELLITE_COUNTRY_CODE_JP));
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(1)).containsKey(any());
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // disallow case that network country codes [US] with [US, CA, UK] configuration
+ // location will not be compared and mQueriedSatelliteAllowed will be set false
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockCountryDetector.getCurrentNetworkCountryIso())
+ .thenReturn(List.of(TEST_SATELLITE_COUNTRY_CODE_US));
+ mSatelliteAccessControllerUT.loadOverlayConfigs(mMockContext);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockCachedAccessRestrictionMap, times(0)).containsKey(any());
+ assertFalse(mQueriedSatelliteAllowed);
+ }
+
+ @Test
public void testRequestIsSatelliteCommunicationAllowedForCurrentLocation() throws Exception {
// OEM-enabled satellite is not supported
when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
@@ -409,6 +678,8 @@
when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(EMPTY_STRING_LIST);
when(mMockTelecomManager.isInEmergencyCall()).thenReturn(false);
when(mMockPhone.isInEcm()).thenReturn(true);
+ when(mMockPhone.getContext()).thenReturn(mMockContext);
+ when(mMockPhone2.getContext()).thenReturn(mMockContext);
mSatelliteAccessControllerUT.elapsedRealtimeNanos = TEST_LOCATION_FRESH_DURATION_NANOS + 1;
when(mMockLocation0.getElapsedRealtimeNanos()).thenReturn(0L);
when(mMockLocation1.getElapsedRealtimeNanos()).thenReturn(0L);