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

Commit 4e4ee743 authored by Chaohui Wang's avatar Chaohui Wang
Browse files

Unify and merge two hasAllApns()

Also add unit tests.

Fix: 374226933
Flag: EXEMPT refactor
Test: manual - on ApnSettings
Test: atest ApnTypesTest
Change-Id: Ie82252ed13d81118292214b360ac49de9a81b7cc
parent 03e7eacc
Loading
Loading
Loading
Loading
+0 −104
Original line number Diff line number Diff line
@@ -23,88 +23,21 @@ import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.UserManager;
import android.provider.Telephony;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.util.Log;

import androidx.annotation.VisibleForTesting;

import com.android.internal.util.ArrayUtils;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.spa.SpaActivity;

import java.util.Arrays;
import java.util.List;

/** Use to edit apn settings. */
public class ApnEditor extends SettingsPreferenceFragment {

    private static final String TAG = ApnEditor.class.getSimpleName();

    /**
     * APN types for data connections.  These are usage categories for an APN
     * entry.  One APN entry may support multiple APN types, eg, a single APN
     * may service regular internet traffic ("default") as well as MMS-specific
     * connections.<br/>
     * APN_TYPE_ALL is a special type to indicate that this APN entry can
     * service all data connections.
     */
    public static final String APN_TYPE_ALL = "*";
    /** APN type for default data traffic */
    public static final String APN_TYPE_DEFAULT = "default";
    /** APN type for MMS traffic */
    public static final String APN_TYPE_MMS = "mms";
    /** APN type for SUPL assisted GPS */
    public static final String APN_TYPE_SUPL = "supl";
    /** APN type for DUN traffic */
    public static final String APN_TYPE_DUN = "dun";
    /** APN type for HiPri traffic */
    public static final String APN_TYPE_HIPRI = "hipri";
    /** APN type for FOTA */
    public static final String APN_TYPE_FOTA = "fota";
    /** APN type for IMS */
    public static final String APN_TYPE_IMS = "ims";
    /** APN type for CBS */
    public static final String APN_TYPE_CBS = "cbs";
    /** APN type for IA Initial Attach APN */
    public static final String APN_TYPE_IA = "ia";
    /** APN type for Emergency PDN. This is not an IA apn, but is used
     * for access to carrier services in an emergency call situation. */
    public static final String APN_TYPE_EMERGENCY = "emergency";
    /** APN type for Mission Critical Services */
    public static final String APN_TYPE_MCX = "mcx";
    /** APN type for XCAP */
    public static final String APN_TYPE_XCAP = "xcap";
    /** APN type for OEM_PAID networks (Automotive PANS) */
    public static final String APN_TYPE_OEM_PAID = "oem_paid";
    /** APN type for OEM_PRIVATE networks (Automotive PANS) */
    public static final String APN_TYPE_OEM_PRIVATE = "oem_private";
    /** Array of all APN types */
    public static final String[] APN_TYPES = {APN_TYPE_DEFAULT,
            APN_TYPE_MMS,
            APN_TYPE_SUPL,
            APN_TYPE_DUN,
            APN_TYPE_HIPRI,
            APN_TYPE_FOTA,
            APN_TYPE_IMS,
            APN_TYPE_CBS,
            APN_TYPE_IA,
            APN_TYPE_EMERGENCY,
            APN_TYPE_MCX,
            APN_TYPE_XCAP,
            APN_TYPE_OEM_PAID,
            APN_TYPE_OEM_PRIVATE,
    };

