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

Commit 99a0e88e authored by Yan Yan's avatar Yan Yan
Browse files

Support configuring capabilities in VCN cell network template

This commit adds the support of configuring required and forbidden
capabilities in the VCN cell underlying network matching template
so that a cell network MUST match the capability criteria to be
selected as the VCN's underlying network.

Bug: 245618320
Test: FrameworksVcnTests(new tests), CtsVcnTestCases
Change-Id: I3ed65ae86e0078fb5f0f6ab311fbc46f915ecdab
parent fbd9f328
Loading
Loading
Loading
Loading
+271 −4
Original line number Diff line number Diff line
@@ -15,6 +15,12 @@
 */
package android.net.vcn;

import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.getMatchCriteriaString;

@@ -37,10 +43,13 @@ import android.util.ArraySet;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.vcn.util.PersistableBundleUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

@@ -64,6 +73,23 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
    private static final int DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA = MATCH_ANY;
    private final int mOpportunisticMatchCriteria;

    private static final String CAPABILITIES_MATCH_CRITERIA_KEY = "mCapabilitiesMatchCriteria";
    @NonNull private final Map<Integer, Integer> mCapabilitiesMatchCriteria;

    private static final Map<Integer, Integer> CAPABILITIES_MATCH_CRITERIA_DEFAULT;

    static {
        Map<Integer, Integer> capsMatchCriteria = new HashMap<>();
        capsMatchCriteria.put(NET_CAPABILITY_CBS, MATCH_ANY);
        capsMatchCriteria.put(NET_CAPABILITY_DUN, MATCH_ANY);
        capsMatchCriteria.put(NET_CAPABILITY_IMS, MATCH_ANY);
        capsMatchCriteria.put(NET_CAPABILITY_INTERNET, MATCH_REQUIRED);
        capsMatchCriteria.put(NET_CAPABILITY_MMS, MATCH_ANY);
        capsMatchCriteria.put(NET_CAPABILITY_RCS, MATCH_ANY);

        CAPABILITIES_MATCH_CRITERIA_DEFAULT = Collections.unmodifiableMap(capsMatchCriteria);
    }

    private VcnCellUnderlyingNetworkTemplate(
            int meteredMatchCriteria,
            int minEntryUpstreamBandwidthKbps,
@@ -73,7 +99,8 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
            Set<String> allowedNetworkPlmnIds,
            Set<Integer> allowedSpecificCarrierIds,
            int roamingMatchCriteria,
            int opportunisticMatchCriteria) {
            int opportunisticMatchCriteria,
            Map<Integer, Integer> capabilitiesMatchCriteria) {
        super(
                NETWORK_PRIORITY_TYPE_CELL,
                meteredMatchCriteria,
@@ -85,6 +112,7 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
        mAllowedSpecificCarrierIds = new ArraySet<>(allowedSpecificCarrierIds);
        mRoamingMatchCriteria = roamingMatchCriteria;
        mOpportunisticMatchCriteria = opportunisticMatchCriteria;
        mCapabilitiesMatchCriteria = new HashMap<>(capabilitiesMatchCriteria);

        validate();
    }
@@ -94,6 +122,7 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
    protected void validate() {
        super.validate();
        validatePlmnIds(mAllowedNetworkPlmnIds);
        validateCapabilitiesMatchCriteria(mCapabilitiesMatchCriteria);
        Objects.requireNonNull(mAllowedSpecificCarrierIds, "matchingCarrierIds is null");
        validateMatchCriteria(mRoamingMatchCriteria, "mRoamingMatchCriteria");
        validateMatchCriteria(mOpportunisticMatchCriteria, "mOpportunisticMatchCriteria");
@@ -113,6 +142,28 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
        }
    }

    private static void validateCapabilitiesMatchCriteria(
            Map<Integer, Integer> capabilitiesMatchCriteria) {
        Objects.requireNonNull(capabilitiesMatchCriteria, "capabilitiesMatchCriteria is null");

        boolean requiredCapabilityFound = false;
        for (Map.Entry<Integer, Integer> entry : capabilitiesMatchCriteria.entrySet()) {
            final int capability = entry.getKey();
            final int matchCriteria = entry.getValue();

            Preconditions.checkArgument(
                    CAPABILITIES_MATCH_CRITERIA_DEFAULT.containsKey(capability),
                    "NetworkCapability " + capability + "out of range");
            validateMatchCriteria(matchCriteria, "capability " + capability);

            requiredCapabilityFound |= (matchCriteria == MATCH_REQUIRED);
        }

        if (!requiredCapabilityFound) {
            throw new IllegalArgumentException("No required capabilities found");
        }
    }

    /** @hide */
    @NonNull
    @VisibleForTesting(visibility = Visibility.PROTECTED)
