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

Commit 88d3ad7f authored by Yan Yan's avatar Yan Yan Committed by Automerger Merge Worker
Browse files

Merge changes I5cd2982f,Ia7f44c5f am: 8d6d8dcc am: 0ec02691

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1902413

Change-Id: Iecc6f5557814fd635416a74e716e26571237e2f9
parents e28d4fcc 0ec02691
Loading
Loading
Loading
Loading
+291 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 android.net.vcn;

import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_DESERIALIZER;
import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_SERIALIZER;
import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER;
import static com.android.server.vcn.util.PersistableBundleUtils.STRING_SERIALIZER;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.PersistableBundle;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.util.ArraySet;

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

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

// TODO: Add documents
/** @hide */
public final class VcnCellUnderlyingNetworkPriority extends VcnUnderlyingNetworkPriority {
    private static final String ALLOWED_NETWORK_PLMN_IDS_KEY = "mAllowedNetworkPlmnIds";
    @NonNull private final Set<String> mAllowedNetworkPlmnIds;
    private static final String ALLOWED_SPECIFIC_CARRIER_IDS_KEY = "mAllowedSpecificCarrierIds";
    @NonNull private final Set<Integer> mAllowedSpecificCarrierIds;

    private static final String ALLOW_ROAMING_KEY = "mAllowRoaming";
    private final boolean mAllowRoaming;

    private static final String REQUIRE_OPPORTUNISTIC_KEY = "mRequireOpportunistic";
    private final boolean mRequireOpportunistic;

    private VcnCellUnderlyingNetworkPriority(
            int networkQuality,
            boolean allowMetered,
            Set<String> allowedNetworkPlmnIds,
            Set<Integer> allowedSpecificCarrierIds,
            boolean allowRoaming,
            boolean requireOpportunistic) {
        super(NETWORK_PRIORITY_TYPE_CELL, networkQuality, allowMetered);
        mAllowedNetworkPlmnIds = new ArraySet<>(allowedNetworkPlmnIds);
        mAllowedSpecificCarrierIds = new ArraySet<>(allowedSpecificCarrierIds);
        mAllowRoaming = allowRoaming;
        mRequireOpportunistic = requireOpportunistic;

        validate();
    }

    /** @hide */
    @Override
    protected void validate() {
        super.validate();
        validatePlmnIds(mAllowedNetworkPlmnIds);
        Objects.requireNonNull(mAllowedSpecificCarrierIds, "allowedCarrierIds is null");
    }

    private static void validatePlmnIds(Set<String> allowedNetworkPlmnIds) {
        Objects.requireNonNull(allowedNetworkPlmnIds, "allowedNetworkPlmnIds is null");

        // A valid PLMN is a concatenation of MNC and MCC, and thus consists of 5 or 6 decimal
        // digits.
        for (String id : allowedNetworkPlmnIds) {
            if ((id.length() == 5 || id.length() == 6) && id.matches("[0-9]+")) {
                continue;
            } else {
                throw new IllegalArgumentException("Found invalid PLMN ID: " + id);
            }
        }
    }

    /** @hide */
    @NonNull
    @VisibleForTesting(visibility = Visibility.PROTECTED)
    public static VcnCellUnderlyingNetworkPriority fromPersistableBundle(
            @NonNull PersistableBundle in) {
        Objects.requireNonNull(in, "PersistableBundle is null");

        final int networkQuality = in.getInt(NETWORK_QUALITY_KEY);
        final boolean allowMetered = in.getBoolean(ALLOW_METERED_KEY);

        final PersistableBundle plmnIdsBundle =
                in.getPersistableBundle(ALLOWED_NETWORK_PLMN_IDS_KEY);
        Objects.requireNonNull(plmnIdsBundle, "plmnIdsBundle is null");
        final Set<String> allowedNetworkPlmnIds =
                new ArraySet<String>(
                        PersistableBundleUtils.toList(plmnIdsBundle, STRING_DESERIALIZER));

        final PersistableBundle specificCarrierIdsBundle =
                in.getPersistableBundle(ALLOWED_SPECIFIC_CARRIER_IDS_KEY);
        Objects.requireNonNull(specificCarrierIdsBundle, "specificCarrierIdsBundle is null");
        final Set<Integer> allowedSpecificCarrierIds =
                new ArraySet<Integer>(
                        PersistableBundleUtils.toList(
                                specificCarrierIdsBundle, INTEGER_DESERIALIZER));

        final boolean allowRoaming = in.getBoolean(ALLOW_ROAMING_KEY);
        final boolean requireOpportunistic = in.getBoolean(REQUIRE_OPPORTUNISTIC_KEY);

        return new VcnCellUnderlyingNetworkPriority(
                networkQuality,
                allowMetered,
                allowedNetworkPlmnIds,
                allowedSpecificCarrierIds,
                allowRoaming,
                requireOpportunistic);
    }

