Add condition whether esim is visible or not

Bug: 314736037
Test: SubscriptionInfoListViewModelTest pass and build pass
Change-Id: I7dc86ca93691f044d951122c0c669c790b7aef98
diff --git a/src/com/android/settings/network/SubscriptionInfoListViewModel.kt b/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
index d30b21d..ee88177 100644
--- a/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
+++ b/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
@@ -19,8 +19,10 @@
 import android.app.Application
 import android.telephony.SubscriptionInfo
 import android.telephony.SubscriptionManager
+
 import androidx.lifecycle.AndroidViewModel
 import androidx.lifecycle.viewModelScope
+
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.asExecutor
 import kotlinx.coroutines.channels.awaitClose
@@ -32,13 +34,12 @@
 
 class SubscriptionInfoListViewModel(application: Application) : AndroidViewModel(application) {
     private val scope = viewModelScope + Dispatchers.Default
-
     val subscriptionInfoListFlow = callbackFlow<List<SubscriptionInfo>> {
         val subscriptionManager = application.getSystemService(SubscriptionManager::class.java)!!
 
         val listener = object : SubscriptionManager.OnSubscriptionsChangedListener() {
             override fun onSubscriptionsChanged() {
-                trySend(subscriptionManager.activeSubscriptionInfoList ?: emptyList())
+                trySend(SubscriptionUtil.getActiveSubscriptions(subscriptionManager))
             }
         }
 
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index 9974ba2..7a127bb 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -18,6 +18,8 @@
 
 import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
 import static android.telephony.UiccSlotInfo.CARD_STATE_INFO_PRESENT;
+import static android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING;
+
 import static com.android.internal.util.CollectionUtils.emptyIfNull;
 
 import android.annotation.Nullable;
@@ -36,9 +38,11 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.flags.Flags;
 import com.android.settings.R;
 import com.android.settings.network.helper.SelectableSubscriptions;
 import com.android.settings.network.helper.SubscriptionAnnotation;
@@ -84,6 +88,8 @@
     }
 
     public static List<SubscriptionInfo> getActiveSubscriptions(SubscriptionManager manager) {
+        //TODO (b/315499317) : Refactor the subscription utils.
+
         if (sActiveResultsForTesting != null) {
             return sActiveResultsForTesting;
         }
@@ -94,7 +100,12 @@
         if (subscriptions == null) {
             return new ArrayList<>();
         }
-        return subscriptions;
+        // Since the SubscriptionManager.getActiveSubscriptionInfoList() has checked whether the
+        // sim visible by the SubscriptionManager.isSubscriptionVisible(), here only checks whether
+        // the esim visible here.
+        return subscriptions.stream()
+                .filter(subInfo -> subInfo != null && isEmbeddedSubscriptionVisible(subInfo))
+                .collect(Collectors.toList());
     }
 
     /**
@@ -128,7 +139,7 @@
     }
 
     /**
-     * Get subscription which is available to be displayed to the user
+     * Get subscriptionInfo which is available to be displayed to the user
      * per subscription id.
      *
      * @param context {@code Context}
@@ -138,13 +149,20 @@
      * @return {@code SubscriptionInfo} based on the given subscription id. Null of subscription
      *         is invalid or not allowed to be displayed to the user.
      */
-    public static SubscriptionInfo getAvailableSubscription(Context context,
+    public static SubscriptionInfo getAvailableSubscriptionBySubIdAndShowingForUser(Context context,
             ProxySubscriptionManager subscriptionManager, int subId) {
+        //TODO (b/315499317) : Refactor the subscription utils.
         final SubscriptionInfo subInfo = subscriptionManager.getAccessibleSubscriptionInfo(subId);
         if (subInfo == null) {
             return null;
         }
 
+        // hide provisioning/bootstrap and satellite profiles for user
+        if (isEmbeddedSubscriptionVisible(subInfo)) {
+            Log.d(TAG, "Do not insert the provision eSIM or NTN eSim");
+            return null;
+        }
+
         final ParcelUuid groupUuid = subInfo.getGroupUuid();
 
         if (groupUuid != null) {
@@ -567,6 +585,12 @@
     public static boolean isSubscriptionVisible(
             SubscriptionManager subscriptionManager, Context context, SubscriptionInfo info) {
         if (info == null) return false;
+
+        // hide provisioning/bootstrap and satellite profiles for user
+        if (isEmbeddedSubscriptionVisible(info)) {
+            return false;
+        }
+
         // If subscription is NOT grouped opportunistic subscription, it's visible.
         if (info.getGroupUuid() == null || !info.isOpportunistic()) return true;
 
@@ -786,4 +810,14 @@
         }
         return (currentSubInfo == null) ? null : currentSubInfo.getSubInfo();
     }
+
+    private static boolean isEmbeddedSubscriptionVisible(@NonNull SubscriptionInfo subInfo) {
+        if (subInfo.isEmbedded()
+                && (subInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING
+                || (Flags.oemEnabledSatelliteFlag()
+                && subInfo.isOnlyNonTerrestrialNetwork()))) {
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java
index 0c3e6bd..6601828 100644
--- a/src/com/android/settings/network/SubscriptionsPreferenceController.java
+++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java
@@ -521,7 +521,7 @@
          * Uses to inject function and value for class and test class.
          */
         public boolean canSubscriptionBeDisplayed(Context context, int subId) {
-            return (SubscriptionUtil.getAvailableSubscription(context,
+            return (SubscriptionUtil.getAvailableSubscriptionBySubIdAndShowingForUser(context,
                     ProxySubscriptionManager.getInstance(context), subId) != null);
         }
 
diff --git a/tests/spa_unit/src/com/android/settings/network/SubscriptionInfoListViewModelTest.kt b/tests/spa_unit/src/com/android/settings/network/SubscriptionInfoListViewModelTest.kt
new file mode 100644
index 0000000..020a470
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/SubscriptionInfoListViewModelTest.kt
@@ -0,0 +1,153 @@
+/*
+ * 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
+
+import android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING
+
+import android.app.Application
+import android.content.Context
+import android.platform.test.flag.junit.SetFlagsRule
+import android.telephony.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import android.telephony.TelephonyCallback
+import android.telephony.TelephonyManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.internal.telephony.flags.Flags
+import com.android.settings.network.telephony.CallStateFlowTest
+import com.android.settingslib.spa.testutils.toListWithTimeout
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.async
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doAnswer
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+
+@RunWith(AndroidJUnit4::class)
+class SubscriptionInfoListViewModelTest {
+    @get:Rule
+    val mSetFlagsRule = SetFlagsRule()
+    private var subInfoListener: SubscriptionManager.OnSubscriptionsChangedListener? = null
+    private val mockSubscriptionManager = mock<SubscriptionManager> {
+        on { activeSubscriptionInfoList } doAnswer { activeSubscriptionInfoList }
+        on { addOnSubscriptionsChangedListener(any(), any()) } doAnswer {
+            subInfoListener =
+                it.arguments[1] as SubscriptionManager.OnSubscriptionsChangedListener
+            subInfoListener?.onSubscriptionsChanged()
+        }
+    }
+
+    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+        on { getSystemService(SubscriptionManager::class.java) } doReturn mockSubscriptionManager
+    }
+
+    private val subscriptionInfoListViewModel: SubscriptionInfoListViewModel =
+        SubscriptionInfoListViewModel(context as Application);
+
+    private var activeSubscriptionInfoList: List<SubscriptionInfo>? = null
+
+    @Test
+    fun onSubscriptionsChanged_noProvisioning_resultSameAsInput() = runBlocking {
+        activeSubscriptionInfoList = listOf(SUB_INFO_1, SUB_INFO_2)
+
+        val listDeferred = async {
+            subscriptionInfoListViewModel.subscriptionInfoListFlow.toListWithTimeout()
+        }
+        delay(100)
+        subInfoListener?.onSubscriptionsChanged()
+
+        assertThat(listDeferred.await()).contains(activeSubscriptionInfoList)
+    }
+
+    @Test
+    fun onSubscriptionsChanged_hasProvisioning_filterProvisioning() = runBlocking {
+        activeSubscriptionInfoList = listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_3)
+        val expectation = listOf(SUB_INFO_1, SUB_INFO_2)
+
+        val listDeferred = async {
+            subscriptionInfoListViewModel.subscriptionInfoListFlow.toListWithTimeout()
+        }
+        delay(100)
+        subInfoListener?.onSubscriptionsChanged()
+
+        assertThat(listDeferred.await()).contains(expectation)
+    }
+
+    @Test
+    fun onSubscriptionsChanged_flagOffHasNonTerrestrialNetwork_filterNonTerrestrialNetwork() =
+        runBlocking {
+            mSetFlagsRule.disableFlags(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+
+            activeSubscriptionInfoList = listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_4)
+            val expectation = listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_4)
+
+            val listDeferred = async {
+                subscriptionInfoListViewModel.subscriptionInfoListFlow.toListWithTimeout()
+            }
+            delay(100)
+            subInfoListener?.onSubscriptionsChanged()
+
+            assertThat(listDeferred.await()).contains(expectation)
+        }
+
+    @Test
+    fun onSubscriptionsChanged_flagOnHasNonTerrestrialNetwork_filterNonTerrestrialNetwork() =
+        runBlocking {
+            mSetFlagsRule.enableFlags(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+
+            activeSubscriptionInfoList = listOf(SUB_INFO_1, SUB_INFO_2, SUB_INFO_4)
+            val expectation = listOf(SUB_INFO_1, SUB_INFO_2)
+
+            val listDeferred = async {
+                subscriptionInfoListViewModel.subscriptionInfoListFlow.toListWithTimeout()
+            }
+            delay(100)
+            subInfoListener?.onSubscriptionsChanged()
+
+            assertThat(listDeferred.await()).contains(expectation)
+        }
+
+    private companion object {
+        val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(1)
+        }.build()
+
+        val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(2)
+        }.build()
+
+        val SUB_INFO_3: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(3)
+            setEmbedded(true)
+            setProfileClass(PROFILE_CLASS_PROVISIONING)
+            setOnlyNonTerrestrialNetwork(false)
+        }.build()
+
+        val SUB_INFO_4: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(4)
+            setEmbedded(true)
+            setOnlyNonTerrestrialNetwork(true)
+        }.build()
+    }
+}
\ No newline at end of file