diff --git a/src/com/android/settings/network/telephony/NetworkSelectRepository.kt b/src/com/android/settings/network/telephony/NetworkSelectRepository.kt index 1f5fbc202f5..d95c90e5c19 100644 --- a/src/com/android/settings/network/telephony/NetworkSelectRepository.kt +++ b/src/com/android/settings/network/telephony/NetworkSelectRepository.kt @@ -18,8 +18,10 @@ package com.android.settings.network.telephony import android.content.Context import android.telephony.AccessNetworkConstants +import android.telephony.CarrierConfigManager import android.telephony.NetworkRegistrationInfo import android.telephony.TelephonyManager +import android.telephony.satellite.SatelliteManager import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.lifecycleScope @@ -28,9 +30,11 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -class NetworkSelectRepository(context: Context, subId: Int) { +class NetworkSelectRepository(context: Context, private val subId: Int) { private val telephonyManager = context.getSystemService(TelephonyManager::class.java)!!.createForSubscriptionId(subId) + private val satelliteManager = context.getSystemService(SatelliteManager::class.java) + private val carrierConfigManager = context.getSystemService(CarrierConfigManager::class.java) data class NetworkRegistrationAndForbiddenInfo( val networkList: List, @@ -55,10 +59,21 @@ class NetworkSelectRepository(context: Context, subId: Int) { if (telephonyManager.dataState != TelephonyManager.DATA_CONNECTED) return null // Try to get the network registration states val serviceState = telephonyManager.serviceState ?: return null - val networkList = serviceState.getNetworkRegistrationInfoListForTransportType( + var networkList = serviceState.getNetworkRegistrationInfoListForTransportType( AccessNetworkConstants.TRANSPORT_TYPE_WWAN ) if (networkList.isEmpty()) return null + + val satellitePlmn = getSatellitePlmns() + // If connected network is Satellite, filter out + if (satellitePlmn.isNotEmpty()) { + val filteredNetworkList = networkList.filter { + val cellIdentity = it.cellIdentity + val plmn = cellIdentity?.plmn + plmn != null && !satellitePlmn.contains(plmn) + } + networkList = filteredNetworkList + } // Due to the aggregation of cell between carriers, it's possible to get CellIdentity // containing forbidden PLMN. // Getting current network from ServiceState is no longer a good idea. @@ -72,4 +87,24 @@ class NetworkSelectRepository(context: Context, subId: Int) { private fun getForbiddenPlmns(): List { return telephonyManager.forbiddenPlmns?.toList() ?: emptyList() } + + /** + * Update satellite PLMNs from the satellite framework. + */ + private fun getSatellitePlmns(): List { + val config = carrierConfigManager.getConfigForSubId( + subId, + CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL + ) + + val shouldFilter = config.getBoolean( + CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL, + true) + + return if (shouldFilter) { + satelliteManager.getSatellitePlmnsForCarrier(subId) + } else { + emptyList(); + } + } } diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/NetworkSelectRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/NetworkSelectRepositoryTest.kt index 4137de494bc..0cbfe02dd42 100644 --- a/tests/spa_unit/src/com/android/settings/network/telephony/NetworkSelectRepositoryTest.kt +++ b/tests/spa_unit/src/com/android/settings/network/telephony/NetworkSelectRepositoryTest.kt @@ -17,20 +17,21 @@ package com.android.settings.network.telephony import android.content.Context -import android.telephony.AccessNetworkConstants -import android.telephony.NetworkRegistrationInfo -import android.telephony.ServiceState -import android.telephony.TelephonyManager +import android.os.PersistableBundle +import android.telephony.* +import android.telephony.satellite.SatelliteManager import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.network.telephony.scan.NetworkScanRepositoryTest import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.anyInt import org.mockito.kotlin.doReturn import org.mockito.kotlin.mock import org.mockito.kotlin.spy import org.mockito.kotlin.stub +import org.mockito.kotlin.whenever @RunWith(AndroidJUnit4::class) class NetworkSelectRepositoryTest { @@ -49,8 +50,16 @@ class NetworkSelectRepositoryTest { on { serviceState } doReturn mockServiceState } + private val mockSatelliteManager = mock { + on { getSatellitePlmnsForCarrier(anyInt()) } doReturn SatellitePlmns + } + + private var mockCarrierConfigManager = mock() + private val context: Context = spy(ApplicationProvider.getApplicationContext()) { on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager + on { getSystemService(SatelliteManager::class.java) } doReturn mockSatelliteManager + on { getSystemService(CarrierConfigManager::class.java) } doReturn mockCarrierConfigManager } private val repository = NetworkSelectRepository(context, SUB_ID) @@ -105,6 +114,14 @@ class NetworkSelectRepositoryTest { on { forbiddenPlmns } doReturn arrayOf(FORBIDDEN_PLMN) } + val config = PersistableBundle() + config.putBoolean( + CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL, + false) + whenever(mockCarrierConfigManager.getConfigForSubId( + SUB_ID, CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL)) + .thenReturn(config) + val info = repository.getNetworkRegistrationInfo() assertThat(info).isEqualTo( @@ -115,9 +132,76 @@ class NetworkSelectRepositoryTest { ) } + @Test + fun getNetworkRegistrationInfo_filterSatellitePlmn() { + + val info1 = createTestNetworkRegistrationInfo("310", "260") + val info2 = createTestNetworkRegistrationInfo("310", "261") + val satelliteInfo = createTestNetworkRegistrationInfo(satelliteMcc, satelliteMnc) + val registrationInfos = listOf(info1, info2, satelliteInfo) + val filteredRegistrationInfos = listOf(info1, info2) + + mockServiceState.stub { + on { + getNetworkRegistrationInfoListForTransportType( + AccessNetworkConstants.TRANSPORT_TYPE_WWAN + ) + } doReturn registrationInfos + } + mockTelephonyManager.stub { + on { forbiddenPlmns } doReturn arrayOf(FORBIDDEN_PLMN) + } + + // disable satellite plmn filter + var config = PersistableBundle() + config.putBoolean( + CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL, + false) + whenever(mockCarrierConfigManager.getConfigForSubId( + SUB_ID, CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL)) + .thenReturn(config) + + var infoList = repository.getNetworkRegistrationInfo() + + assertThat(infoList).isEqualTo( + NetworkSelectRepository.NetworkRegistrationAndForbiddenInfo( + networkList = registrationInfos, + forbiddenPlmns = listOf(FORBIDDEN_PLMN), + ) + ) + + // enable satellite plmn filter + config = PersistableBundle() + config.putBoolean( + CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL, + true) + whenever(mockCarrierConfigManager.getConfigForSubId( + SUB_ID, CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL)) + .thenReturn(config) + + infoList = repository.getNetworkRegistrationInfo() + + assertThat(infoList).isEqualTo( + NetworkSelectRepository.NetworkRegistrationAndForbiddenInfo( + networkList = filteredRegistrationInfos, + forbiddenPlmns = listOf(FORBIDDEN_PLMN), + ) + ) + } + private companion object { const val SUB_ID = 1 val NetworkRegistrationInfos = listOf(NetworkRegistrationInfo.Builder().build()) const val FORBIDDEN_PLMN = "Forbidden PLMN" + const val satelliteMcc = "310" + const val satelliteMnc = "810" + val SatellitePlmns = listOf(satelliteMcc + satelliteMnc) + + fun createTestNetworkRegistrationInfo(mcc: String, mnc: String): NetworkRegistrationInfo { + val cellInfo = CellIdentityLte(0, 0, 0, 0, IntArray(2) { 0 }, + 0, mcc, mnc, "", "", emptyList(), null) + + return NetworkRegistrationInfo.Builder().setCellIdentity(cellInfo).build() + } } }