    /** @hide */
    @Override
    @NonNull
    @VisibleForTesting(visibility = Visibility.PROTECTED)
    public PersistableBundle toPersistableBundle() {
        final PersistableBundle result = super.toPersistableBundle();

        final PersistableBundle plmnIdsBundle =
                PersistableBundleUtils.fromList(
                        new ArrayList<>(mAllowedNetworkPlmnIds), STRING_SERIALIZER);
        result.putPersistableBundle(ALLOWED_NETWORK_PLMN_IDS_KEY, plmnIdsBundle);

        final PersistableBundle specificCarrierIdsBundle =
                PersistableBundleUtils.fromList(
                        new ArrayList<>(mAllowedSpecificCarrierIds), INTEGER_SERIALIZER);
        result.putPersistableBundle(ALLOWED_SPECIFIC_CARRIER_IDS_KEY, specificCarrierIdsBundle);

        result.putBoolean(ALLOW_ROAMING_KEY, mAllowRoaming);
        result.putBoolean(REQUIRE_OPPORTUNISTIC_KEY, mRequireOpportunistic);

        return result;
    }

    /** Retrieve the allowed PLMN IDs, or an empty set if any PLMN ID is acceptable. */
    @NonNull
    public Set<String> getAllowedPlmnIds() {
        return Collections.unmodifiableSet(mAllowedNetworkPlmnIds);
    }

    /**
     * Retrieve the allowed specific carrier IDs, or an empty set if any specific carrier ID is
     * acceptable.
     */
    @NonNull
    public Set<Integer> getAllowedSpecificCarrierIds() {
        return Collections.unmodifiableSet(mAllowedSpecificCarrierIds);
    }

    /** Return if roaming is allowed. */
    public boolean allowRoaming() {
        return mAllowRoaming;
    }

    /** Return if requiring an opportunistic network. */
    public boolean requireOpportunistic() {
        return mRequireOpportunistic;
    }

    @Override
    public int hashCode() {
        return Objects.hash(
                super.hashCode(),
                mAllowedNetworkPlmnIds,
                mAllowedSpecificCarrierIds,
                mAllowRoaming,
                mRequireOpportunistic);
    }

    @Override
    public boolean equals(@Nullable Object other) {
        if (!super.equals(other)) {
            return false;
        }

        if (!(other instanceof VcnCellUnderlyingNetworkPriority)) {
            return false;
        }

        final VcnCellUnderlyingNetworkPriority rhs = (VcnCellUnderlyingNetworkPriority) other;
        return Objects.equals(mAllowedNetworkPlmnIds, rhs.mAllowedNetworkPlmnIds)
                && Objects.equals(mAllowedSpecificCarrierIds, rhs.mAllowedSpecificCarrierIds)
                && mAllowRoaming == rhs.mAllowRoaming
                && mRequireOpportunistic == rhs.mRequireOpportunistic;
    }

    /** This class is used to incrementally build WifiNetworkPriority objects. */
    public static class Builder extends VcnUnderlyingNetworkPriority.Builder<Builder> {
        @NonNull private final Set<String> mAllowedNetworkPlmnIds = new ArraySet<>();
        @NonNull private final Set<Integer> mAllowedSpecificCarrierIds = new ArraySet<>();

