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
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index a5cdb95..91874c4 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -41,6 +41,7 @@
 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.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 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 @@
                 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 cc8c8b4..26ea9b3 100644
--- a/src/com/android/settings/network/telephony/SubscriptionRepository.kt
+++ b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
@@ -50,6 +50,31 @@
     fun getSelectableSubscriptionInfoList(): List<SubscriptionInfo> =
         context.getSelectableSubscriptionInfoList()
 
+    /** Flow of whether the subscription visible for the given [subId]. */
+    fun isSubscriptionVisibleFlow(subId: Int): Flow<Boolean> {
+        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<Boolean> {
         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 f75c14a..5dbc534 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
@@ -190,6 +190,32 @@
     }
 
     @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 {
             on { getPhoneNumber(SUB_ID_IN_SLOT_1) } doReturn NUMBER_1