1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.network.telephony 18 19 import android.content.Context 20 import android.telephony.AccessNetworkConstants 21 import android.telephony.CarrierConfigManager 22 import android.telephony.NetworkRegistrationInfo 23 import android.telephony.TelephonyManager 24 import android.telephony.satellite.SatelliteManager 25 import android.util.Log 26 import androidx.lifecycle.Lifecycle 27 import androidx.lifecycle.LifecycleOwner 28 import androidx.lifecycle.lifecycleScope 29 import androidx.lifecycle.repeatOnLifecycle 30 import kotlinx.coroutines.Dispatchers 31 import kotlinx.coroutines.launch 32 import kotlinx.coroutines.withContext 33 34 class NetworkSelectRepository(context: Context, private val subId: Int) { 35 private val telephonyManager = 36 context.getSystemService(TelephonyManager::class.java)!!.createForSubscriptionId(subId) 37 private val satelliteManager = context.getSystemService(SatelliteManager::class.java) 38 private val carrierConfigManager = context.getSystemService(CarrierConfigManager::class.java) 39 40 data class NetworkRegistrationAndForbiddenInfo( 41 val networkList: List<NetworkRegistrationInfo>, 42 val forbiddenPlmns: List<String>, 43 ) 44 45 /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */ launchUpdateNetworkRegistrationInfonull46 fun launchUpdateNetworkRegistrationInfo( 47 lifecycleOwner: LifecycleOwner, 48 action: (NetworkRegistrationAndForbiddenInfo) -> Unit, 49 ) { 50 lifecycleOwner.lifecycleScope.launch { 51 lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { 52 withContext(Dispatchers.Default) { 53 getNetworkRegistrationInfo() 54 }?.let(action) 55 } 56 } 57 } 58 getNetworkRegistrationInfonull59 fun getNetworkRegistrationInfo(): NetworkRegistrationAndForbiddenInfo? { 60 if (telephonyManager.dataState != TelephonyManager.DATA_CONNECTED) return null 61 // Try to get the network registration states 62 val serviceState = telephonyManager.serviceState ?: return null 63 var networkList = serviceState.getNetworkRegistrationInfoListForTransportType( 64 AccessNetworkConstants.TRANSPORT_TYPE_WWAN 65 ) 66 if (networkList.isEmpty()) return null 67 68 val satellitePlmn = getSatellitePlmns() 69 // If connected network is Satellite, filter out 70 if (satellitePlmn.isNotEmpty()) { 71 val filteredNetworkList = networkList.filter { 72 val cellIdentity = it.cellIdentity 73 val plmn = cellIdentity?.plmn 74 plmn != null && !satellitePlmn.contains(plmn) 75 } 76 networkList = filteredNetworkList 77 } 78 // Due to the aggregation of cell between carriers, it's possible to get CellIdentity 79 // containing forbidden PLMN. 80 // Getting current network from ServiceState is no longer a good idea. 81 // Add an additional rule to avoid from showing forbidden PLMN to the user. 82 return NetworkRegistrationAndForbiddenInfo(networkList, getForbiddenPlmns()) 83 } 84 85 /** 86 * Update forbidden PLMNs from the USIM App 87 */ getForbiddenPlmnsnull88 private fun getForbiddenPlmns(): List<String> { 89 return telephonyManager.forbiddenPlmns?.toList() ?: emptyList() 90 } 91 92 /** 93 * Update satellite PLMNs from the satellite framework. 94 */ getSatellitePlmnsnull95 private fun getSatellitePlmns(): List<String> { 96 if (satelliteManager == null) { 97 Log.d(TAG, "SatelliteManager is null") 98 return emptyList() 99 } 100 101 if (carrierConfigManager == null) { 102 Log.d(TAG, "carrierConfigManager is null") 103 return emptyList() 104 } 105 106 val config = carrierConfigManager.getConfigForSubId( 107 subId, 108 CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL 109 ) 110 111 val shouldFilter = config.getBoolean( 112 CarrierConfigManager.KEY_REMOVE_SATELLITE_PLMN_IN_MANUAL_NETWORK_SCAN_BOOL, 113 true) 114 115 return if (shouldFilter) { 116 satelliteManager.getSatellitePlmnsForCarrier(subId) 117 } else { 118 emptyList() 119 } 120 } 121 122 private companion object { 123 private const val TAG = "NetworkSelectRepository" 124 } 125 } 126