@@ -146,6 +197,19 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
                        PersistableBundleUtils.toList(
                                specificCarrierIdsBundle, INTEGER_DESERIALIZER));

        final PersistableBundle capabilitiesMatchCriteriaBundle =
                in.getPersistableBundle(CAPABILITIES_MATCH_CRITERIA_KEY);
        final Map<Integer, Integer> capabilitiesMatchCriteria;
        if (capabilitiesMatchCriteriaBundle == null) {
            capabilitiesMatchCriteria = CAPABILITIES_MATCH_CRITERIA_DEFAULT;
        } else {
            capabilitiesMatchCriteria =
                    PersistableBundleUtils.toMap(
                            capabilitiesMatchCriteriaBundle,
                            INTEGER_DESERIALIZER,
                            INTEGER_DESERIALIZER);
        }

        final int roamingMatchCriteria = in.getInt(ROAMING_MATCH_KEY);
        final int opportunisticMatchCriteria = in.getInt(OPPORTUNISTIC_MATCH_KEY);

@@ -158,7 +222,8 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
                allowedNetworkPlmnIds,
                allowedSpecificCarrierIds,
                roamingMatchCriteria,
                opportunisticMatchCriteria);
                opportunisticMatchCriteria,
                capabilitiesMatchCriteria);
    }

    /** @hide */
@@ -178,6 +243,12 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
                        new ArrayList<>(mAllowedSpecificCarrierIds), INTEGER_SERIALIZER);
        result.putPersistableBundle(ALLOWED_SPECIFIC_CARRIER_IDS_KEY, specificCarrierIdsBundle);

        final PersistableBundle capabilitiesMatchCriteriaBundle =
                PersistableBundleUtils.fromMap(
                        mCapabilitiesMatchCriteria, INTEGER_SERIALIZER, INTEGER_SERIALIZER);
        result.putPersistableBundle(
                CAPABILITIES_MATCH_CRITERIA_KEY, capabilitiesMatchCriteriaBundle);

        result.putInt(ROAMING_MATCH_KEY, mRoamingMatchCriteria);
        result.putInt(OPPORTUNISTIC_MATCH_KEY, mOpportunisticMatchCriteria);

@@ -225,12 +296,76 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
        return mOpportunisticMatchCriteria;
    }

    /**
     * Returns the matching criteria for CBS networks.
     *
     * @see Builder#setCbs(int)
     * @hide
     */
    @MatchCriteria
    public int getCbs() {
        return mCapabilitiesMatchCriteria.get(NET_CAPABILITY_CBS);
    }

    /**
     * Returns the matching criteria for DUN networks.
     *
     * @see Builder#setDun(int)
     * @hide
     */
    @MatchCriteria
    public int getDun() {
        return mCapabilitiesMatchCriteria.get(NET_CAPABILITY_DUN);
    }
    /**
     * Returns the matching criteria for IMS networks.
     *
     * @see Builder#setIms(int)
     * @hide
     */
    @MatchCriteria
    public int getIms() {
        return mCapabilitiesMatchCriteria.get(NET_CAPABILITY_IMS);
    }
    /**
     * Returns the matching criteria for INTERNET networks.
     *
     * @see Builder#setInternet(int)
     * @hide
     */
    @MatchCriteria
    public int getInternet() {
        return mCapabilitiesMatchCriteria.get(NET_CAPABILITY_INTERNET);
    }
    /**
     * Returns the matching criteria for MMS networks.
     *
     * @see Builder#setMms(int)
     * @hide
     */
    @MatchCriteria
    public int getMms() {
        return mCapabilitiesMatchCriteria.get(NET_CAPABILITY_MMS);
    }

    /**
     * Returns the matching criteria for RCS networks.
     *
     * @see Builder#setRcs(int)
     * @hide
     */
    @MatchCriteria
    public int getRcs() {
        return mCapabilitiesMatchCriteria.get(NET_CAPABILITY_RCS);
    }

    @Override
    public int hashCode() {
        return Objects.hash(
                super.hashCode(),
                mAllowedNetworkPlmnIds,
                mAllowedSpecificCarrierIds,
                mCapabilitiesMatchCriteria,
                mRoamingMatchCriteria,
                mOpportunisticMatchCriteria);
    }
