Add SettingsExposedDropdownMenuBox and SwitchPreference.

Bug: 298906796
Test: Munual
Change-Id: I666c51b79589b9529b623c81c156a545af269e03
diff --git a/src/com/android/settings/network/apn/ApnEditPageProvider.kt b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
index 1cca81a..756d90f 100644
--- a/src/com/android/settings/network/apn/ApnEditPageProvider.kt
+++ b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
@@ -20,16 +20,23 @@
 import android.os.Bundle
 import androidx.compose.foundation.layout.Column
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringArrayResource
 import androidx.compose.ui.res.stringResource
 import androidx.navigation.NavType
 import androidx.navigation.navArgument
 import com.android.settings.R
 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.SettingsOutlinedTextField
+import com.android.settingslib.spa.widget.preference.SwitchPreference
+import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
 import com.android.settingslib.spa.widget.scaffold.RegularScaffold
 import java.util.Base64
 
@@ -56,7 +63,10 @@
     @Composable
     override fun Page(arguments: Bundle?) {
         val apnDataInit = ApnData()
-        ApnPage(apnDataInit)
+        val apnDataCur = remember {
+            mutableStateOf(apnDataInit)
+        }
+        ApnPage(apnDataCur)
     }
 
     fun getRoute(
@@ -71,8 +81,13 @@
 }
 
 @Composable
