Add updateApnDataToDatabase.

Fix: 304672976
Test: Visual Test
Change-Id: If0ed6b8090a37c5a98ab2eeb29fba61c1173c0a7
diff --git a/src/com/android/settings/network/apn/ApnEditPageProvider.kt b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
index 0b0431d..46849f8 100644
--- a/src/com/android/settings/network/apn/ApnEditPageProvider.kt
+++ b/src/com/android/settings/network/apn/ApnEditPageProvider.kt
@@ -74,7 +74,7 @@
         val apnDataCur = remember {
             mutableStateOf(apnDataInit)
         }
-        ApnPage(apnDataInit, apnDataCur)
+        ApnPage(apnDataInit, apnDataCur, uriInit)
     }
 
     fun getRoute(
@@ -87,7 +87,7 @@
 }
 
 @Composable
-fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>) {
+fun ApnPage(apnDataInit: ApnData, apnDataCur: MutableState<ApnData>, uriInit: Uri) {
     var apnData by apnDataCur
     val context = LocalContext.current
     val authTypeOptions = stringArrayResource(R.array.apn_auth_entries).toList()
@@ -99,7 +99,7 @@
         title = stringResource(id = R.string.apn_edit),
         actions = {
             IconButton(onClick = {
-                validateAndSaveApnData(apnDataInit, apnData, context)
+                validateAndSaveApnData(apnDataInit, apnData, context, uriInit)
             }) { Icon(imageVector = Icons.Outlined.Done, contentDescription = "Save APN") }
         }
     ) {
diff --git a/src/com/android/settings/network/apn/ApnRepository.kt b/src/com/android/settings/network/apn/ApnRepository.kt
index a518aa5..e0121b4 100644
--- a/src/com/android/settings/network/apn/ApnRepository.kt
+++ b/src/com/android/settings/network/apn/ApnRepository.kt
@@ -16,11 +16,13 @@
 
 package com.android.settings.network.apn
 
+import android.content.ContentValues
 import android.content.Context
 import android.net.Uri
 import android.provider.Telephony
 import android.util.Log
 import com.android.settings.R
+import com.android.settingslib.utils.ThreadUtils
 import java.util.Locale
 
 const val NAME_INDEX = 1
@@ -161,4 +163,35 @@
             ""
         }
     }