@@ -248,6 +383,7 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
        final VcnCellUnderlyingNetworkTemplate rhs = (VcnCellUnderlyingNetworkTemplate) other;
        return Objects.equals(mAllowedNetworkPlmnIds, rhs.mAllowedNetworkPlmnIds)
                && Objects.equals(mAllowedSpecificCarrierIds, rhs.mAllowedSpecificCarrierIds)
                && Objects.equals(mCapabilitiesMatchCriteria, rhs.mCapabilitiesMatchCriteria)
                && mRoamingMatchCriteria == rhs.mRoamingMatchCriteria
                && mOpportunisticMatchCriteria == rhs.mOpportunisticMatchCriteria;
    }
@@ -261,6 +397,7 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
        if (!mAllowedNetworkPlmnIds.isEmpty()) {
            pw.println("mAllowedSpecificCarrierIds: " + mAllowedSpecificCarrierIds);
        }
        pw.println("mCapabilitiesMatchCriteria: " + mCapabilitiesMatchCriteria);
        if (mRoamingMatchCriteria != DEFAULT_ROAMING_MATCH_CRITERIA) {
            pw.println("mRoamingMatchCriteria: " + getMatchCriteriaString(mRoamingMatchCriteria));
        }
@@ -277,6 +414,7 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork

        @NonNull private final Set<String> mAllowedNetworkPlmnIds = new ArraySet<>();
        @NonNull private final Set<Integer> mAllowedSpecificCarrierIds = new ArraySet<>();
        @NonNull private final Map<Integer, Integer> mCapabilitiesMatchCriteria = new HashMap<>();

        private int mRoamingMatchCriteria = DEFAULT_ROAMING_MATCH_CRITERIA;
        private int mOpportunisticMatchCriteria = DEFAULT_OPPORTUNISTIC_MATCH_CRITERIA;
