Merge "Filter out the satellite PLMNs from the current connected network" into main

This commit is contained in:
Hakjun Choi
2024-08-15 19:46:59 +00:00
committed by Android (Google) Code Review
2 changed files with 125 additions and 6 deletions

View File

@@ -18,8 +18,10 @@ package com.android.settings.network.telephony
import android.content.Context import android.content.Context
import android.telephony.AccessNetworkConstants import android.telephony.AccessNetworkConstants
import android.telephony.CarrierConfigManager
import android.telephony.NetworkRegistrationInfo import android.telephony.NetworkRegistrationInfo
import android.telephony.TelephonyManager import android.telephony.TelephonyManager
import android.telephony.satellite.SatelliteManager
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@@ -28,9 +30,11 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
class NetworkSelectRepository(context: Context, subId: Int) { class NetworkSelectRepository(context: Context, private val subId: Int) {
private val telephonyManager = private val telephonyManager =
context.getSystemService(TelephonyManager::class.java)!!.createForSubscriptionId(subId) 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( data class NetworkRegistrationAndForbiddenInfo(
val networkList: List<NetworkRegistrationInfo>, val networkList: List<NetworkRegistrationInfo>,
@@ -55,10 +59,21 @@ class NetworkSelectRepository(context: Context, subId: Int) {
if (telephonyManager.dataState != TelephonyManager.DATA_CONNECTED) return null if (telephonyManager.dataState != TelephonyManager.DATA_CONNECTED) return null
// Try to get the network registration states // Try to get the network registration states
val serviceState = telephonyManager.serviceState ?: return null val serviceState = telephonyManager.serviceState ?: return null
val networkList = serviceState.getNetworkRegistrationInfoListForTransportType( var networkList = serviceState.getNetworkRegistrationInfoListForTransportType(
AccessNetworkConstants.TRANSPORT_TYPE_WWAN AccessNetworkConstants.TRANSPORT_TYPE_WWAN
) )
if (networkList.isEmpty()) return null 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 // Due to the aggregation of cell between carriers, it's possible to get CellIdentity
// containing forbidden PLMN. // containing forbidden PLMN.
// Getting current network from ServiceState is no longer a good idea. // 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<String> { private fun getForbiddenPlmns(): List<String> {
return telephonyManager.forbiddenPlmns?.toList() ?: emptyList() return telephonyManager.forbiddenPlmns?.toList() ?: emptyList()
} }
/**
* Update satellite PLMNs from the satellite framework.
*/
private fun getSatellitePlmns(): List<String> {
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();
}
}
} }

View File

@@ -17,20 +17,21 @@
package com.android.settings.network.telephony package com.android.settings.network.telephony
import android.content.Context import android.content.Context
import android.telephony.AccessNetworkConstants import android.os.PersistableBundle
import android.telephony.NetworkRegistrationInfo import android.telephony.*
import android.telephony.ServiceState import android.telephony.satellite.SatelliteManager
import android.telephony.TelephonyManager
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.network.telephony.scan.NetworkScanRepositoryTest import com.android.settings.network.telephony.scan.NetworkScanRepositoryTest
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.kotlin.doReturn import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock import org.mockito.kotlin.mock
import org.mockito.kotlin.spy import org.mockito.kotlin.spy
import org.mockito.kotlin.stub import org.mockito.kotlin.stub
import org.mockito.kotlin.whenever
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class NetworkSelectRepositoryTest { class NetworkSelectRepositoryTest {
@@ -49,8 +50,16 @@ class NetworkSelectRepositoryTest {
on { serviceState } doReturn mockServiceState on { serviceState } doReturn mockServiceState
} }
private val mockSatelliteManager = mock<SatelliteManager> {
on { getSatellitePlmnsForCarrier(anyInt()) } doReturn SatellitePlmns
}
private var mockCarrierConfigManager = mock<CarrierConfigManager>()
private val context: Context = spy(ApplicationProvider.getApplicationContext()) { private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager 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) private val repository = NetworkSelectRepository(context, SUB_ID)
@@ -105,6 +114,14 @@ class NetworkSelectRepositoryTest {
on { forbiddenPlmns } doReturn arrayOf(FORBIDDEN_PLMN) 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() val info = repository.getNetworkRegistrationInfo()
assertThat(info).isEqualTo( 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 { private companion object {
const val SUB_ID = 1 const val SUB_ID = 1
val NetworkRegistrationInfos = listOf(NetworkRegistrationInfo.Builder().build()) val NetworkRegistrationInfos = listOf(NetworkRegistrationInfo.Builder().build())
const val FORBIDDEN_PLMN = "Forbidden PLMN" 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()
}
} }
} }