Add SettingsExposedDropdownMenuCheckBox.
SettingsExposedDropdownMenuCheckBox requires input index.

Bug: 298906796
Test: Munual
Change-Id: I6059bd5371a2472fbbb9a6b0aa83be769f90264e
diff --git a/src/com/android/settings/network/apn/ApnEditPageProvider.kt b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
index 90d96c6..f2c3325 100644
--- a/src/com/android/settings/network/apn/ApnEditPageProvider.kt
+++ b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
@@ -34,6 +34,7 @@
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuBox
+import com.android.settingslib.spa.widget.editor.SettingsExposedDropdownMenuCheckBox
 import com.android.settingslib.spa.widget.editor.SettingsOutlinedTextField
 import com.android.settingslib.spa.widget.preference.SwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
@@ -86,8 +87,13 @@
     val context = LocalContext.current
     val authTypeOptions = stringArrayResource(R.array.apn_auth_entries).toList()
     val apnProtocolOptions = stringArrayResource(R.array.apn_protocol_entries).toList()
+    val bearerOptionsAll = stringArrayResource(R.array.bearer_entries)
+    val bearerOptions = bearerOptionsAll.drop(1).toList()
+    val bearerEmptyVal = bearerOptionsAll[0]
     val mvnoTypeOptions = stringArrayResource(R.array.mvno_type_entries).toList()
-
+    val bearerSelectedOptionsState = remember {
+        getBearerSelectedOptionsState(apnData.bearer, apnData.bearerBitmask, context)
+    }
     RegularScaffold(
         title = stringResource(id = R.string.apn_edit),
     ) {
@@ -184,6 +190,13 @@
                     }
                 }
             )