@@ -287,7 +425,9 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
        private int mMinExitDownstreamBandwidthKbps = DEFAULT_MIN_BANDWIDTH_KBPS;

        /** Construct a Builder object. */
        public Builder() {}
        public Builder() {
            mCapabilitiesMatchCriteria.putAll(CAPABILITIES_MATCH_CRITERIA_DEFAULT);
        }

        /**
         * Set the matching criteria for metered networks.
@@ -461,6 +601,132 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
            return this;
        }

        /**
         * Sets the matching criteria for CBS networks.
         *
         * <p>A template where {@code setCbs(MATCH_REQUIRED)} is called will only match CBS networks
         * (ones with NET_CAPABILITY_CBS). A template where {@code setCbs(MATCH_FORBIDDEN)} is
         * called will only match networks that do not support CBS (ones without
         * NET_CAPABILITY_CBS).
         *
         * @param matchCriteria the matching criteria for CBS networks. Defaults to {@link
         *     #MATCH_ANY}.
         * @see NetworkCapabilities#NET_CAPABILITY_CBS
         * @hide
         */
        @NonNull
        public Builder setCbs(@MatchCriteria int matchCriteria) {
            validateMatchCriteria(matchCriteria, "setCbs");

            mCapabilitiesMatchCriteria.put(NET_CAPABILITY_CBS, matchCriteria);
            return this;
        }

        /**
         * Sets the matching criteria for DUN networks.
         *
         * <p>A template where {@code setDun(MATCH_REQUIRED)} is called will only match DUN networks
         * (ones with NET_CAPABILITY_DUN). A template where {@code setDun(MATCH_FORBIDDEN)} is
         * called will only match networks that do not support DUN (ones without
         * NET_CAPABILITY_DUN).
         *
         * @param matchCriteria the matching criteria for DUN networks. Defaults to {@link
         *     #MATCH_ANY}.
         * @see NetworkCapabilities#NET_CAPABILITY_DUN
         * @hide
         */
        @NonNull
        public Builder setDun(@MatchCriteria int matchCriteria) {
            validateMatchCriteria(matchCriteria, "setDun");

            mCapabilitiesMatchCriteria.put(NET_CAPABILITY_DUN, matchCriteria);
            return this;
        }

        /**
         * Sets the matching criteria for IMS networks.
         *
         * <p>A template where {@code setIms(MATCH_REQUIRED)} is called will only match IMS networks
         * (ones with NET_CAPABILITY_IMS). A template where {@code setIms(MATCH_FORBIDDEN)} is
         * called will only match networks that do not support IMS (ones without
         * NET_CAPABILITY_IMS).
         *
         * @param matchCriteria the matching criteria for IMS networks. Defaults to {@link
         *     #MATCH_ANY}.
         * @see NetworkCapabilities#NET_CAPABILITY_IMS
         * @hide
         */
        @NonNull
        public Builder setIms(@MatchCriteria int matchCriteria) {
            validateMatchCriteria(matchCriteria, "setIms");

            mCapabilitiesMatchCriteria.put(NET_CAPABILITY_IMS, matchCriteria);
            return this;
        }

        /**
         * Sets the matching criteria for INTERNET networks.
         *
         * <p>A template where {@code setInternet(MATCH_REQUIRED)} is called will only match
         * INTERNET networks (ones with NET_CAPABILITY_INTERNET). A template where {@code
         * setInternet(MATCH_FORBIDDEN)} is called will only match networks that do not support
         * INTERNET (ones without NET_CAPABILITY_INTERNET).
         *
         * @param matchCriteria the matching criteria for INTERNET networks. Defaults to {@link
         *     #MATCH_REQUIRED}.
         * @see NetworkCapabilities#NET_CAPABILITY_INTERNET
         * @hide
         */
        @NonNull
        public Builder setInternet(@MatchCriteria int matchCriteria) {
            validateMatchCriteria(matchCriteria, "setInternet");

            mCapabilitiesMatchCriteria.put(NET_CAPABILITY_INTERNET, matchCriteria);
            return this;
        }

        /**
         * Sets the matching criteria for MMS networks.
         *
         * <p>A template where {@code setMms(MATCH_REQUIRED)} is called will only match MMS networks
         * (ones with NET_CAPABILITY_MMS). A template where {@code setMms(MATCH_FORBIDDEN)} is
         * called will only match networks that do not support MMS (ones without
         * NET_CAPABILITY_MMS).
         *
         * @param matchCriteria the matching criteria for MMS networks. Defaults to {@link
         *     #MATCH_ANY}.
         * @see NetworkCapabilities#NET_CAPABILITY_MMS
         * @hide
         */
        @NonNull
        public Builder setMms(@MatchCriteria int matchCriteria) {
            validateMatchCriteria(matchCriteria, "setMms");

            mCapabilitiesMatchCriteria.put(NET_CAPABILITY_MMS, matchCriteria);
            return this;
        }

        /**
         * Sets the matching criteria for RCS networks.
         *
         * <p>A template where {@code setRcs(MATCH_REQUIRED)} is called will only match RCS networks
         * (ones with NET_CAPABILITY_RCS). A template where {@code setRcs(MATCH_FORBIDDEN)} is
         * called will only match networks that do not support RCS (ones without
         * NET_CAPABILITY_RCS).
         *
         * @param matchCriteria the matching criteria for RCS networks. Defaults to {@link
         *     #MATCH_ANY}.
         * @see NetworkCapabilities#NET_CAPABILITY_RCS
         * @hide
         */
        @NonNull
        public Builder setRcs(@MatchCriteria int matchCriteria) {
            validateMatchCriteria(matchCriteria, "setRcs");

            mCapabilitiesMatchCriteria.put(NET_CAPABILITY_RCS, matchCriteria);
            return this;
        }

        /** Build the VcnCellUnderlyingNetworkTemplate. */
        @NonNull
        public VcnCellUnderlyingNetworkTemplate build() {
@@ -473,7 +739,8 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
                    mAllowedNetworkPlmnIds,
                    mAllowedSpecificCarrierIds,
                    mRoamingMatchCriteria,
                    mOpportunisticMatchCriteria);
                    mOpportunisticMatchCriteria,
                    mCapabilitiesMatchCriteria);
        }
    }
}
+71 −5
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.fail;