        private boolean mAllowRoaming = false;
        private boolean mRequireOpportunistic = false;

        /** Construct a Builder object. */
        public Builder() {}

        /**
         * Set allowed operator PLMN IDs.
         *
         * <p>This is used to distinguish cases where roaming agreements may dictate a different
         * priority from a partner's networks.
         *
         * @param allowedNetworkPlmnIds the allowed operator PLMN IDs in String. Defaults to an
         *     empty set, allowing ANY PLMN ID. A valid PLMN is a concatenation of MNC and MCC, and
         *     thus consists of 5 or 6 decimal digits. See {@link SubscriptionInfo#getMccString()}
         *     and {@link SubscriptionInfo#getMncString()}.
         */
        @NonNull
        public Builder setAllowedPlmnIds(@NonNull Set<String> allowedNetworkPlmnIds) {
            validatePlmnIds(allowedNetworkPlmnIds);

            mAllowedNetworkPlmnIds.clear();
            mAllowedNetworkPlmnIds.addAll(allowedNetworkPlmnIds);
            return this;
        }

        /**
         * Set allowed specific carrier IDs.
         *
         * @param allowedSpecificCarrierIds the allowed specific carrier IDs. Defaults to an empty
         *     set, allowing ANY carrier ID. See {@link TelephonyManager#getSimSpecificCarrierId()}.
         */
        @NonNull
        public Builder setAllowedSpecificCarrierIds(
                @NonNull Set<Integer> allowedSpecificCarrierIds) {
            Objects.requireNonNull(allowedSpecificCarrierIds, "allowedCarrierIds is null");
            mAllowedSpecificCarrierIds.clear();
            mAllowedSpecificCarrierIds.addAll(allowedSpecificCarrierIds);
            return this;
        }

        /**
         * Set if roaming is allowed.
         *
         * @param allowRoaming the flag to indicate if roaming is allowed. Defaults to {@code
         *     false}.
         */
        @NonNull
        public Builder setAllowRoaming(boolean allowRoaming) {
            mAllowRoaming = allowRoaming;
            return this;
        }

        /**
         * Set if requiring an opportunistic network.
         *
         * @param requireOpportunistic the flag to indicate if caller requires an opportunistic
         *     network. Defaults to {@code false}.
         */
        @NonNull
        public Builder setRequireOpportunistic(boolean requireOpportunistic) {
            mRequireOpportunistic = requireOpportunistic;
            return this;
        }

        /** Build the VcnCellUnderlyingNetworkPriority. */
        @NonNull
        public VcnCellUnderlyingNetworkPriority build() {
            return new VcnCellUnderlyingNetworkPriority(
                    mNetworkQuality,
                    mAllowMetered,
                    mAllowedNetworkPlmnIds,
                    mAllowedSpecificCarrierIds,
                    mAllowRoaming,
                    mRequireOpportunistic);
        }

        /** @hide */
        @Override
        Builder self() {
            return this;
        }
    }
}
+97 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package android.net.vcn;

import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
import static android.net.vcn.VcnUnderlyingNetworkPriority.NETWORK_QUALITY_OK;

import static com.android.internal.annotations.VisibleForTesting.Visibility;