    /** Array of APN types that are never user-editable */
    private static final String[] ALWAYS_READ_ONLY_APN_TYPES = new String[] {
        APN_TYPE_OEM_PAID,
        APN_TYPE_OEM_PRIVATE,
    };

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
@@ -143,43 +76,6 @@ public class ApnEditor extends SettingsPreferenceFragment {
        }
    }

    /**
     * Fetch complete list of read only APN types.
     *
     * The list primarily comes from carrier config, but is also supplied by APN types which are
     * always read only.
     */
    static String[] getReadOnlyApnTypes(PersistableBundle b) {
        String[] carrierReadOnlyApnTypes = b.getStringArray(
                CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY);
        return ArrayUtils.concat(String.class, carrierReadOnlyApnTypes, ALWAYS_READ_ONLY_APN_TYPES);
    }

    /**
     * Check if passed in array of APN types indicates all APN types
     * @param apnTypes array of APN types. "*" indicates all types.
     * @return true if all apn types are included in the array, false otherwise
     */
    static boolean hasAllApns(String[] apnTypes) {
        if (ArrayUtils.isEmpty(apnTypes)) {
            return false;
        }

        final List apnList = Arrays.asList(apnTypes);
        if (apnList.contains(APN_TYPE_ALL)) {
            Log.d(TAG, "hasAllApns: true because apnList.contains(APN_TYPE_ALL)");
            return true;
        }
        for (String apn : APN_TYPES) {
            if (!apnList.contains(apn)) {
                return false;
            }
        }

        Log.d(TAG, "hasAllApns: true");
        return true;
    }

    @Override
    public int getMetricsCategory() {
        return SettingsEnums.APN_EDITOR;
+3 −2
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import kotlin.Unit;

import java.util.ArrayList;
import java.util.List;

/** Handle each different apn setting. */
public class ApnSettings extends RestrictedSettingsFragment
@@ -135,9 +136,9 @@ public class ApnSettings extends RestrictedSettingsFragment
        mHideImsApn = b.getBoolean(CarrierConfigManager.KEY_HIDE_IMS_APN_BOOL);
        mAllowAddingApns = b.getBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL);
        if (mAllowAddingApns) {
            final String[] readOnlyApnTypes = ApnEditor.getReadOnlyApnTypes(b);
            final List<String> readOnlyApnTypes = ApnTypes.getReadOnlyApnTypes(b);
            // if no apn type can be edited, do not allow adding APNs
            if (ApnEditor.hasAllApns(readOnlyApnTypes)) {
            if (ApnTypes.hasAllApnTypes(readOnlyApnTypes)) {
                Log.d(TAG, "not allowing adding APN because all APN types are read only");
                mAllowAddingApns = false;
            }
+2 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.telephony.CarrierConfigManager
import android.util.Log
import com.android.settings.R
import com.android.settings.network.apn.ApnTypes.getPreSelectedApnType
import com.android.settings.network.apn.ApnTypes.getReadOnlyApnTypes

private const val TAG = "ApnStatus"

@@ -204,7 +205,7 @@ fun getCarrierCustomizedConfig(
        CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL
    )
    val customizedConfig = CustomizedConfig(
        readOnlyApnTypes = ApnEditor.getReadOnlyApnTypes(b)?.toList() ?: emptyList(),
        readOnlyApnTypes = b.getReadOnlyApnTypes(),
        readOnlyApnFields = b.getStringArray(
            CarrierConfigManager.KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY
        )?.toList() ?: emptyList(),
+31 −3
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.settings.network.apn

import android.content.Context
import android.os.PersistableBundle
import android.telephony.CarrierConfigManager
import android.telephony.data.ApnSetting
import android.util.Log
import android.widget.Toast
@@ -51,9 +53,7 @@ object ApnTypes {

    private fun splitToList(apnType: String): List<String> {
        val types = apnType.split(',').map { it.trim().toLowerCase(Locale.current) }
        if (ApnSetting.TYPE_ALL_STRING in types || APN_TYPES.all { it in types }) {
            return listOf(ApnSetting.TYPE_ALL_STRING)
        }
        if (hasAllApnTypes(types)) return listOf(ApnSetting.TYPE_ALL_STRING)
        return APN_TYPES.filter { it in types }
    }

@@ -132,4 +132,32 @@ object ApnTypes {
    private fun defaultPreSelectedApnTypes(readOnlyApnTypes: List<String>) =
        if (ApnSetting.TYPE_ALL_STRING in readOnlyApnTypes) emptyList()
        else PreSelectedTypes.filterNot { it in readOnlyApnTypes }

    /** Array of APN types that are never user-editable */
    private val ALWAYS_READ_ONLY_APN_TYPES =
        arrayOf(ApnSetting.TYPE_OEM_PAID_STRING, ApnSetting.TYPE_OEM_PRIVATE_STRING)

    /**
     * Fetch complete list of read only APN types.
     *
     * The list primarily comes from carrier config, but is also supplied by APN types which are
     * always read only.
     */
    @JvmStatic
    fun PersistableBundle.getReadOnlyApnTypes(): List<String> {
        val carrierReadOnlyApnTypes =
            getStringArray(CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY)?.toList()
                ?: emptyList()
        return carrierReadOnlyApnTypes + ALWAYS_READ_ONLY_APN_TYPES
    }

    /**
     * Check if passed in array of APN types indicates all APN types
     *
     * @param apnTypes array of APN types. "*" indicates all types.
     * @return true if all apn types are included in the array, false otherwise
     */
    @JvmStatic
    fun hasAllApnTypes(apnTypes: List<String>): Boolean =
        ApnSetting.TYPE_ALL_STRING in apnTypes || APN_TYPES.all { it in apnTypes }
}
+62 −0
Original line number Diff line number Diff line
@@ -91,6 +91,68 @@ class ApnTypesTest {
        assertThat(apnType).isEqualTo("default,mms,supl,hipri,fota,cbs,xcap")
    }

    @Test
    fun hasAllApnTypes_allString() {
        val apnTypes = listOf(ApnSetting.TYPE_ALL_STRING)

        val hasAllApnTypes = ApnTypes.hasAllApnTypes(apnTypes)

        assertThat(hasAllApnTypes).isTrue()
    }

    @Test
    fun hasAllApnTypes_allTypes() {
        val apnTypes = listOf(
            ApnSetting.TYPE_DEFAULT_STRING,
            ApnSetting.TYPE_MMS_STRING,
            ApnSetting.TYPE_SUPL_STRING,
            ApnSetting.TYPE_DUN_STRING,
            ApnSetting.TYPE_HIPRI_STRING,
            ApnSetting.TYPE_FOTA_STRING,
            ApnSetting.TYPE_IMS_STRING,
            ApnSetting.TYPE_CBS_STRING,
            ApnSetting.TYPE_IA_STRING,
            ApnSetting.TYPE_EMERGENCY_STRING,
            ApnSetting.TYPE_MCX_STRING,
            ApnSetting.TYPE_XCAP_STRING,
            ApnSetting.TYPE_VSIM_STRING,
            ApnSetting.TYPE_BIP_STRING,
            ApnSetting.TYPE_ENTERPRISE_STRING,
            ApnSetting.TYPE_OEM_PAID_STRING,
            ApnSetting.TYPE_OEM_PRIVATE_STRING,
        )

        val hasAllApnTypes = ApnTypes.hasAllApnTypes(apnTypes)

        assertThat(hasAllApnTypes).isTrue()
    }

    @Test
    fun hasAllApnTypes_allTypesExceptDefault() {
        val apnTypes = listOf(
            ApnSetting.TYPE_MMS_STRING,
            ApnSetting.TYPE_SUPL_STRING,
            ApnSetting.TYPE_DUN_STRING,
            ApnSetting.TYPE_HIPRI_STRING,
            ApnSetting.TYPE_FOTA_STRING,
            ApnSetting.TYPE_IMS_STRING,
            ApnSetting.TYPE_CBS_STRING,
            ApnSetting.TYPE_IA_STRING,
            ApnSetting.TYPE_EMERGENCY_STRING,
            ApnSetting.TYPE_MCX_STRING,
            ApnSetting.TYPE_XCAP_STRING,
            ApnSetting.TYPE_VSIM_STRING,
            ApnSetting.TYPE_BIP_STRING,
            ApnSetting.TYPE_ENTERPRISE_STRING,
            ApnSetting.TYPE_OEM_PAID_STRING,
            ApnSetting.TYPE_OEM_PRIVATE_STRING,
        )

        val hasAllApnTypes = ApnTypes.hasAllApnTypes(apnTypes)

        assertThat(hasAllApnTypes).isFalse()
    }

    private companion object {
        const val APN_TYPE = "type"
    }