+            SettingsExposedDropdownMenuCheckBox(
+                stringResource(R.string.bearer),
+                bearerOptions,
+                bearerSelectedOptionsState,
+                bearerEmptyVal,
+                apnData.bearerEnabled
+            ) {}
             SettingsExposedDropdownMenuBox(
                 stringResource(R.string.mvno_type),
                 mvnoTypeOptions,
diff --git a/src/com/android/settings/network/apn/ApnStatus.kt b/src/com/android/settings/network/apn/ApnStatus.kt
index 7f4c297..06d8cfb 100644
--- a/src/com/android/settings/network/apn/ApnStatus.kt
+++ b/src/com/android/settings/network/apn/ApnStatus.kt
@@ -16,8 +16,12 @@
 
 package com.android.settings.network.apn
 
+import android.content.Context
 import android.provider.Telephony
 import android.telephony.TelephonyManager
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.snapshots.SnapshotStateList
+import com.android.settings.R
 
 data class ApnData(
     val name: String = "",
@@ -65,4 +69,29 @@
     var bearerEnabled = true
     var mvnoTypeEnabled = true
     var mvnoValueEnabled = false
-}
\ No newline at end of file
+}
+
+fun getBearerSelectedOptionsState(
+    bearer: Int,
+    bearerBitmask: Int,
+    context: Context
+): SnapshotStateList<Int> {
+    val bearerValues = context.resources.getStringArray(R.array.bearer_values)
+    val bearerSelectedOptionsState = mutableStateListOf<Int>()
+    if (bearerBitmask != 0) {
+        var i = 1
+        var _bearerBitmask = bearerBitmask
+        while (_bearerBitmask != 0) {
+            if (_bearerBitmask and 1 == 1 && !bearerSelectedOptionsState.contains(i)) {
+                bearerSelectedOptionsState.add(bearerValues.indexOf("$i") - 1)
+            }
+            _bearerBitmask = _bearerBitmask shr 1
+            i++
+        }
+    }
+    if (bearer != 0 && !bearerSelectedOptionsState.contains(bearer)) {
+        // add mBearerInitialVal to bearers
+        bearerSelectedOptionsState.add(bearerValues.indexOf("$bearer") - 1)
+    }
+    return bearerSelectedOptionsState
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt b/tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt
index 590fe9e..0d2dcef 100644
--- a/tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/apn/ApnEditPageProviderTest.kt
@@ -17,16 +17,22 @@
 package com.android.settings.network.apn
 
 import android.content.Context
+import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.assertIsOff
 import androidx.compose.ui.test.assertIsOn
 import androidx.compose.ui.test.hasText
+import androidx.compose.ui.test.isFocused
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onAllNodesWithText
 import androidx.compose.ui.test.onChild
 import androidx.compose.ui.test.onChildAt
+import androidx.compose.ui.test.onLast
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.onRoot
+import androidx.compose.ui.test.performClick
 import androidx.compose.ui.test.performScrollToNode
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -49,15 +55,20 @@
     private val apnType = "apn_type"
     private val apnRoaming = "IPv4"
     private val apnEnable = context.resources.getString(R.string.carrier_enabled)
-    private val apnProtocolOptions = context.resources.getStringArray(R.array.apn_protocol_entries).toList()
-    private val apnData = ApnData(
-        name = apnName,
-        mmsc = mmsc,
-        mmsProxy = mmsProxy,
-        mnc = mnc,
-        apnType = apnType,
-        apnRoaming = apnProtocolOptions.indexOf(apnRoaming),
-        apnEnable = true
+    private val apnProtocolOptions =
+        context.resources.getStringArray(R.array.apn_protocol_entries).toList()
+    private val bearer = context.resources.getString(R.string.bearer)
+    private val bearerOptions = context.resources.getStringArray(R.array.bearer_entries).toList()
+    private val apnData = mutableStateOf(
+        ApnData(
+            name = apnName,
+            mmsc = mmsc,
+            mmsProxy = mmsProxy,
+            mnc = mnc,
+            apnType = apnType,
+            apnRoaming = apnProtocolOptions.indexOf(apnRoaming),
+            apnEnable = true
+        )
     )
 
     @Test
@@ -69,7 +80,7 @@
     fun title_displayed() {
         composeTestRule.setContent {
             ApnPage(remember {
-                mutableStateOf(apnData)
+                apnData
             })
         }
         composeTestRule.onNodeWithText(context.getString(R.string.apn_edit)).assertIsDisplayed()
@@ -79,7 +90,7 @@
     fun name_displayed() {
         composeTestRule.setContent {
             ApnPage(remember {
-                mutableStateOf(apnData)
+                apnData
             })
         }
         composeTestRule.onNodeWithText(apnName, true).assertIsDisplayed()
@@ -89,7 +100,7 @@
     fun mmsc_displayed() {
         composeTestRule.setContent {
             ApnPage(remember {
-                mutableStateOf(apnData)
+                apnData
             })
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
@@ -101,7 +112,7 @@
     fun mms_proxy_displayed() {
         composeTestRule.setContent {
             ApnPage(remember {
-                mutableStateOf(apnData)
+                apnData
             })
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
@@ -113,7 +124,7 @@
     fun mnc_displayed() {
         composeTestRule.setContent {
             ApnPage(remember {
-                mutableStateOf(apnData)
+                apnData
             })
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
@@ -125,7 +136,7 @@
     fun apn_type_displayed() {
         composeTestRule.setContent {
             ApnPage(remember {
-                mutableStateOf(apnData)
+                apnData
             })
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
@@ -137,7 +148,7 @@
     fun apn_roaming_displayed() {
         composeTestRule.setContent {
             ApnPage(remember {
-                mutableStateOf(apnData)
+                apnData
             })
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
@@ -149,7 +160,7 @@
     fun carrier_enabled_displayed() {
         composeTestRule.setContent {
             ApnPage(remember {
-                mutableStateOf(apnData)
+                apnData
             })
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
@@ -161,11 +172,73 @@
     fun carrier_enabled_isChecked() {
         composeTestRule.setContent {
             ApnPage(remember {
-                mutableStateOf(apnData)
+                apnData
             })
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
             .performScrollToNode(hasText(apnEnable, true))
         composeTestRule.onNodeWithText(apnEnable, true).assertIsOn()
     }
+
+    @Test
+    fun carrier_enabled_checkChanged() {
+        composeTestRule.setContent {
+            ApnPage(remember {
+                apnData
+            })
+        }
+        composeTestRule.onRoot().onChild().onChildAt(0)
+            .performScrollToNode(hasText(apnEnable, true))
+        composeTestRule.onNodeWithText(apnEnable, true).performClick()
+        composeTestRule.onNodeWithText(apnEnable, true).assertIsOff()
+    }
+
+    @Test
+    fun bearer_displayed() {
+        composeTestRule.setContent {
+            ApnPage(remember {
+                apnData
+            })
+        }
+        composeTestRule.onRoot().onChild().onChildAt(0)
+            .performScrollToNode(hasText(bearer, true))
+        composeTestRule.onNodeWithText(bearer, true).assertIsDisplayed()
+    }
+
+    @Test
+    fun bearer_changed() {
+        var apnDataa: MutableState<ApnData> = apnData
+        composeTestRule.setContent {
+            apnDataa = remember {
+                apnData
+            }
+            ApnPage(apnDataa)
+        }
+        composeTestRule.onRoot().onChild().onChildAt(0)
+            .performScrollToNode(hasText(bearer, true))
+        composeTestRule.onNodeWithText(bearer, true).performClick()
+        composeTestRule.onNodeWithText(bearerOptions[1], true).performClick()
+        composeTestRule.onNode(hasText(bearerOptions[0]) and isFocused(), true).assertDoesNotExist()
+        composeTestRule.onNode(hasText(bearerOptions[1]) and isFocused(), true).assertIsDisplayed()
+    }
+
+    @Test
+    fun bearer_changed_back2Default() {
+        var apnDataa: MutableState<ApnData> = apnData
+        composeTestRule.setContent {
+            apnDataa = remember {
+                apnData
+            }
+            ApnPage(apnDataa)
+        }
+        composeTestRule.onRoot().onChild().onChildAt(0)
+            .performScrollToNode(hasText(bearer, true))
+        composeTestRule.onNodeWithText(bearer, true).performClick()
+        composeTestRule.onNodeWithText(bearerOptions[1], true).performClick()
+        composeTestRule.onNode(hasText(bearerOptions[0]) and isFocused(), true).assertDoesNotExist()
+        composeTestRule.onNode(hasText(bearerOptions[1]) and isFocused(), true).assertIsDisplayed()
+        composeTestRule.onAllNodesWithText(bearerOptions[1], true).onLast().performClick()
+        composeTestRule.onNode(hasText(bearerOptions[0]) and isFocused(), true).assertIsDisplayed()
+        composeTestRule.onNode(hasText(bearerOptions[1]) and isFocused(), true).assertDoesNotExist()
+    }
 }
\ No newline at end of file