Merge "Get NetworkRegistrationInfo on background thread" into main
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.network.telephony
|
||||
|
||||
import android.content.Context
|
||||
import android.telephony.AccessNetworkConstants
|
||||
import android.telephony.NetworkRegistrationInfo
|
||||
import android.telephony.TelephonyManager
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class NetworkSelectRepository(context: Context, subId: Int) {
|
||||
private val telephonyManager =
|
||||
context.getSystemService(TelephonyManager::class.java)!!.createForSubscriptionId(subId)
|
||||
|
||||
data class NetworkRegistrationAndForbiddenInfo(
|
||||
val networkList: List<NetworkRegistrationInfo>,
|
||||
val forbiddenPlmns: List<String>,
|
||||
)
|
||||
|
||||
/** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */
|
||||
fun launchUpdateNetworkRegistrationInfo(
|
||||
lifecycleOwner: LifecycleOwner,
|
||||
action: (NetworkRegistrationAndForbiddenInfo) -> Unit,
|
||||
) {
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
withContext(Dispatchers.Default) {
|
||||
getNetworkRegistrationInfo()
|
||||
}?.let(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getNetworkRegistrationInfo(): NetworkRegistrationAndForbiddenInfo? {
|
||||
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(
|
||||
AccessNetworkConstants.TRANSPORT_TYPE_WWAN
|
||||
)
|
||||
if (networkList.isEmpty()) return null
|
||||
// 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.
|
||||
// Add an additional rule to avoid from showing forbidden PLMN to the user.
|
||||
return NetworkRegistrationAndForbiddenInfo(networkList, getForbiddenPlmns())
|
||||
}
|
||||
|
||||
/**
|
||||
* Update forbidden PLMNs from the USIM App
|
||||
*/
|
||||
private fun getForbiddenPlmns(): List<String> {
|
||||
return telephonyManager.forbiddenPlmns?.toList() ?: emptyList()
|
||||
}
|
||||
}
|
@@ -24,12 +24,10 @@ import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.PersistableBundle;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.AccessNetworkConstants;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.CellIdentity;
|
||||
import android.telephony.CellInfo;
|
||||
import android.telephony.NetworkRegistrationInfo;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SignalStrength;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
@@ -52,13 +50,11 @@ import com.android.settings.network.telephony.scan.NetworkScanRepository;
|
||||
import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanCellInfos;
|
||||
import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanComplete;
|
||||
import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanError;
|
||||
import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanResult;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import kotlin.Unit;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -101,6 +97,8 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
private NetworkScanRepository mNetworkScanRepository;
|
||||
private boolean mUpdateScanResult = false;
|
||||
|
||||
private NetworkSelectRepository mNetworkSelectRepository;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
@@ -138,6 +136,7 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
mCarrierConfigManager.registerCarrierConfigChangeListener(mNetworkScanExecutor,
|
||||
mCarrierConfigChangeListener);
|
||||
mNetworkScanRepository = new NetworkScanRepository(context, mSubId);
|
||||
mNetworkSelectRepository = new NetworkSelectRepository(context, mSubId);
|
||||
}
|
||||
|
||||
@Keep
|
||||
@@ -202,14 +201,17 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
mProgressHeader = setPinnedHeaderView(
|
||||
com.android.settingslib.widget.progressbar.R.layout.progress_header
|
||||
).findViewById(com.android.settingslib.widget.progressbar.R.id.progress_bar_animation);
|
||||
forceUpdateConnectedPreferenceCategory();
|
||||
mNetworkSelectRepository.launchUpdateNetworkRegistrationInfo(
|
||||
getViewLifecycleOwner(),
|
||||
(info) -> {
|
||||
forceUpdateConnectedPreferenceCategory(info);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
launchNetworkScan();
|
||||
}
|
||||
|
||||
private void launchNetworkScan() {
|
||||
mNetworkScanRepository.launchNetworkScan(getViewLifecycleOwner(), new Function1<>() {
|
||||
@Override
|
||||
public Unit invoke(@NonNull NetworkScanResult networkScanResult) {
|
||||
mNetworkScanRepository.launchNetworkScan(getViewLifecycleOwner(), (networkScanResult) -> {
|
||||
if (!mUpdateScanResult) {
|
||||
// Not update UI if not in scan mode.
|
||||
return Unit.INSTANCE;
|
||||
@@ -230,7 +232,6 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
}
|
||||
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -238,7 +239,6 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
updateForbiddenPlmns();
|
||||
setProgressBarVisible(true);
|
||||
mUpdateScanResult = true;
|
||||
}
|
||||
@@ -477,33 +477,15 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
* - If the device has no data, we will remove the connected network operators list from the
|
||||
* screen.
|
||||
*/
|
||||
private void forceUpdateConnectedPreferenceCategory() {
|
||||
if (mTelephonyManager.getDataState() == mTelephonyManager.DATA_CONNECTED) {
|
||||
// Try to get the network registration states
|
||||
final ServiceState ss = mTelephonyManager.getServiceState();
|
||||
if (ss == null) {
|
||||
return;
|
||||
}
|
||||
final List<NetworkRegistrationInfo> networkList =
|
||||
ss.getNetworkRegistrationInfoListForTransportType(
|
||||
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
|
||||
if (networkList == null || networkList.size() == 0) {
|
||||
return;
|
||||
}
|
||||
// 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.
|
||||
// Add an additional rule to avoid from showing forbidden PLMN to the user.
|
||||
if (mForbiddenPlmns == null) {
|
||||
updateForbiddenPlmns();
|
||||
}
|
||||
for (NetworkRegistrationInfo regInfo : networkList) {
|
||||
private void forceUpdateConnectedPreferenceCategory(
|
||||
NetworkSelectRepository.NetworkRegistrationAndForbiddenInfo info) {
|
||||
for (NetworkRegistrationInfo regInfo : info.getNetworkList()) {
|
||||
final CellIdentity cellIdentity = regInfo.getCellIdentity();
|
||||
if (cellIdentity == null) {
|
||||
continue;
|
||||
}
|
||||
final NetworkOperatorPreference pref = new NetworkOperatorPreference(
|
||||
getPrefContext(), mForbiddenPlmns, mShow4GForLTE);
|
||||
getPrefContext(), info.getForbiddenPlmns(), mShow4GForLTE);
|
||||
pref.updateCell(null, cellIdentity);
|
||||
if (pref.isForbiddenNetwork()) {
|
||||
continue;
|
||||
@@ -517,7 +499,6 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all of the preference summary
|
||||
|
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
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 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.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.spy
|
||||
import org.mockito.kotlin.stub
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class NetworkSelectRepositoryTest {
|
||||
|
||||
private val mockServiceState = mock<ServiceState> {
|
||||
on {
|
||||
getNetworkRegistrationInfoListForTransportType(
|
||||
AccessNetworkConstants.TRANSPORT_TYPE_WWAN
|
||||
)
|
||||
} doReturn NetworkRegistrationInfos
|
||||
}
|
||||
|
||||
private val mockTelephonyManager = mock<TelephonyManager> {
|
||||
on { createForSubscriptionId(SUB_ID) } doReturn mock
|
||||
on { dataState } doReturn TelephonyManager.DATA_CONNECTED
|
||||
on { serviceState } doReturn mockServiceState
|
||||
}
|
||||
|
||||
private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
|
||||
on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
|
||||
}
|
||||
|
||||
private val repository = NetworkSelectRepository(context, SUB_ID)
|
||||
|
||||
@Test
|
||||
fun getNetworkRegistrationInfo_notConnected_returnNull() {
|
||||
mockTelephonyManager.stub {
|
||||
on { dataState } doReturn TelephonyManager.DATA_DISCONNECTED
|
||||
}
|
||||
|
||||
val info = repository.getNetworkRegistrationInfo()
|
||||
|
||||
assertThat(info).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getNetworkRegistrationInfo_nullServiceState_returnNull() {
|
||||
mockTelephonyManager.stub {
|
||||
on { serviceState } doReturn null
|
||||
}
|
||||
|
||||
val info = repository.getNetworkRegistrationInfo()
|
||||
|
||||
assertThat(info).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getNetworkRegistrationInfo_emptyNetworkList_returnNull() {
|
||||
mockServiceState.stub {
|
||||
on {
|
||||
getNetworkRegistrationInfoListForTransportType(
|
||||
AccessNetworkConstants.TRANSPORT_TYPE_WWAN
|
||||
)
|
||||
} doReturn emptyList()
|
||||
}
|
||||
|
||||
val info = repository.getNetworkRegistrationInfo()
|
||||
|
||||
assertThat(info).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getNetworkRegistrationInfo_hasNetworkList_returnInfo() {
|
||||
mockServiceState.stub {
|
||||
on {
|
||||
getNetworkRegistrationInfoListForTransportType(
|
||||
AccessNetworkConstants.TRANSPORT_TYPE_WWAN
|
||||
)
|
||||
} doReturn NetworkRegistrationInfos
|
||||
}
|
||||
mockTelephonyManager.stub {
|
||||
on { forbiddenPlmns } doReturn arrayOf(FORBIDDEN_PLMN)
|
||||
}
|
||||
|
||||
val info = repository.getNetworkRegistrationInfo()
|
||||
|
||||
assertThat(info).isEqualTo(
|
||||
NetworkSelectRepository.NetworkRegistrationAndForbiddenInfo(
|
||||
networkList = NetworkRegistrationInfos,
|
||||
forbiddenPlmns = listOf(FORBIDDEN_PLMN),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val SUB_ID = 1
|
||||
val NetworkRegistrationInfos = listOf(NetworkRegistrationInfo.Builder().build())
|
||||
const val FORBIDDEN_PLMN = "Forbidden PLMN"
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user