-fun ApnPage(apnDataInit: ApnData) {
-    var apnData by remember { mutableStateOf(apnDataInit) }
+fun ApnPage(apnDataCur: MutableState<ApnData>) {
+    var apnData by apnDataCur
+    val context = LocalContext.current
+    val authTypeOptions = stringArrayResource(R.array.apn_auth_entries).toList()
+    val apnProtocolOptions = stringArrayResource(R.array.apn_protocol_entries).toList()
+    val mvnoTypeOptions = stringArrayResource(R.array.mvno_type_entries).toList()
+
     RegularScaffold(
         title = stringResource(id = R.string.apn_edit),
     ) {
@@ -133,11 +148,50 @@
                 stringResource(R.string.apn_mnc),
                 enabled = apnData.mncEnabled
             ) { apnData = apnData.copy(mnc = it) }
+            SettingsExposedDropdownMenuBox(
+                label = stringResource(R.string.apn_auth_type),
+                options = authTypeOptions,
+                selectedOptionText =
+                authTypeOptions.getOrElse(apnData.authType) { "" },
+                enabled = apnData.authTypeEnabled,
+            ) { apnData = apnData.copy(authType = authTypeOptions.indexOf(it)) }
             SettingsOutlinedTextField(
                 apnData.apnType,
                 stringResource(R.string.apn_type),
                 enabled = apnData.apnTypeEnabled
             ) { apnData = apnData.copy(apn = it) } // TODO: updateApnType
+            SettingsExposedDropdownMenuBox(
+                stringResource(R.string.apn_protocol),
+                apnProtocolOptions,
+                apnData.apnProtocol,
+                apnData.apnProtocolEnabled
+            ) { apnData = apnData.copy(apnProtocol = it) }
+            SettingsExposedDropdownMenuBox(
+                stringResource(R.string.apn_roaming_protocol),
+                apnProtocolOptions,
+                apnData.apnRoaming,
+                apnData.apnRoamingEnabled
+            ) { apnData = apnData.copy(apnRoaming = it) }
+            SwitchPreference(
+                object : SwitchPreferenceModel {
+                    override val title = context.resources.getString(R.string.carrier_enabled)
+                    override val changeable =
+                        stateOf(apnData.apnEnableEnabled)
+                    override val checked =
+                        stateOf(apnData.apnEnable)
+                    override val onCheckedChange = { newChecked: Boolean ->
+                        apnData = apnData.copy(apnEnable = newChecked)
+                    }
+                }
+            )
+            SettingsExposedDropdownMenuBox(
+                stringResource(R.string.mvno_type),
+                mvnoTypeOptions,
+                apnData.mvnoType,
+                apnData.mvnoTypeEnabled
+            ) {
+                apnData = apnData.copy(mvnoType = it)
+            } // TODO: mvnoDescription
             SettingsOutlinedTextField(
                 apnData.mvnoValue,
                 stringResource(R.string.mvno_match_data),
diff --git a/src/com/android/settings/network/apn/ApnStatus.kt b/src/com/android/settings/network/apn/ApnStatus.kt
index 78734d0..8a2d613 100644
--- a/src/com/android/settings/network/apn/ApnStatus.kt
+++ b/src/com/android/settings/network/apn/ApnStatus.kt
@@ -36,7 +36,7 @@
     val apnType: String = "",
     val apnProtocol: String = "",
     val apnRoaming: String = "",
-    val apnEnable: Int = 1,
+    val apnEnable: Boolean = true,
     val bearer: Int = 0,
     val mvnoType: String = "",
     var mvnoValue: String = "",
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 bfdb408..c6c37d5 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,9 +17,17 @@
 package com.android.settings.network.apn
 
 import android.content.Context
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
 import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.assertIsOn
+import androidx.compose.ui.test.hasText
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onChild
+import androidx.compose.ui.test.onChildAt
 import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.onRoot
+import androidx.compose.ui.test.performScrollToNode
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.settings.R
@@ -34,8 +42,22 @@
     val composeTestRule = createComposeRule()
 
     private val context: Context = ApplicationProvider.getApplicationContext()
-
-    val apnData = ApnData(name = "apn_name")
+    private val apnName = "apn_name"
+    private val mmsc = "mmsc"
+    private val mmsProxy = "mms_proxy"
+    private val mnc = "mnc"
+    private val apnType = "apn_type"
+    private val apnRoaming = "IPv4"
+    private val apnEnable = context.resources.getString(R.string.carrier_enabled)
+    private val apnData = ApnData(
+        name = apnName,
+        mmsc = mmsc,
+        mmsProxy = mmsProxy,
+        mnc = mnc,
+        apnType = apnType,
+        apnRoaming = apnRoaming,
+        apnEnable = true
+    )
 
     @Test
     fun apnEditPageProvider_name() {
@@ -45,7 +67,9 @@
     @Test
     fun title_displayed() {
         composeTestRule.setContent {
-            ApnPage(apnData)
+            ApnPage(remember {
+                mutableStateOf(apnData)
+            })
         }
         composeTestRule.onNodeWithText(context.getString(R.string.apn_edit)).assertIsDisplayed()
     }
@@ -53,8 +77,94 @@
     @Test
     fun name_displayed() {
         composeTestRule.setContent {
-            ApnPage(apnData)
+            ApnPage(remember {
+                mutableStateOf(apnData)
+            })
         }
-        composeTestRule.onNodeWithText("apn_name", true).assertIsDisplayed()
+        composeTestRule.onNodeWithText(apnName, true).assertIsDisplayed()
+    }
+
+    @Test
+    fun mmsc_displayed() {
+        composeTestRule.setContent {
+            ApnPage(remember {
+                mutableStateOf(apnData)
+            })
+        }
+        composeTestRule.onRoot().onChild().onChildAt(0)
+            .performScrollToNode(hasText(mmsc, true))
+        composeTestRule.onNodeWithText(mmsc, true).assertIsDisplayed()
+    }
+
+    @Test
+    fun mms_proxy_displayed() {
+        composeTestRule.setContent {
+            ApnPage(remember {
+                mutableStateOf(apnData)
+            })
+        }
+        composeTestRule.onRoot().onChild().onChildAt(0)
+            .performScrollToNode(hasText(mmsProxy, true))
+        composeTestRule.onNodeWithText(mmsProxy, true).assertIsDisplayed()
+    }
+
+    @Test
+    fun mnc_displayed() {
+        composeTestRule.setContent {
+            ApnPage(remember {
+                mutableStateOf(apnData)
+            })
+        }
+        composeTestRule.onRoot().onChild().onChildAt(0)
+            .performScrollToNode(hasText(mnc, true))
+        composeTestRule.onNodeWithText(mnc, true).assertIsDisplayed()
+    }
+
+    @Test
+    fun apn_type_displayed() {
+        composeTestRule.setContent {
+            ApnPage(remember {
+                mutableStateOf(apnData)
+            })
+        }
+        composeTestRule.onRoot().onChild().onChildAt(0)
+            .performScrollToNode(hasText(apnType, true))
+        composeTestRule.onNodeWithText(apnType, true).assertIsDisplayed()
+    }
+
+    @Test
+    fun apn_roaming_displayed() {
+        composeTestRule.setContent {
+            ApnPage(remember {
+                mutableStateOf(apnData)
+            })
+        }
+        composeTestRule.onRoot().onChild().onChildAt(0)
+            .performScrollToNode(hasText(apnRoaming, true))
+        composeTestRule.onNodeWithText(apnRoaming, true).assertIsDisplayed()
+    }
+
+    @Test
+    fun carrier_enabled_displayed() {
+        composeTestRule.setContent {
+            ApnPage(remember {
+                mutableStateOf(apnData)
+            })
+        }
+        composeTestRule.onRoot().onChild().onChildAt(0)
+            .performScrollToNode(hasText(apnEnable, true))
+        composeTestRule.onNodeWithText(apnEnable, true).assertIsDisplayed()
+    }
+
+    @Test
+    fun carrier_enabled_isChecked() {
+        composeTestRule.setContent {
+            ApnPage(remember {
+                mutableStateOf(apnData)
+            })
+        }
+        composeTestRule.onRoot().onChild().onChildAt(0)
+            .performScrollToNode(hasText(apnEnable, true))
+        composeTestRule.onNodeWithText(apnEnable, true).assertIsOn()
     }
 }
\ No newline at end of file