@@ -41,6 +42,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
@@ -157,6 +159,34 @@ public final class VcnGatewayConnectionConfig {
                TimeUnit.MINUTES.toMillis(5),
                TimeUnit.MINUTES.toMillis(15)
            };

    private static final LinkedHashSet<VcnUnderlyingNetworkPriority>
            DEFAULT_UNDERLYING_NETWORK_PRIORITIES = new LinkedHashSet<>();

    static {
        DEFAULT_UNDERLYING_NETWORK_PRIORITIES.add(
                new VcnCellUnderlyingNetworkPriority.Builder()
                        .setNetworkQuality(NETWORK_QUALITY_OK)
                        .setAllowMetered(true /* allowMetered */)
                        .setAllowRoaming(true /* allowRoaming */)
                        .setRequireOpportunistic(true /* requireOpportunistic */)
                        .build());

        DEFAULT_UNDERLYING_NETWORK_PRIORITIES.add(
                new VcnWifiUnderlyingNetworkPriority.Builder()
                        .setNetworkQuality(NETWORK_QUALITY_OK)
                        .setAllowMetered(true /* allowMetered */)
                        .build());

        DEFAULT_UNDERLYING_NETWORK_PRIORITIES.add(
                new VcnCellUnderlyingNetworkPriority.Builder()
                        .setNetworkQuality(NETWORK_QUALITY_OK)
                        .setAllowMetered(true /* allowMetered */)
                        .setAllowRoaming(true /* allowRoaming */)
                        .setRequireOpportunistic(false /* requireOpportunistic */)
                        .build());
    }

    private static final String GATEWAY_CONNECTION_NAME_KEY = "mGatewayConnectionName";
    @NonNull private final String mGatewayConnectionName;