import org.junit.Test;
@@ -31,8 +32,7 @@ public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTe
    private static final Set<String> ALLOWED_PLMN_IDS = new HashSet<>();
    private static final Set<Integer> ALLOWED_CARRIER_IDS = new HashSet<>();

    // Package private for use in VcnGatewayConnectionConfigTest
    static VcnCellUnderlyingNetworkTemplate getTestNetworkTemplate() {
    private static VcnCellUnderlyingNetworkTemplate.Builder getTestNetworkTemplateBuilder() {
        return new VcnCellUnderlyingNetworkTemplate.Builder()
                .setMetered(MATCH_FORBIDDEN)
                .setMinUpstreamBandwidthKbps(
@@ -44,13 +44,44 @@ public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTe
                .setOperatorPlmnIds(ALLOWED_PLMN_IDS)
                .setSimSpecificCarrierIds(ALLOWED_CARRIER_IDS)
                .setRoaming(MATCH_FORBIDDEN)
                .setOpportunistic(MATCH_REQUIRED)
                .build();
                .setOpportunistic(MATCH_REQUIRED);
    }

    // Package private for use in VcnGatewayConnectionConfigTest
    static VcnCellUnderlyingNetworkTemplate getTestNetworkTemplate() {
        return getTestNetworkTemplateBuilder().build();
    }

    private void setAllCapabilities(
            VcnCellUnderlyingNetworkTemplate.Builder builder, int matchCriteria) {
        builder.setCbs(matchCriteria);
        builder.setDun(matchCriteria);
        builder.setIms(matchCriteria);
        builder.setInternet(matchCriteria);
        builder.setMms(matchCriteria);
        builder.setRcs(matchCriteria);
    }

    private void verifyAllCapabilities(
            VcnCellUnderlyingNetworkTemplate template,
            int expectMatchCriteriaforNonInternet,
            int expectMatchCriteriaforInternet) {
        assertEquals(expectMatchCriteriaforNonInternet, template.getCbs());
        assertEquals(expectMatchCriteriaforNonInternet, template.getDun());
        assertEquals(expectMatchCriteriaforNonInternet, template.getIms());
        assertEquals(expectMatchCriteriaforNonInternet, template.getMms());
        assertEquals(expectMatchCriteriaforNonInternet, template.getRcs());

        assertEquals(expectMatchCriteriaforInternet, template.getInternet());
    }

    @Test
    public void testBuilderAndGetters() {
        final VcnCellUnderlyingNetworkTemplate networkPriority = getTestNetworkTemplate();
        final VcnCellUnderlyingNetworkTemplate.Builder builder = getTestNetworkTemplateBuilder();
        setAllCapabilities(builder, MATCH_REQUIRED);

        final VcnCellUnderlyingNetworkTemplate networkPriority = builder.build();

        assertEquals(MATCH_FORBIDDEN, networkPriority.getMetered());
        assertEquals(
                TEST_MIN_ENTRY_UPSTREAM_BANDWIDTH_KBPS,
@@ -68,6 +99,8 @@ public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTe
        assertEquals(ALLOWED_CARRIER_IDS, networkPriority.getSimSpecificCarrierIds());
        assertEquals(MATCH_FORBIDDEN, networkPriority.getRoaming());
        assertEquals(MATCH_REQUIRED, networkPriority.getOpportunistic());

        verifyAllCapabilities(networkPriority, MATCH_REQUIRED, MATCH_REQUIRED);
    }

    @Test
@@ -86,6 +119,8 @@ public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTe
        assertEquals(new HashSet<Integer>(), networkPriority.getSimSpecificCarrierIds());
        assertEquals(MATCH_ANY, networkPriority.getRoaming());
        assertEquals(MATCH_ANY, networkPriority.getOpportunistic());

        verifyAllCapabilities(networkPriority, MATCH_ANY, MATCH_REQUIRED);
    }

    @Test
@@ -111,6 +146,25 @@ public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTe
        }
    }

    @Test
    public void testBuildFailWithoutRequiredCapabilities() {
        try {
            new VcnCellUnderlyingNetworkTemplate.Builder().setInternet(MATCH_ANY).build();

            fail("Expected IAE for missing required capabilities");
        } catch (IllegalArgumentException expected) {
        }
    }

    @Test
    public void testEqualsWithDifferentCapabilities() {
        final VcnCellUnderlyingNetworkTemplate left =
                new VcnCellUnderlyingNetworkTemplate.Builder().setDun(MATCH_REQUIRED).build();
        final VcnCellUnderlyingNetworkTemplate right =
                new VcnCellUnderlyingNetworkTemplate.Builder().setMms(MATCH_REQUIRED).build();
        assertNotEquals(left, right);
    }

    @Test
    public void testPersistableBundle() {
        final VcnCellUnderlyingNetworkTemplate networkPriority = getTestNetworkTemplate();
@@ -119,4 +173,16 @@ public class VcnCellUnderlyingNetworkTemplateTest extends VcnUnderlyingNetworkTe
                VcnUnderlyingNetworkTemplate.fromPersistableBundle(
                        networkPriority.toPersistableBundle()));
    }

    @Test
    public void testPersistableBundleWithCapabilities() {
        final VcnCellUnderlyingNetworkTemplate.Builder builder = getTestNetworkTemplateBuilder();
        setAllCapabilities(builder, MATCH_REQUIRED);

        final VcnCellUnderlyingNetworkTemplate networkPriority = builder.build();
        assertEquals(
                networkPriority,
                VcnUnderlyingNetworkTemplate.fromPersistableBundle(
                        networkPriority.toPersistableBundle()));
    }
}