Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 93fb316f authored by Charlotte Lu's avatar Charlotte Lu
Browse files

Add ApnDataInit.

Fix: 298906796
Test: Unit Test
Change-Id: Ibf9e12e4f9c4ee033ad6dc2ca1f2267bf1f21912
parent 4188a571
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ const val SUB_ID = "subId"
const val MVNO_TYPE = "mvnoType"
const val MVNO_MATCH_DATA = "mvnoMatchData"
const val EDIT_URL = "editUrl"
const val INSERT_URL = "insertUrl"

object ApnEditPageProvider : SettingsPageProvider {

@@ -66,7 +67,10 @@ object ApnEditPageProvider : SettingsPageProvider {

    @Composable
    override fun Page(arguments: Bundle?) {
        val apnDataInit = ApnData()
        val uriString = arguments!!.getString(URI)
        val uriInit = Uri.parse(String(Base64.getDecoder().decode(uriString)))
        val subId = arguments.getInt(SUB_ID)
        val apnDataInit = getApnDataInit(arguments, LocalContext.current, uriInit, subId)
        val apnDataCur = remember {
            mutableStateOf(apnDataInit)
        }
+182 −0
Original line number Diff line number Diff line
/*
 * 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.apn

import android.content.Context
import android.net.Uri
import android.provider.Telephony
import android.util.Log
import com.android.settings.R
import java.util.Locale

const val NAME_INDEX = 1
const val APN_INDEX = 2
const val PROXY_INDEX = 3
const val PORT_INDEX = 4
const val USER_INDEX = 5
const val SERVER_INDEX = 6
const val PASSWORD_INDEX = 7
const val MMSC_INDEX = 8
const val MCC_INDEX = 9
const val MNC_INDEX = 10
const val MMSPROXY_INDEX = 12
const val MMSPORT_INDEX = 13
const val AUTH_TYPE_INDEX = 14
const val TYPE_INDEX = 15
const val PROTOCOL_INDEX = 16
const val CARRIER_ENABLED_INDEX = 17
const val NETWORK_TYPE_INDEX = 18
const val ROAMING_PROTOCOL_INDEX = 19
const val MVNO_TYPE_INDEX = 20
const val MVNO_MATCH_DATA_INDEX = 21
const val EDITED_INDEX = 22
const val USER_EDITABLE_INDEX = 23
const val CARRIER_ID_INDEX = 24

val sProjection = arrayOf(
    Telephony.Carriers._ID,  // 0
    Telephony.Carriers.NAME,  // 1
    Telephony.Carriers.APN,  // 2
    Telephony.Carriers.PROXY,  // 3
    Telephony.Carriers.PORT,  // 4
    Telephony.Carriers.USER,  // 5
    Telephony.Carriers.SERVER,  // 6
    Telephony.Carriers.PASSWORD,  // 7
    Telephony.Carriers.MMSC,  // 8
    Telephony.Carriers.MCC,  // 9
    Telephony.Carriers.MNC,  // 10
    Telephony.Carriers.NUMERIC,  // 11
    Telephony.Carriers.MMSPROXY,  // 12
    Telephony.Carriers.MMSPORT,  // 13
    Telephony.Carriers.AUTH_TYPE,  // 14
    Telephony.Carriers.TYPE,  // 15
    Telephony.Carriers.PROTOCOL,  // 16
    Telephony.Carriers.CARRIER_ENABLED,  // 17
    Telephony.Carriers.NETWORK_TYPE_BITMASK, // 18
    Telephony.Carriers.ROAMING_PROTOCOL,  // 19
    Telephony.Carriers.MVNO_TYPE,  // 20
    Telephony.Carriers.MVNO_MATCH_DATA,  // 21
    Telephony.Carriers.EDITED_STATUS,  // 22
    Telephony.Carriers.USER_EDITABLE,  // 23
    Telephony.Carriers.CARRIER_ID // 24
)

const val TAG = "ApnRepository"

/**
 * Query apn related information based on uri.
 * @param uri URI data used for query.
 *
 * @return Stored apn related information.
 */
fun getApnDataFromUri(uri: Uri, context: Context): ApnData {
    var apnData = ApnData()
    val contentResolver = context.contentResolver
    val apnProtocolOptions = context.resources.getStringArray(R.array.apn_protocol_entries).toList()
    val mvnoTypeOptions = context.resources.getStringArray(R.array.mvno_type_entries).toList()

    contentResolver.query(
        uri,
        sProjection,
        null /* selection */,
        null /* selectionArgs */,
        null /* sortOrder */
    ).use { cursor ->
        if (cursor != null && cursor.moveToFirst()) {
            val name = cursor.getString(NAME_INDEX)
            val apn = cursor.getString(APN_INDEX)
            val proxy = cursor.getString(PROXY_INDEX)
            val port = cursor.getString(PORT_INDEX)
            val userName = cursor.getString(USER_INDEX)
            val server = cursor.getString(SERVER_INDEX)
            val passWord = cursor.getString(PASSWORD_INDEX)
            val mmsc = cursor.getString(MMSC_INDEX)
            val mcc = cursor.getString(MCC_INDEX)
            val mnc = cursor.getString(MNC_INDEX)
            val mmsProxy = cursor.getString(MMSPROXY_INDEX)
            val mmsPort = cursor.getString(MMSPORT_INDEX)
            val authType = cursor.getInt(AUTH_TYPE_INDEX)
            val apnType = cursor.getString(TYPE_INDEX)
            val apnProtocol = convertProtocol2Options(cursor.getString(PROTOCOL_INDEX), context)
            val apnRoaming =
                convertProtocol2Options(cursor.getString(ROAMING_PROTOCOL_INDEX), context)
            val apnEnable = cursor.getInt(CARRIER_ENABLED_INDEX) == 1
            val networkType = cursor.getLong(NETWORK_TYPE_INDEX)
            val mvnoType = cursor.getString(MVNO_TYPE_INDEX)
            val mvnoValue = cursor.getString(MVNO_MATCH_DATA_INDEX)

            val edited = cursor.getInt(EDITED_INDEX)
            val userEditable = cursor.getInt(USER_EDITABLE_INDEX)
            val carrierId = cursor.getInt(CARRIER_ID_INDEX)

            apnData = apnData.copy(
                name = name,
                apn = apn,
                proxy = proxy,
                port = port,
                userName = userName,
                passWord = passWord,
                server = server,
                mmsc = mmsc,
                mmsProxy = mmsProxy,
                mmsPort = mmsPort,
                mcc = mcc,
                mnc = mnc,
                authType = authType,
                apnType = apnType,
                apnProtocol = apnProtocolOptions.indexOf(apnProtocol),
                apnRoaming = apnProtocolOptions.indexOf(apnRoaming),
                apnEnable = apnEnable,
                networkType = networkType,
                mvnoType = mvnoTypeOptions.indexOf(mvnoType),
                mvnoValue = mvnoValue,
                edited = edited,
                userEditable = userEditable,
                carrierId = carrierId
            )
        }
    }
    if (apnData.name == "") {
        Log.d(TAG, "Can't get apnData from Uri $uri")
    }
    return apnData
}

/**
 * Returns The UI choice (e.g., "IPv4/IPv6") corresponding to the given
 * raw value of the protocol preference (e.g., "IPV4V6"). If unknown,
 * return null.
 *
 * @return UI choice
 */
private fun convertProtocol2Options(raw: String, context: Context): String {
    val apnProtocolOptions = context.resources.getStringArray(R.array.apn_protocol_entries).toList()
    val apnProtocolValues = context.resources.getStringArray(R.array.apn_protocol_values).toList()

    var uRaw = raw.uppercase(Locale.getDefault())
    uRaw = if (uRaw == "IPV4") "IP" else uRaw
    val protocolIndex = apnProtocolValues.indexOf(uRaw)
    return if (protocolIndex == -1) {
        ""
    } else {
        try {
            apnProtocolOptions[protocolIndex]
        } catch (e: ArrayIndexOutOfBoundsException) {
            ""
        }
    }
}
+151 −22
Original line number Diff line number Diff line
@@ -16,8 +16,16 @@

package com.android.settings.network.apn

import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.provider.Telephony
import android.telephony.CarrierConfigManager
import android.telephony.TelephonyManager
import android.text.TextUtils
import android.util.Log
import com.android.internal.util.ArrayUtils
import com.android.settings.R

data class ApnData(
    val name: String = "",
@@ -42,26 +50,147 @@ data class ApnData(
    var mvnoValue: String = "",
    val edited: Int = Telephony.Carriers.USER_EDITED,
    val userEditable: Int = 1,
    val carrierId: Int = TelephonyManager.UNKNOWN_CARRIER_ID
) {
    var nameEnabled = true
    var apnEnabled = true
    var proxyEnabled = true
    var portEnabled = true
    var userNameEnabled = true
    var passWordEnabled = true
    var serverEnabled = true
    var mmscEnabled = true
    var mmsProxyEnabled = true
    var mmsPortEnabled = true
    var mccEnabled = true
    var mncEnabled = true
    var authTypeEnabled = true
    var apnTypeEnabled = true
    var apnProtocolEnabled = true
    var apnRoamingEnabled = true
    var apnEnableEnabled = true
    var networkTypeEnabled = true
    var mvnoTypeEnabled = true
    var mvnoValueEnabled = false
    val carrierId: Int = TelephonyManager.UNKNOWN_CARRIER_ID,
    val nameEnabled: Boolean = true,
    val apnEnabled: Boolean = true,
    val proxyEnabled: Boolean = true,
    val portEnabled: Boolean = true,
    val userNameEnabled: Boolean = true,
    val passWordEnabled: Boolean = true,
    val serverEnabled: Boolean = true,
    val mmscEnabled: Boolean = true,
    val mmsProxyEnabled: Boolean = true,
    val mmsPortEnabled: Boolean = true,
    val mccEnabled: Boolean = true,
    val mncEnabled: Boolean = true,
    val authTypeEnabled: Boolean = true,
    val apnTypeEnabled: Boolean = true,
    val apnProtocolEnabled: Boolean = true,
    val apnRoamingEnabled: Boolean = true,
    val apnEnableEnabled: Boolean = true,
    val networkTypeEnabled: Boolean = true,
    val mvnoTypeEnabled: Boolean = true,
    val mvnoValueEnabled: Boolean = false,
    val newApn: Boolean = false,
)

data class CustomizedConfig(
    val newApn: Boolean = false,
    val readOnlyApn: Boolean = false,
    val isAddApnAllowed: Boolean = true,
    val readOnlyApnTypes: List<String> = emptyList(),
    val readOnlyApnFields: List<String> = emptyList(),
    val defaultApnTypes: List<String> = emptyList(),
    val defaultApnProtocol: String = "",
    val defaultApnRoamingProtocol: String = "",
)

/**
 * Initialize ApnData according to the arguments.
 * @param arguments The data passed in when the user calls PageProvider.
 * @param uriInit The decoded user incoming uri data in Page.
 * @param subId The subId obtained in arguments.
 *
 * @return Initialized CustomizedConfig information.
 */
fun getApnDataInit(arguments: Bundle, context: Context, uriInit: Uri, subId: Int): ApnData {

    val uriType = arguments.getString(URI_TYPE)!!
    val mvnoType = arguments.getString(MVNO_TYPE)
    val mvnoValue = arguments.getString(MVNO_MATCH_DATA)
    val mvnoTypeOptions = context.resources.getStringArray(R.array.mvno_type_entries).toList()

    val configManager =
        context.getSystemService(Context.CARRIER_CONFIG_SERVICE) as CarrierConfigManager
    getCarrierCustomizedConfig(configManager, subId)

    if (!uriInit.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) {
        Log.e(TAG, "Insert request not for carrier table. Uri: $uriInit")
        return ApnData() //TODO: finish
    }

    var apnDataInit = when (uriType) {
        EDIT_URL -> getApnDataFromUri(uriInit, context)
        INSERT_URL -> ApnData(
            mvnoType = mvnoTypeOptions.indexOf(mvnoType!!),
            mvnoValue = mvnoValue!!
        )

        else -> ApnData() //TODO: finish
    }

    if (uriType == INSERT_URL) {
        apnDataInit = apnDataInit.copy(newApn = true)
    }

    // TODO: mvnoDescription
    apnDataInit = apnDataInit.copy(
        apnEnableEnabled =
        context.resources.getBoolean(R.bool.config_allow_edit_carrier_enabled)
    )
    // TODO: mIsCarrierIdApn & disableInit(apnDataInit)
    return apnDataInit
}

/**
 * Initialize CustomizedConfig information through subId.
 * @param subId subId information obtained from arguments.
 *
 * @return Initialized CustomizedConfig information.
 */
fun getCarrierCustomizedConfig(configManager: CarrierConfigManager, subId: Int): CustomizedConfig {
    val b = configManager.getConfigForSubId(
        subId,
        CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY,
        CarrierConfigManager.KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY,
        CarrierConfigManager.KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY,
        CarrierConfigManager.Apn.KEY_SETTINGS_DEFAULT_PROTOCOL_STRING,
        CarrierConfigManager.Apn.KEY_SETTINGS_DEFAULT_ROAMING_PROTOCOL_STRING,
        CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL
    )
    val customizedConfig = CustomizedConfig(
        readOnlyApnTypes = b.getStringArray(
            CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY
        )?.toList() ?: emptyList(), readOnlyApnFields = b.getStringArray(
            CarrierConfigManager.KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY
        )?.toList() ?: emptyList(), defaultApnTypes = b.getStringArray(
            CarrierConfigManager.KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY
        )?.toList() ?: emptyList(), defaultApnProtocol = b.getString(
            CarrierConfigManager.Apn.KEY_SETTINGS_DEFAULT_PROTOCOL_STRING
        ) ?: "", defaultApnRoamingProtocol = b.getString(
            CarrierConfigManager.Apn.KEY_SETTINGS_DEFAULT_ROAMING_PROTOCOL_STRING
        ) ?: "", isAddApnAllowed = b.getBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL)
    )
    if (!ArrayUtils.isEmpty(customizedConfig.readOnlyApnTypes)) {
        Log.d(
            TAG,
            "getCarrierCustomizedConfig: read only APN type: " + customizedConfig.readOnlyApnTypes.joinToString(
                ", "
            )
        )
    }
    if (!ArrayUtils.isEmpty(customizedConfig.defaultApnTypes)) {
        Log.d(
            TAG,
            "getCarrierCustomizedConfig: default apn types: " + customizedConfig.defaultApnTypes.joinToString(
                ", "
            )
        )
    }
    if (!TextUtils.isEmpty(customizedConfig.defaultApnProtocol)) {
        Log.d(
            TAG,
            "getCarrierCustomizedConfig: default apn protocol: ${customizedConfig.defaultApnProtocol}"
        )
    }
    if (!TextUtils.isEmpty(customizedConfig.defaultApnRoamingProtocol)) {
        Log.d(
            TAG,
            "getCarrierCustomizedConfig: default apn roaming protocol: ${customizedConfig.defaultApnRoamingProtocol}"
        )
    }
    if (!customizedConfig.isAddApnAllowed) {
        Log.d(TAG, "getCarrierCustomizedConfig: not allow to add new APN")
    }
    return customizedConfig
}
 No newline at end of file
+55 −0
Original line number Diff line number Diff line
/*
 * 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.apn

import android.content.ContentResolver
import android.content.Context
import android.database.MatrixCursor
import android.net.Uri
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever

@RunWith(AndroidJUnit4::class)
class ApnRepositoryTest {

    private val context: Context = ApplicationProvider.getApplicationContext()
    private val mContentResolver = mock<ContentResolver> {}
    private val uri = mock<Uri> {}

    @Test
    fun getApnDataFromUri() {
        // mock out resources and the feature provider
        val cursor = MatrixCursor(sProjection)
        cursor.addRow(
            arrayOf<Any?>(
                0, "name", "apn", "proxy", "port",
                "userName", "server", "passWord", "mmsc", "mcc", "mnc", "numeric",
                "mmsProxy", "mmsPort", 0, "apnType", "apnProtocol", 0,
                0, "apnRoaming", "mvnoType", "mvnoValue", 0, 1, 0
            )
        )
        val context = Mockito.spy(context)
        whenever(context.contentResolver).thenReturn(mContentResolver)
        whenever(mContentResolver.query(uri, sProjection, null, null, null)).thenReturn(cursor)
        assert(getApnDataFromUri(uri, context).name == "name")
    }
}
 No newline at end of file
+50 −0
Original line number Diff line number Diff line
/*
 * 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.apn

import android.os.PersistableBundle
import android.telephony.CarrierConfigManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock

@RunWith(AndroidJUnit4::class)
class ApnStatusTest {
    private val subId = 1
    private val configManager = mock<CarrierConfigManager> {
        val p = PersistableBundle()
        p.putBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL, true)
        on {
            getConfigForSubId(
                subId,
                CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY,
                CarrierConfigManager.KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY,
                CarrierConfigManager.KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY,
                CarrierConfigManager.Apn.KEY_SETTINGS_DEFAULT_PROTOCOL_STRING,
                CarrierConfigManager.Apn.KEY_SETTINGS_DEFAULT_ROAMING_PROTOCOL_STRING,
                CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL
            )
        } doReturn p
    }

    @Test
    fun getCarrierCustomizedConfig_test() {
        assert(getCarrierCustomizedConfig(configManager, subId).isAddApnAllowed)
    }
}
 No newline at end of file
+2 −2

File changed.

Contains only whitespace changes.

Loading