@@ -166,6 +196,9 @@ public final class VcnGatewayConnectionConfig {
    private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities";
    @NonNull private final SortedSet<Integer> mExposedCapabilities;

    private static final String UNDERLYING_NETWORK_PRIORITIES_KEY = "mUnderlyingNetworkPriorities";
    @NonNull private final LinkedHashSet<VcnUnderlyingNetworkPriority> mUnderlyingNetworkPriorities;

    private static final String MAX_MTU_KEY = "mMaxMtu";
    private final int mMaxMtu;

@@ -177,6 +210,7 @@ public final class VcnGatewayConnectionConfig {
            @NonNull String gatewayConnectionName,
            @NonNull IkeTunnelConnectionParams tunnelConnectionParams,
            @NonNull Set<Integer> exposedCapabilities,
            @NonNull LinkedHashSet<VcnUnderlyingNetworkPriority> underlyingNetworkPriorities,
            @NonNull long[] retryIntervalsMs,
            @IntRange(from = MIN_MTU_V6) int maxMtu) {
        mGatewayConnectionName = gatewayConnectionName;
@@ -185,6 +219,11 @@ public final class VcnGatewayConnectionConfig {
        mRetryIntervalsMs = retryIntervalsMs;
        mMaxMtu = maxMtu;

        mUnderlyingNetworkPriorities = new LinkedHashSet<>(underlyingNetworkPriorities);
        if (mUnderlyingNetworkPriorities.isEmpty()) {
            mUnderlyingNetworkPriorities.addAll(DEFAULT_UNDERLYING_NETWORK_PRIORITIES);
        }

        validate();
    }

@@ -198,12 +237,19 @@ public final class VcnGatewayConnectionConfig {

        final PersistableBundle exposedCapsBundle =
                in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY);
        final PersistableBundle networkPrioritiesBundle =
                in.getPersistableBundle(UNDERLYING_NETWORK_PRIORITIES_KEY);

        mGatewayConnectionName = in.getString(GATEWAY_CONNECTION_NAME_KEY);
        mTunnelConnectionParams =
                TunnelConnectionParamsUtils.fromPersistableBundle(tunnelConnectionParamsBundle);
        mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList(
                exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
        mUnderlyingNetworkPriorities =
                new LinkedHashSet<>(
                        PersistableBundleUtils.toList(
                                networkPrioritiesBundle,
                                VcnUnderlyingNetworkPriority::fromPersistableBundle));
        mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY);
        mMaxMtu = in.getInt(MAX_MTU_KEY);

@@ -221,6 +267,7 @@ public final class VcnGatewayConnectionConfig {
            checkValidCapability(cap);
        }

        Objects.requireNonNull(mUnderlyingNetworkPriorities, "underlyingNetworkPriorities is null");
        Objects.requireNonNull(mRetryIntervalsMs, "retryIntervalsMs was null");
        validateRetryInterval(mRetryIntervalsMs);

@@ -302,6 +349,18 @@ public final class VcnGatewayConnectionConfig {
        return Collections.unmodifiableSet(mExposedCapabilities);
    }

    /**
     * Retrieve the configured VcnUnderlyingNetworkPriority list, or a default list if it is not
     * configured.
     *
     * @see Builder#setVcnUnderlyingNetworkPriorities(LinkedHashSet<VcnUnderlyingNetworkPriority>)
     * @hide
     */
    @NonNull
    public LinkedHashSet<VcnUnderlyingNetworkPriority> getVcnUnderlyingNetworkPriorities() {
        return new LinkedHashSet<>(mUnderlyingNetworkPriorities);
    }

    /**
     * Retrieves the configured retry intervals.
     *
@@ -338,10 +397,15 @@ public final class VcnGatewayConnectionConfig {
                PersistableBundleUtils.fromList(
                        new ArrayList<>(mExposedCapabilities),
                        PersistableBundleUtils.INTEGER_SERIALIZER);
        final PersistableBundle networkPrioritiesBundle =
                PersistableBundleUtils.fromList(
                        new ArrayList<>(mUnderlyingNetworkPriorities),
                        VcnUnderlyingNetworkPriority::toPersistableBundle);

        result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName);
        result.putPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY, tunnelConnectionParamsBundle);
        result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
        result.putPersistableBundle(UNDERLYING_NETWORK_PRIORITIES_KEY, networkPrioritiesBundle);
        result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs);
        result.putInt(MAX_MTU_KEY, mMaxMtu);

@@ -379,6 +443,11 @@ public final class VcnGatewayConnectionConfig {
        @NonNull private final String mGatewayConnectionName;
        @NonNull private final IkeTunnelConnectionParams mTunnelConnectionParams;
        @NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();

        @NonNull
        private final LinkedHashSet<VcnUnderlyingNetworkPriority> mUnderlyingNetworkPriorities =
                new LinkedHashSet<>(DEFAULT_UNDERLYING_NETWORK_PRIORITIES);

        @NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
        private int mMaxMtu = DEFAULT_MAX_MTU;

@@ -449,6 +518,33 @@ public final class VcnGatewayConnectionConfig {
            return this;
        }

        /**
         * Set the VcnUnderlyingNetworkPriority list.
         *
         * @param underlyingNetworkPriorities a list of unique VcnUnderlyingNetworkPriorities that
         *     are ordered from most to least preferred, or an empty list to use the default
         *     prioritization. The default network prioritization is Opportunistic cellular, Carrier
         *     WiFi and Macro cellular
         * @return
         */
        /** @hide */
        @NonNull
        public Builder setVcnUnderlyingNetworkPriorities(
                @NonNull LinkedHashSet<VcnUnderlyingNetworkPriority> underlyingNetworkPriorities) {
            Objects.requireNonNull(
                    mUnderlyingNetworkPriorities, "underlyingNetworkPriorities is null");

            mUnderlyingNetworkPriorities.clear();

            if (underlyingNetworkPriorities.isEmpty()) {
                mUnderlyingNetworkPriorities.addAll(DEFAULT_UNDERLYING_NETWORK_PRIORITIES);
            } else {
                mUnderlyingNetworkPriorities.addAll(underlyingNetworkPriorities);
            }

            return this;
        }

        /**
         * Set the retry interval between VCN establishment attempts upon successive failures.
         *
@@ -513,6 +609,7 @@ public final class VcnGatewayConnectionConfig {
                    mGatewayConnectionName,
                    mTunnelConnectionParams,
                    mExposedCapabilities,
                    mUnderlyingNetworkPriorities,
                    mRetryIntervalsMs,
                    mMaxMtu);
        }
+1 −1
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ public abstract class VcnUnderlyingNetworkPriority {
            case NETWORK_PRIORITY_TYPE_WIFI:
                return VcnWifiUnderlyingNetworkPriority.fromPersistableBundle(in);
            case NETWORK_PRIORITY_TYPE_CELL:
                throw new UnsupportedOperationException("Not implemented");
                return VcnCellUnderlyingNetworkPriority.fromPersistableBundle(in);
            default:
                throw new IllegalArgumentException(
                        "Invalid networkPriorityType:" + networkPriorityType);
+16 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ public class PersistableBundleUtils {
    private static final String PARCEL_UUID_KEY = "PARCEL_UUID";
    private static final String BYTE_ARRAY_KEY = "BYTE_ARRAY_KEY";
    private static final String INTEGER_KEY = "INTEGER_KEY";
    private static final String STRING_KEY = "STRING_KEY";

    /**
     * Functional interface to convert an object of the specified type to a PersistableBundle.
@@ -91,6 +92,21 @@ public class PersistableBundleUtils {
                return bundle.getInt(INTEGER_KEY);
            };

    /** Serializer to convert s String to a PersistableBundle. */
    public static final Serializer<String> STRING_SERIALIZER =
            (i) -> {
                final PersistableBundle result = new PersistableBundle();
                result.putString(STRING_KEY, i);
                return result;
            };

    /** Deserializer to convert a PersistableBundle to a String. */
    public static final Deserializer<String> STRING_DESERIALIZER =
            (bundle) -> {
                Objects.requireNonNull(bundle, "PersistableBundle is null");
                return bundle.getString(STRING_KEY);
            };

    /**
     * Converts a ParcelUuid to a PersistableBundle.
     *
+77 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 android.net.vcn;

import static android.net.vcn.VcnUnderlyingNetworkPriority.NETWORK_QUALITY_ANY;
import static android.net.vcn.VcnUnderlyingNetworkPriority.NETWORK_QUALITY_OK;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

import java.util.HashSet;
import java.util.Set;

public class VcnCellUnderlyingNetworkPriorityTest {
    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 VcnCellUnderlyingNetworkPriority getTestNetworkPriority() {
        return new VcnCellUnderlyingNetworkPriority.Builder()
                .setNetworkQuality(NETWORK_QUALITY_OK)
                .setAllowMetered(true /* allowMetered */)
                .setAllowedPlmnIds(ALLOWED_PLMN_IDS)
                .setAllowedSpecificCarrierIds(ALLOWED_CARRIER_IDS)
                .setAllowRoaming(true /* allowRoaming */)
                .setRequireOpportunistic(true /* requireOpportunistic */)
                .build();
    }

    @Test
    public void testBuilderAndGetters() {
        final VcnCellUnderlyingNetworkPriority networkPriority = getTestNetworkPriority();
        assertEquals(NETWORK_QUALITY_OK, networkPriority.getNetworkQuality());
        assertTrue(networkPriority.allowMetered());
        assertEquals(ALLOWED_PLMN_IDS, networkPriority.getAllowedPlmnIds());
        assertEquals(ALLOWED_CARRIER_IDS, networkPriority.getAllowedSpecificCarrierIds());
        assertTrue(networkPriority.allowRoaming());
        assertTrue(networkPriority.requireOpportunistic());
    }

    @Test
    public void testBuilderAndGettersForDefaultValues() {
        final VcnCellUnderlyingNetworkPriority networkPriority =
                new VcnCellUnderlyingNetworkPriority.Builder().build();
        assertEquals(NETWORK_QUALITY_ANY, networkPriority.getNetworkQuality());
        assertFalse(networkPriority.allowMetered());
        assertEquals(new HashSet<String>(), networkPriority.getAllowedPlmnIds());
        assertEquals(new HashSet<Integer>(), networkPriority.getAllowedSpecificCarrierIds());
        assertFalse(networkPriority.allowRoaming());
        assertFalse(networkPriority.requireOpportunistic());
    }

    @Test
    public void testPersistableBundle() {
        final VcnCellUnderlyingNetworkPriority networkPriority = getTestNetworkPriority();
        assertEquals(
                networkPriority,
                VcnUnderlyingNetworkPriority.fromPersistableBundle(
                        networkPriority.toPersistableBundle()));
    }
}
Loading