diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml
index 62a88b75646..038688e390c 100644
--- a/res/xml/mobile_network_settings.xml
+++ b/res/xml/mobile_network_settings.xml
@@ -210,7 +210,7 @@
android:title="@string/network_operator_category"
settings:controller="com.android.settings.network.telephony.NetworkPreferenceCategoryController">
-
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index dbe8ae86817..0812ccc83cd 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -276,7 +276,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
use(OpenNetworkSelectPagePreferenceController.class).init(mSubId);
final AutoSelectPreferenceController autoSelectPreferenceController =
use(AutoSelectPreferenceController.class)
- .init(getLifecycle(), mSubId)
+ .init(mSubId)
.addListener(openNetworkSelectPagePreferenceController);
use(NetworkPreferenceCategoryController.class).init(mSubId)
.setChildren(Arrays.asList(autoSelectPreferenceController));
diff --git a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java
deleted file mode 100644
index 36e2aa8e935..00000000000
--- a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright (C) 2018 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.gsm;
-
-import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
-
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.HandlerExecutor;
-import android.os.Looper;
-import android.os.PersistableBundle;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.telephony.CarrierConfigManager;
-import android.telephony.ServiceState;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleEventObserver;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.TwoStatePreference;
-
-import com.android.settings.R;
-import com.android.settings.network.AllowedNetworkTypesListener;
-import com.android.settings.network.CarrierConfigCache;
-import com.android.settings.network.helper.ServiceStateStatus;
-import com.android.settings.network.telephony.MobileNetworkUtils;
-import com.android.settings.network.telephony.TelephonyTogglePreferenceController;
-import com.android.settingslib.utils.ThreadUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Preference controller for "Auto Select Network"
- */
-public class AutoSelectPreferenceController extends TelephonyTogglePreferenceController
- implements LifecycleEventObserver{
- private static final long MINIMUM_DIALOG_TIME_MILLIS = TimeUnit.SECONDS.toMillis(1);
- private static final String LOG_TAG = "AutoSelectPreferenceController";
- private static final String INTERNAL_LOG_TAG_ONRESUME = "OnResume";
- private static final String INTERNAL_LOG_TAG_AFTERSET = "AfterSet";
-
- private final Handler mUiHandler;
- private PreferenceScreen mPreferenceScreen;
- private AllowedNetworkTypesListener mAllowedNetworkTypesListener;
- private TelephonyManager mTelephonyManager;
- private boolean mOnlyAutoSelectInHome;
- private List mListeners;
- @VisibleForTesting
- ProgressDialog mProgressDialog;
- @VisibleForTesting
- TwoStatePreference mSwitchPreference;
- private AtomicBoolean mUpdatingConfig;
- private int mCacheOfModeStatus;
- private AtomicLong mRecursiveUpdate;
- ServiceStateStatus mServiceStateStatus;
-
- public AutoSelectPreferenceController(Context context, String key) {
- super(context, key);
- mTelephonyManager = context.getSystemService(TelephonyManager.class);
- mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- mRecursiveUpdate = new AtomicLong();
- mUpdatingConfig = new AtomicBoolean();
- mCacheOfModeStatus = TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
- mListeners = new ArrayList<>();
- mUiHandler = new Handler(Looper.getMainLooper());
- mAllowedNetworkTypesListener = new AllowedNetworkTypesListener(
- new HandlerExecutor(mUiHandler));
- mAllowedNetworkTypesListener.setAllowedNetworkTypesListener(
- () -> updatePreference());
- }
-
- private void updatePreference() {
- if (mPreferenceScreen != null) {
- displayPreference(mPreferenceScreen);
- }
- if (mSwitchPreference != null) {
- mRecursiveUpdate.getAndIncrement();
- updateState(mSwitchPreference);
- mRecursiveUpdate.decrementAndGet();
- }
- }
-
- /**
- * Implementation of LifecycleEventObserver.
- */
- @SuppressWarnings("FutureReturnValueIgnored")
- public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner,
- @NonNull Lifecycle.Event event) {
- switch (event) {
- case ON_START:
- mAllowedNetworkTypesListener.register(mContext, mSubId);
- break;
- case ON_RESUME:
- ThreadUtils.postOnBackgroundThread(() -> {
- queryNetworkSelectionMode(INTERNAL_LOG_TAG_ONRESUME);
- //Update UI in UI thread
- mUiHandler.post(() -> {
- if (mSwitchPreference != null) {
- mRecursiveUpdate.getAndIncrement();
- mSwitchPreference.setChecked(isChecked());
- mRecursiveUpdate.decrementAndGet();
- updateListenerValue();
- }
- });
- });
- break;
- case ON_STOP:
- mAllowedNetworkTypesListener.unregister(mContext, mSubId);
- break;
- default:
- // Do nothing
- break;
- }
- }
-
- @Override
- public int getAvailabilityStatus(int subId) {
- return MobileNetworkUtils.shouldDisplayNetworkSelectOptions(mContext, subId)
- ? AVAILABLE
- : CONDITIONALLY_UNAVAILABLE;
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mPreferenceScreen = screen;
- mSwitchPreference = screen.findPreference(getPreferenceKey());
- }
-
- @Override
- public boolean isChecked() {
- return mCacheOfModeStatus == TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
- }
-
- @Override
- public void updateState(Preference preference) {
- super.updateState(preference);
-
- preference.setSummary(null);
- final ServiceState serviceState = mTelephonyManager.getServiceState();
- if (serviceState == null) {
- preference.setEnabled(false);
- return;
- }
-
- if (serviceState.getRoaming()) {
- preference.setEnabled(true);
- } else {
- preference.setEnabled(!mOnlyAutoSelectInHome);
- if (mOnlyAutoSelectInHome) {
- preference.setSummary(mContext.getString(
- R.string.manual_mode_disallowed_summary,
- mTelephonyManager.getSimOperatorName()));
- }
- }
- }
-
- @Override
- public boolean setChecked(boolean isChecked) {
- if (mRecursiveUpdate.get() != 0) {
- // Changing from software are allowed and changing presentation only.
- return true;
- }
- if (isChecked) {
- setAutomaticSelectionMode();
- } else {
- if (mSwitchPreference != null) {
- Intent intent = new Intent();
- intent.setClassName(SETTINGS_PACKAGE_NAME,
- SETTINGS_PACKAGE_NAME + ".Settings$NetworkSelectActivity");
- intent.putExtra(Settings.EXTRA_SUB_ID, mSubId);
- mSwitchPreference.setIntent(intent);
- }
- }
- return false;
- }
-
- @VisibleForTesting
- Future setAutomaticSelectionMode() {
- final long startMillis = SystemClock.elapsedRealtime();
- showAutoSelectProgressBar();
- if (mSwitchPreference != null) {
- mSwitchPreference.setIntent(null);
- mSwitchPreference.setEnabled(false);
- }
- return ThreadUtils.postOnBackgroundThread(() -> {
- // set network selection mode in background
- mUpdatingConfig.set(true);
- mTelephonyManager.setNetworkSelectionModeAutomatic();
- mUpdatingConfig.set(false);
-
- //Update UI in UI thread
- final long durationMillis = SystemClock.elapsedRealtime() - startMillis;
-
- mUiHandler.postDelayed(() -> {
- ThreadUtils.postOnBackgroundThread(() -> {
- queryNetworkSelectionMode(INTERNAL_LOG_TAG_AFTERSET);
-
- //Update UI in UI thread
- mUiHandler.post(() -> {
- mRecursiveUpdate.getAndIncrement();
- if (mSwitchPreference != null) {
- mSwitchPreference.setEnabled(true);
- mSwitchPreference.setChecked(isChecked());
- }
- mRecursiveUpdate.decrementAndGet();
- updateListenerValue();
- dismissProgressBar();
- });
- });
- }, Math.max(MINIMUM_DIALOG_TIME_MILLIS - durationMillis, 0));
- });
- }
-
- /**
- * Initialization based on given subscription id.
- **/
- public AutoSelectPreferenceController init(Lifecycle lifecycle, int subId) {
- mSubId = subId;
- mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
- .createForSubscriptionId(mSubId);
- final PersistableBundle carrierConfig =
- CarrierConfigCache.getInstance(mContext).getConfigForSubId(mSubId);
- mOnlyAutoSelectInHome = carrierConfig != null
- ? carrierConfig.getBoolean(
- CarrierConfigManager.KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL)
- : false;
-
- mServiceStateStatus = new ServiceStateStatus(lifecycle, mTelephonyManager,
- new HandlerExecutor(mUiHandler)) {
- @Override
- protected void setValue(ServiceState status) {
- if (status == null) {
- return;
- }
- updateUiAutoSelectValue(status);
- }
- };
- return this;
- }
-
- public AutoSelectPreferenceController addListener(OnNetworkSelectModeListener lsn) {
- mListeners.add(lsn);
-
- return this;
- }
-
- private void queryNetworkSelectionMode(String tag) {
- mCacheOfModeStatus = mTelephonyManager.getNetworkSelectionMode();
- Log.d(LOG_TAG, tag + ": query command done. mCacheOfModeStatus: " + mCacheOfModeStatus);
- }
-
- @VisibleForTesting
- void updateUiAutoSelectValue(ServiceState status) {
- if (status == null) {
- return;
- }
- if (!mUpdatingConfig.get()) {
- int networkSelectionMode = status.getIsManualSelection()
- ? TelephonyManager.NETWORK_SELECTION_MODE_MANUAL
- : TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
- if (mCacheOfModeStatus == networkSelectionMode) {
- return;
- }
- mCacheOfModeStatus = networkSelectionMode;
- Log.d(LOG_TAG, "updateUiAutoSelectValue: mCacheOfModeStatus: " + mCacheOfModeStatus);
-
- mRecursiveUpdate.getAndIncrement();
- updateState(mSwitchPreference);
- mRecursiveUpdate.decrementAndGet();
- updateListenerValue();
- }
- }
-
- private void updateListenerValue() {
- for (OnNetworkSelectModeListener lsn : mListeners) {
- lsn.onNetworkSelectModeUpdated(mCacheOfModeStatus);
- }
- }
-
- private void showAutoSelectProgressBar() {
- if (mProgressDialog == null) {
- mProgressDialog = new ProgressDialog(mContext);
- mProgressDialog.setMessage(
- mContext.getResources().getString(R.string.register_automatically));
- mProgressDialog.setCanceledOnTouchOutside(false);
- mProgressDialog.setCancelable(false);
- mProgressDialog.setIndeterminate(true);
- }
- mProgressDialog.show();
- }
-
- private void dismissProgressBar() {
- if (mProgressDialog != null && mProgressDialog.isShowing()) {
- try {
- mProgressDialog.dismiss();
- } catch (IllegalArgumentException e) {
- // Ignore exception since the dialog will be gone anyway.
- }
- }
- }
-
- /**
- * Callback when network select mode might get updated
- *
- * @see TelephonyManager#getNetworkSelectionMode()
- */
- public interface OnNetworkSelectModeListener {
- void onNetworkSelectModeUpdated(int mode);
- }
-}
diff --git a/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt
new file mode 100644
index 00000000000..1ed9d9aceda
--- /dev/null
+++ b/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.kt
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2023 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.gsm
+
+import android.app.ProgressDialog
+import android.content.Context
+import android.content.Intent
+import android.os.PersistableBundle
+import android.provider.Settings
+import android.telephony.CarrierConfigManager
+import android.telephony.ServiceState
+import android.telephony.TelephonyManager
+import androidx.annotation.VisibleForTesting
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import androidx.preference.Preference
+import androidx.preference.PreferenceScreen
+import com.android.settings.R
+import com.android.settings.Settings.NetworkSelectActivity
+import com.android.settings.network.CarrierConfigCache
+import com.android.settings.network.telephony.MobileNetworkUtils
+import com.android.settings.network.telephony.allowedNetworkTypesFlow
+import com.android.settings.network.telephony.serviceStateFlow
+import com.android.settings.spa.preference.ComposePreferenceController
+import com.android.settingslib.spa.framework.compose.OverridableFlow
+import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
+import com.android.settingslib.spa.widget.preference.SwitchPreference
+import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
+import kotlin.properties.Delegates.notNull
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ * Preference controller for "Auto Select Network"
+ */
+class AutoSelectPreferenceController @JvmOverloads constructor(
+ context: Context,
+ key: String,
+ private val allowedNetworkTypesFlowFactory: (subId: Int) -> Flow =
+ context::allowedNetworkTypesFlow,
+ private val serviceStateFlowFactory: (subId: Int) -> Flow =
+ context::serviceStateFlow,
+ private val getConfigForSubId: (subId: Int) -> PersistableBundle = { subId ->
+ CarrierConfigCache.getInstance(context).getConfigForSubId(subId)
+ },
+) : ComposePreferenceController(context, key) {
+
+ private lateinit var telephonyManager: TelephonyManager
+ private val listeners = mutableListOf()
+
+ @VisibleForTesting
+ var progressDialog: ProgressDialog? = null
+
+ private lateinit var preference: Preference
+
+ private var subId by notNull()
+
+ /**
+ * Initialization based on given subscription id.
+ */
+ fun init(subId: Int): AutoSelectPreferenceController {
+ this.subId = subId
+ telephonyManager = mContext.getSystemService(TelephonyManager::class.java)!!
+ .createForSubscriptionId(subId)
+
+ return this
+ }
+
+ override fun getAvailabilityStatus() =
+ if (MobileNetworkUtils.shouldDisplayNetworkSelectOptions(mContext, subId)) AVAILABLE
+ else CONDITIONALLY_UNAVAILABLE
+
+ override fun displayPreference(screen: PreferenceScreen) {
+ super.displayPreference(screen)
+ preference = screen.findPreference(preferenceKey)!!
+ }
+
+ @Composable
+ override fun Content() {
+ val coroutineScope = rememberCoroutineScope()
+ val serviceStateFlow = remember {
+ serviceStateFlowFactory(subId)
+ .stateIn(coroutineScope, SharingStarted.Lazily, null)
+ .filterNotNull()
+ }
+ val isAutoOverridableFlow = remember {
+ OverridableFlow(serviceStateFlow.map { !it.isManualSelection })
+ }
+ val isAuto by isAutoOverridableFlow.flow
+ .onEach(::updateListenerValue)
+ .collectAsStateWithLifecycle(initialValue = null)
+ val disallowedSummary by serviceStateFlow.map(::getDisallowedSummary)
+ .collectAsStateWithLifecycle(initialValue = "")
+ SwitchPreference(object : SwitchPreferenceModel {
+ override val title = stringResource(R.string.select_automatically)
+ override val summary = { disallowedSummary }
+ override val changeable = { disallowedSummary.isEmpty() }
+ override val checked = { isAuto }
+ override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
+ if (newChecked) {
+ coroutineScope.launch { setAutomaticSelectionMode(isAutoOverridableFlow) }
+ } else {
+ mContext.startActivity(Intent().apply {
+ setClass(mContext, NetworkSelectActivity::class.java)
+ putExtra(Settings.EXTRA_SUB_ID, subId)
+ })
+ }
+ }
+ })
+ }
+
+ private suspend fun getDisallowedSummary(serviceState: ServiceState): String =
+ withContext(Dispatchers.Default) {
+ if (!serviceState.roaming && onlyAutoSelectInHome()) {
+ mContext.getString(
+ R.string.manual_mode_disallowed_summary,
+ telephonyManager.simOperatorName
+ )
+ } else ""
+ }
+
+ private fun onlyAutoSelectInHome(): Boolean =
+ getConfigForSubId(subId)
+ .getBoolean(CarrierConfigManager.KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL)
+
+ private suspend fun setAutomaticSelectionMode(overrideChannel: OverridableFlow) {
+ showAutoSelectProgressBar()
+
+ withContext(Dispatchers.Default) {
+ val minimumDialogTimeDeferred = async { delay(MINIMUM_DIALOG_TIME) }
+ telephonyManager.setNetworkSelectionModeAutomatic()
+ minimumDialogTimeDeferred.await()
+ }
+ overrideChannel.override(true)
+
+ dismissProgressBar()
+ }
+
+ override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+ allowedNetworkTypesFlowFactory(subId).collectLatestWithLifecycle(viewLifecycleOwner) {
+ preference.isVisible = withContext(Dispatchers.Default) {
+ MobileNetworkUtils.shouldDisplayNetworkSelectOptions(mContext, subId)
+ }
+ }
+ }
+
+ fun addListener(listener: OnNetworkSelectModeListener): AutoSelectPreferenceController {
+ listeners.add(listener)
+ return this
+ }
+
+ private fun updateListenerValue(isAuto: Boolean) {
+ for (listener in listeners) {
+ listener.onNetworkSelectModeUpdated(
+ if (isAuto) TelephonyManager.NETWORK_SELECTION_MODE_AUTO
+ else TelephonyManager.NETWORK_SELECTION_MODE_MANUAL
+ )
+ }
+ }
+
+ private fun showAutoSelectProgressBar() {
+ if (progressDialog == null) {
+ progressDialog = ProgressDialog(mContext).apply {
+ setMessage(mContext.resources.getString(R.string.register_automatically))
+ setCanceledOnTouchOutside(false)
+ setCancelable(false)
+ isIndeterminate = true
+ }
+ }
+ progressDialog?.show()
+ }
+
+ private fun dismissProgressBar() {
+ if (progressDialog?.isShowing == true) {
+ try {
+ progressDialog?.dismiss()
+ } catch (e: IllegalArgumentException) {
+ // Ignore exception since the dialog will be gone anyway.
+ }
+ }
+ }
+
+ /**
+ * Callback when network select mode might get updated
+ *
+ * @see TelephonyManager.getNetworkSelectionMode
+ */
+ interface OnNetworkSelectModeListener {
+ fun onNetworkSelectModeUpdated(mode: Int)
+ }
+
+ companion object {
+ private val MINIMUM_DIALOG_TIME = 1.seconds
+ }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.kt
new file mode 100644
index 00000000000..f821e1a76fd
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.kt
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2023 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.gsm
+
+import android.content.Context
+import android.content.Intent
+import android.provider.Settings
+import android.telephony.CarrierConfigManager
+import android.telephony.ServiceState
+import android.telephony.TelephonyManager
+import androidx.compose.ui.test.assertIsEnabled
+import androidx.compose.ui.test.assertIsNotEnabled
+import androidx.compose.ui.test.assertIsOff
+import androidx.compose.ui.test.assertIsOn
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.onRoot
+import androidx.compose.ui.test.performClick
+import androidx.core.os.persistableBundleOf
+import androidx.preference.PreferenceManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
+import com.android.settings.Settings.NetworkSelectActivity
+import com.android.settings.spa.preference.ComposePreference
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.doNothing
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@RunWith(AndroidJUnit4::class)
+class AutoSelectPreferenceControllerTest {
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ private val mockTelephonyManager = mock {
+ on { createForSubscriptionId(SUB_ID) } doReturn mock
+ on { simOperatorName } doReturn OPERATOR_NAME
+ }
+
+ private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+ on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
+ doNothing().whenever(mock).startActivity(any())
+ }
+
+ private val preference = ComposePreference(context).apply { key = TEST_KEY }
+ private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
+
+ private val serviceState = ServiceState()
+
+ private val carrierConfig = persistableBundleOf()
+
+ private val controller = AutoSelectPreferenceController(
+ context = context,
+ key = TEST_KEY,
+ allowedNetworkTypesFlowFactory = { emptyFlow() },
+ serviceStateFlowFactory = { flowOf(serviceState) },
+ getConfigForSubId = { carrierConfig },
+ ).init(subId = SUB_ID)
+
+ @Before
+ fun setUp() {
+ preferenceScreen.addPreference(preference)
+ controller.displayPreference(preferenceScreen)
+ }
+
+ @Test
+ fun isChecked_isAutoSelection_on() {
+ serviceState.isManualSelection = false
+
+ composeTestRule.setContent {
+ controller.Content()
+ }
+
+ composeTestRule.onNodeWithText(context.getString(R.string.select_automatically))
+ .assertIsOn()
+ }
+
+ @Test
+ fun isChecked_isManualSelection_off() {
+ serviceState.isManualSelection = true
+
+ composeTestRule.setContent {
+ controller.Content()
+ }
+
+ composeTestRule.onNodeWithText(context.getString(R.string.select_automatically))
+ .assertIsOff()
+ }
+
+
+ @Test
+ fun isEnabled_isRoaming_enabled() {
+ serviceState.roaming = true
+
+ composeTestRule.setContent {
+ controller.Content()
+ }
+
+ composeTestRule.onNodeWithText(context.getString(R.string.select_automatically))
+ .assertIsEnabled()
+ }
+
+ @Test
+ fun isEnabled_notOnlyAutoSelectInHome_enabled() {
+ serviceState.roaming = false
+ carrierConfig.putBoolean(
+ CarrierConfigManager.KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL, false
+ )
+
+ composeTestRule.setContent {
+ controller.Content()
+ }
+
+ composeTestRule.onNodeWithText(context.getString(R.string.select_automatically))
+ .assertIsEnabled()
+ }
+
+ @Test
+ fun isEnabled_onlyAutoSelectInHome_notEnabled() {
+ serviceState.roaming = false
+ carrierConfig.putBoolean(
+ CarrierConfigManager.KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL, true
+ )
+
+ composeTestRule.setContent {
+ controller.Content()
+ }
+
+ composeTestRule.onNodeWithText("Unavailable when connected to T-mobile")
+ .assertIsNotEnabled()
+ }
+
+ @Test
+ fun onClick_turnOff_startNetworkSelectActivity() {
+ serviceState.isManualSelection = false
+
+ composeTestRule.setContent {
+ controller.Content()
+ }
+ composeTestRule.onRoot().performClick()
+
+ val intent = argumentCaptor {
+ verify(context).startActivity(capture())
+ }.firstValue
+ assertThat(intent.component!!.className).isEqualTo(NetworkSelectActivity::class.java.name)
+ assertThat(intent.getIntExtra(Settings.EXTRA_SUB_ID, 0)).isEqualTo(SUB_ID)
+ }
+
+ @Test
+ fun onClick_turnOn_setNetworkSelectionModeAutomatic() = runBlocking {
+ serviceState.isManualSelection = true
+ controller.progressDialog = mock()
+
+ composeTestRule.setContent {
+ controller.Content()
+ }
+ composeTestRule.onRoot().performClick()
+ delay(100)
+
+ verify(controller.progressDialog!!).show()
+ verify(mockTelephonyManager).setNetworkSelectionModeAutomatic()
+ }
+
+ private companion object {
+ const val TEST_KEY = "test_key"
+ const val SUB_ID = 2
+ const val OPERATOR_NAME = "T-mobile"
+ }
+}
diff --git a/tests/unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java
deleted file mode 100644
index 39f2050b7f7..00000000000
--- a/tests/unit/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceControllerTest.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2020 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.gsm;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.os.PersistableBundle;
-import android.telephony.CarrierConfigManager;
-import android.telephony.ServiceState;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-
-import androidx.lifecycle.Lifecycle;
-import androidx.preference.SwitchPreference;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.network.CarrierConfigCache;
-import com.android.settings.testutils.ResourcesUtils;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-
-@RunWith(AndroidJUnit4.class)
-public class AutoSelectPreferenceControllerTest {
- private static final int SUB_ID = 2;
- private static final String OPERATOR_NAME = "T-mobile";
-
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private TelephonyManager mTelephonyManager;
- @Mock
- private SubscriptionManager mSubscriptionManager;
- @Mock
- private CarrierConfigCache mCarrierConfigCache;
- @Mock
- private ProgressDialog mProgressDialog;
- @Mock
- private ServiceState mTestServiceState;
- @Mock
- private Lifecycle mLifecycle;
-
- private PersistableBundle mCarrierConfig;
- private AutoSelectPreferenceController mController;
- private SwitchPreference mSwitchPreference;
- private Context mContext;
-
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- mContext = spy(ApplicationProvider.getApplicationContext());
-
- when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
- when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
- CarrierConfigCache.setTestInstance(mContext, mCarrierConfigCache);
- when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager);
-
- mCarrierConfig = new PersistableBundle();
- mCarrierConfig.putBoolean(CarrierConfigManager.KEY_ONLY_AUTO_SELECT_IN_HOME_NETWORK_BOOL,
- true);
- when(mCarrierConfigCache.getConfigForSubId(SUB_ID)).thenReturn(mCarrierConfig);
-
- mSwitchPreference = new SwitchPreference(mContext);
- mController = new AutoSelectPreferenceController(mContext, "auto_select");
- mController.mProgressDialog = mProgressDialog;
- mController.mSwitchPreference = mSwitchPreference;
- mController.init(mLifecycle, SUB_ID);
- sleepAfterInit();
- }
-
- private void sleepAfterInit() {
- try {
- Thread.sleep(2000);
- } catch (Exception e) {
- fail("Sleep timeout " + e);
- }
- }
-
- @Test
- public void setChecked_isChecked_showProgressDialog() {
- when(mTelephonyManager.getNetworkSelectionMode()).thenReturn(
- TelephonyManager.NETWORK_SELECTION_MODE_AUTO);
-
- // Wait for asynchronous thread to finish, otherwise test will flake.
- Future thread = mController.setAutomaticSelectionMode();
- try {
- thread.get();
- } catch (ExecutionException | InterruptedException e) {
- e.printStackTrace();
- fail("Exception during automatic selection");
- }
-
- verify(mProgressDialog).show();
- verify(mTelephonyManager).setNetworkSelectionModeAutomatic();
- }
-
- @Test
- public void updateState_isRoaming_enabled() {
- when(mTelephonyManager.getServiceState()).thenReturn(mTestServiceState);
- when(mTestServiceState.getRoaming()).thenReturn(true);
-
- mController.updateState(mSwitchPreference);
-
- assertThat(mSwitchPreference.isEnabled()).isTrue();
- }
-
- @Test
- public void updateState_notRoamingWithAutoSelectOn_disabled() {
- when(mTelephonyManager.getServiceState()).thenReturn(mTestServiceState);
- when(mTestServiceState.getRoaming()).thenReturn(false);
- doReturn(OPERATOR_NAME).when(mTelephonyManager).getSimOperatorName();
-
- mController.updateState(mSwitchPreference);
-
- assertThat(mSwitchPreference.isEnabled()).isFalse();
- assertThat(mSwitchPreference.getSummary()).isEqualTo(
- ResourcesUtils.getResourcesString(mContext, "manual_mode_disallowed_summary",
- mTelephonyManager.getSimOperatorName()));
- }
-
- @Test
- public void init_carrierConfigNull_shouldNotCrash() {
- when(mCarrierConfigCache.getConfigForSubId(SUB_ID)).thenReturn(null);
-
- // Should not crash
- mController.init(mLifecycle, SUB_ID);
- }
-
- @Test
- public void updateUiAutoSelectValue_serviceStateGetIsManualSelection_isCheckedFalse() {
- when(mTelephonyManager.getNetworkSelectionMode()).thenReturn(
- TelephonyManager.NETWORK_SELECTION_MODE_AUTO);
- when(mTestServiceState.getIsManualSelection()).thenReturn(true);
- mController.init(mLifecycle, SUB_ID);
- sleepAfterInit();
-
- mController.updateUiAutoSelectValue(mTestServiceState);
-
- assertThat(mController.isChecked()).isFalse();
- assertThat(mSwitchPreference.isChecked()).isFalse();
- }
-
- @Test
- public void updateUiAutoSelectValue_serviceStateGetIsAutoSelection_isCheckedTrue() {
- when(mTelephonyManager.getNetworkSelectionMode()).thenReturn(
- TelephonyManager.NETWORK_SELECTION_MODE_MANUAL);
- when(mTestServiceState.getIsManualSelection()).thenReturn(false);
- mController.init(mLifecycle, SUB_ID);
- sleepAfterInit();
-
- mController.updateUiAutoSelectValue(mTestServiceState);
-
- assertThat(mController.isChecked()).isTrue();
- assertThat(mSwitchPreference.isChecked()).isTrue();
- }
-}