From 1b3a315d06318440e70b78ad58eeb30fdd667faa Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Fri, 30 Aug 2024 15:47:14 +0800 Subject: [PATCH] New isSubscriptionVisibleFlow Use this instead of mSubscriptionInfoEntity, so MobileNetworkSettings not closed unexpectedly. Bug: 358238959 Flag: EXEMPT bug fix Test: force stop settings & settings search - mobile settings Test: adb shell am start -a android.settings.NETWORK_OPERATOR_SETTINGS Change-Id: I34286da808600d8b9faa0da85a59665707ecfde3 --- .../telephony/MobileNetworkSettings.java | 18 +++++++++---- .../telephony/SubscriptionRepository.kt | 25 ++++++++++++++++++ .../telephony/SubscriptionRepositoryTest.kt | 26 +++++++++++++++++++ 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java index a5cdb954664..91874c4f5ac 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java +++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java @@ -41,6 +41,7 @@ import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.ViewModelProvider; import androidx.preference.Preference; @@ -66,6 +67,8 @@ import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.utils.ThreadUtils; +import kotlin.Unit; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -359,6 +362,16 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); collectAirplaneModeAndFinishIfOn(this); + + LifecycleOwner viewLifecycleOwner = getViewLifecycleOwner(); + new SubscriptionRepository(requireContext()) + .collectSubscriptionVisible(mSubId, viewLifecycleOwner, (isVisible) -> { + if (!isVisible) { + Log.d(LOG_TAG, "Due to subscription not visible, closes page"); + finishFragment(); + } + return Unit.INSTANCE; + }); } @Override @@ -532,11 +545,6 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme Log.d(LOG_TAG, "Set subInfo to default subInfo."); } } - if (mSubscriptionInfoEntity == null && getActivity() != null) { - // If the current subId is not existed, finish it. - finishFragment(); - return; - } onSubscriptionDetailChanged(); } } diff --git a/src/com/android/settings/network/telephony/SubscriptionRepository.kt b/src/com/android/settings/network/telephony/SubscriptionRepository.kt index cc8c8b47b2d..26ea9b3fc42 100644 --- a/src/com/android/settings/network/telephony/SubscriptionRepository.kt +++ b/src/com/android/settings/network/telephony/SubscriptionRepository.kt @@ -50,6 +50,31 @@ class SubscriptionRepository(private val context: Context) { fun getSelectableSubscriptionInfoList(): List = context.getSelectableSubscriptionInfoList() + /** Flow of whether the subscription visible for the given [subId]. */ + fun isSubscriptionVisibleFlow(subId: Int): Flow { + return subscriptionsChangedFlow() + .map { + val subInfo = + subscriptionManager.availableSubscriptionInfoList?.firstOrNull { subInfo -> + subInfo.subscriptionId == subId + } + subInfo != null && + SubscriptionUtil.isSubscriptionVisible(subscriptionManager, context, subInfo) + } + .conflate() + .onEach { Log.d(TAG, "[$subId] isSubscriptionVisibleFlow: $it") } + .flowOn(Dispatchers.Default) + } + + /** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */ + fun collectSubscriptionVisible( + subId: Int, + lifecycleOwner: LifecycleOwner, + action: (Boolean) -> Unit, + ) { + isSubscriptionVisibleFlow(subId).collectLatestWithLifecycle(lifecycleOwner, action = action) + } + /** Flow of whether the subscription enabled for the given [subId]. */ fun isSubscriptionEnabledFlow(subId: Int): Flow { if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false) diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt index f75c14a6d37..5dbc5340745 100644 --- a/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt +++ b/tests/spa_unit/src/com/android/settings/network/telephony/SubscriptionRepositoryTest.kt @@ -189,6 +189,32 @@ class SubscriptionRepositoryTest { assertThat(subInfos.map { it.subscriptionId }).containsExactly(SUB_ID_3_NOT_IN_SLOT) } + @Test + fun isSubscriptionVisibleFlow_available_returnTrue() = runBlocking { + mockSubscriptionManager.stub { + on { getAvailableSubscriptionInfoList() } doReturn + listOf(SubscriptionInfo.Builder().apply { setId(SUB_ID_IN_SLOT_0) }.build()) + } + + val isVisible = + repository.isSubscriptionVisibleFlow(SUB_ID_IN_SLOT_0).firstWithTimeoutOrNull() + + assertThat(isVisible).isTrue() + } + + @Test + fun isSubscriptionVisibleFlow_unavailable_returnFalse() = runBlocking { + mockSubscriptionManager.stub { + on { getAvailableSubscriptionInfoList() } doReturn + listOf(SubscriptionInfo.Builder().apply { setId(SUB_ID_IN_SLOT_0) }.build()) + } + + val isVisible = + repository.isSubscriptionVisibleFlow(SUB_ID_IN_SLOT_1).firstWithTimeoutOrNull() + + assertThat(isVisible).isFalse() + } + @Test fun phoneNumberFlow() = runBlocking { mockSubscriptionManager.stub {