+}
+
+fun convertOptions2Protocol(protocolIndex: Int, context: Context): String {
+    val apnProtocolValues = context.resources.getStringArray(R.array.apn_protocol_values).toList()
+
+    return if (protocolIndex == -1) {
+        ""
+    } else {
+        try {
+            apnProtocolValues[protocolIndex]
+        } catch (e: ArrayIndexOutOfBoundsException) {
+            ""
+        }
+    }
+}
+
+fun updateApnDataToDatabase(newApn: Boolean, values: ContentValues, context: Context, uriInit: Uri) {
+    ThreadUtils.postOnBackgroundThread {
+        if (newApn) {
+            // Add a new apn to the database
+            val newUri = context.contentResolver.insert(uriInit, values)
+            if (newUri == null) {
+                Log.e(TAG, "Can't add a new apn to database $uriInit")
+            }
+        } else {
+            // Update the existing apn
+            context.contentResolver.update(
+                uriInit, values, null /* where */, null /* selection Args */
+            )
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/network/apn/ApnStatus.kt b/src/com/android/settings/network/apn/ApnStatus.kt
index 5904e98..a5a215b 100644
--- a/src/com/android/settings/network/apn/ApnStatus.kt
+++ b/src/com/android/settings/network/apn/ApnStatus.kt
@@ -16,6 +16,7 @@
 
 package com.android.settings.network.apn
 
+import android.content.ContentValues
 import android.content.Context
 import android.net.Uri
 import android.os.Bundle
@@ -68,7 +69,29 @@
     val newApn: Boolean = false,
     val subId: Int = -1,
     val customizedConfig: CustomizedConfig = CustomizedConfig()
-)
+) {
+    fun getContentValues(context: Context): ContentValues {
+        val values = ContentValues()
+        values.put(Telephony.Carriers.NAME, name)
+        values.put(Telephony.Carriers.APN, apn)
+        values.put(Telephony.Carriers.PROXY, proxy)
+        values.put(Telephony.Carriers.PORT, port)
+        values.put(Telephony.Carriers.MMSPROXY, mmsProxy)
+        values.put(Telephony.Carriers.MMSPORT, mmsPort)
+        values.put(Telephony.Carriers.USER, userName)
+        values.put(Telephony.Carriers.SERVER, server)
+        values.put(Telephony.Carriers.PASSWORD, passWord)
+        values.put(Telephony.Carriers.MMSC, mmsc)
+        values.put(Telephony.Carriers.AUTH_TYPE, authType)
+        values.put(Telephony.Carriers.PROTOCOL, convertOptions2Protocol(apnProtocol, context))
+        values.put(Telephony.Carriers.ROAMING_PROTOCOL, convertOptions2Protocol(apnRoaming, context))
+        values.put(Telephony.Carriers.TYPE, apnType)
+        values.put(Telephony.Carriers.NETWORK_TYPE_BITMASK, networkType)
+        values.put(Telephony.Carriers.CARRIER_ENABLED, apnEnable)
+        values.put(Telephony.Carriers.EDITED_STATUS, Telephony.Carriers.USER_EDITED)
+        return values
+    }
+}
 
 data class CustomizedConfig(
     val newApn: Boolean = false,
@@ -181,7 +204,7 @@
  *
  * @return true if there is no error
  */
-fun validateAndSaveApnData(apnDataInit: ApnData, apnData: ApnData, context: Context): Boolean {
+fun validateAndSaveApnData(apnDataInit: ApnData, apnData: ApnData, context: Context, uriInit: Uri): Boolean {
     // Nothing to do if it's a read only APN
     if (apnData.customizedConfig.readOnlyApn) {
         return true
@@ -193,7 +216,7 @@
     }
     if (apnData.newApn || (apnData != apnDataInit)) {
         Log.d(TAG, "validateAndSaveApnData: apnData ${apnData.name}")
-        // TODO: updateApnDataToDatabase
+        updateApnDataToDatabase(apnData.newApn, apnData.getContentValues(context), context, uriInit)
     }
     return true
 }
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 ddc8364..20d67fc 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,6 +17,7 @@
 package com.android.settings.network.apn
 
 import android.content.Context
+import android.net.Uri
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.ui.test.assertIsDisplayed
@@ -40,6 +41,7 @@
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
 
 @RunWith(AndroidJUnit4::class)
 class ApnEditPageProviderTest {
@@ -68,6 +70,7 @@
     private val apnData = mutableStateOf(
         apnInit
     )
+    private val uri = mock<Uri> {}
 
     @Test
     fun apnEditPageProvider_name() {
@@ -77,9 +80,7 @@
     @Test
     fun title_displayed() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onNodeWithText(context.getString(R.string.apn_edit)).assertIsDisplayed()
     }
@@ -87,9 +88,7 @@
     @Test
     fun name_displayed() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onNodeWithText(apnName, true).assertIsDisplayed()
     }
@@ -97,9 +96,7 @@
     @Test
     fun mmsc_displayed() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
             .performScrollToNode(hasText(mmsc, true))
@@ -109,9 +106,7 @@
     @Test
     fun mms_proxy_displayed() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
             .performScrollToNode(hasText(mmsProxy, true))
@@ -121,9 +116,7 @@
     @Test
     fun apn_type_displayed() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
             .performScrollToNode(hasText(apnType, true))
@@ -133,9 +126,7 @@
     @Test
     fun apn_roaming_displayed() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
             .performScrollToNode(hasText(apnRoaming, true))
@@ -145,9 +136,7 @@
     @Test
     fun carrier_enabled_displayed() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
             .performScrollToNode(hasText(apnEnable, true))
@@ -157,9 +146,7 @@
     @Test
     fun carrier_enabled_isChecked() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
             .performScrollToNode(hasText(apnEnable, true))
@@ -169,9 +156,7 @@
     @Test
     fun carrier_enabled_checkChanged() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
             .performScrollToNode(hasText(apnEnable, true))
@@ -182,9 +167,7 @@
     @Test
     fun network_type_displayed() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
             .performScrollToNode(hasText(networkType, true))
@@ -194,9 +177,7 @@
     @Test
     fun network_type_changed() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
             .performScrollToNode(hasText(networkType, true))
@@ -210,9 +191,7 @@
     @Test
     fun network_type_changed_back2Default() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
             .performScrollToNode(hasText(networkType, true))
@@ -230,9 +209,7 @@
     @Test
     fun password_displayed() {
         composeTestRule.setContent {
-            ApnPage(apnInit, remember {
-                apnData
-            })
+            ApnPage(apnInit, remember { apnData }, uri)
         }
         composeTestRule.onRoot().onChild().onChildAt(0)
             .performScrollToNode(hasText(passwordTitle, true))