diff options
| author | 2017-01-25 02:11:10 +0000 | |
|---|---|---|
| committer | 2017-01-25 02:11:10 +0000 | |
| commit | 6570ce6c807f74a9c2fa32c353be3563c20f1728 (patch) | |
| tree | 0473477e227d6aae2f2bd92674ff391fa520646d | |
| parent | 3a13bb43f6c9896eb7f8c64c59b2c76de4dbf4bd (diff) | |
| parent | 28c7afe5787790af3e3ca4dba8ab79f8751ee6ec (diff) | |
Merge "hotspot2: add support for complete HomeSP subtree"
am: 28c7afe578
Change-Id: If1b097fb5b9453d1e108534c1fb088dfc92b1b6e
5 files changed, 564 insertions, 20 deletions
diff --git a/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java b/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java index 65a49ea6cecc..2731f428bf39 100644 --- a/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java +++ b/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java @@ -21,11 +21,14 @@ import android.net.wifi.hotspot2.pps.Credential;  import android.net.wifi.hotspot2.pps.HomeSP;  import android.text.TextUtils;  import android.util.Log; +import android.util.Pair;  import java.io.IOException;  import java.util.ArrayList; +import java.util.HashMap;  import java.util.HashSet;  import java.util.List; +import java.util.Map;  import java.util.Set;  import org.xml.sax.SAXException; @@ -131,6 +134,14 @@ public final class PPSMOParser {      private static final String NODE_FQDN = "FQDN";      private static final String NODE_FRIENDLY_NAME = "FriendlyName";      private static final String NODE_ROAMING_CONSORTIUM_OI = "RoamingConsortiumOI"; +    private static final String NODE_NETWORK_ID = "NetworkID"; +    private static final String NODE_SSID = "SSID"; +    private static final String NODE_HESSID = "HESSID"; +    private static final String NODE_ICON_URL = "IconURL"; +    private static final String NODE_HOME_OI_LIST = "HomeOIList"; +    private static final String NODE_HOME_OI = "HomeOI"; +    private static final String NODE_HOME_OI_REQUIRED = "HomeOIRequired"; +    private static final String NODE_OTHER_HOME_PARTNERS = "OtherHomePartners";      /**       * Fields under Credential subtree. @@ -558,6 +569,20 @@ public final class PPSMOParser {                      homeSp.roamingConsortiumOIs =                              parseRoamingConsortiumOI(getPpsNodeValue(child));                      break; +                case NODE_ICON_URL: +                    homeSp.iconUrl = getPpsNodeValue(child); +                    break; +                case NODE_NETWORK_ID: +                    homeSp.homeNetworkIds = parseNetworkIds(child); +                    break; +                case NODE_HOME_OI_LIST: +                    Pair<List<Long>, List<Long>> homeOIs = parseHomeOIList(child); +                    homeSp.matchAllOIs = convertFromLongList(homeOIs.first); +                    homeSp.matchAnyOIs = convertFromLongList(homeOIs.second); +                    break; +                case NODE_OTHER_HOME_PARTNERS: +                    homeSp.otherHomePartners = parseOtherHomePartners(child); +                    break;                  default:                      throw new ParsingException("Unknown node under HomeSP: " + child.getName());              } @@ -587,6 +612,192 @@ public final class PPSMOParser {      }      /** +     * Parse configurations under PerProviderSubscription/HomeSP/NetworkID subtree. +     * +     * @param node PPSNode representing the root of the PerProviderSubscription/HomeSP/NetworkID +     *             subtree +     * @return HashMap<String, Long> representing list of <SSID, HESSID> pair. +     * @throws ParsingException +     */ +    static private Map<String, Long> parseNetworkIds(PPSNode node) +            throws ParsingException { +        if (node.isLeaf()) { +            throw new ParsingException("Leaf node not expected for NetworkID"); +        } + +        Map<String, Long> networkIds = new HashMap<>(); +        for (PPSNode child : node.getChildren()) { +            Pair<String, Long> networkId = parseNetworkIdInstance(child); +            networkIds.put(networkId.first, networkId.second); +        } +        return networkIds; +    } + +    /** +     * Parse configurations under PerProviderSubscription/HomeSP/NetworkID/<X+> subtree. +     * The instance name (<X+>) is irrelevant and must be unique for each instance, which +     * is verified when the PPS tree is constructed {@link #buildPpsNode}. +     * +     * @param node PPSNode representing the root of the +     *             PerProviderSubscription/HomeSP/NetworkID/<X+> subtree +     * @return Pair<String, Long> representing <SSID, HESSID> pair. +     * @throws ParsingException +     */ +    static private Pair<String, Long> parseNetworkIdInstance(PPSNode node) +            throws ParsingException { +        if (node.isLeaf()) { +            throw new ParsingException("Leaf node not expected for NetworkID instance"); +        } + +        String ssid = null; +        Long hessid = null; +        for (PPSNode child : node.getChildren()) { +            switch (child.getName()) { +                case NODE_SSID: +                    ssid = getPpsNodeValue(child); +                    break; +                case NODE_HESSID: +                    try { +                        hessid = Long.parseLong(getPpsNodeValue(child), 16); +                    } catch (NumberFormatException e) { +                        throw new ParsingException("Invalid HESSID: " + getPpsNodeValue(child)); +                    } +                    break; +                default: +                    throw new ParsingException("Unknown node under NetworkID instance: " + +                            child.getName()); +            } +        } +        if (ssid == null) +            throw new ParsingException("NetworkID instance missing SSID"); + +        return new Pair<String, Long>(ssid, hessid); +    } + +    /** +     * Parse configurations under PerProviderSubscription/HomeSP/HomeOIList subtree. +     * +     * @param node PPSNode representing the root of the PerProviderSubscription/HomeSP/HomeOIList +     *             subtree +     * @return Pair<List<Long>, List<Long>> containing both MatchAllOIs and MatchAnyOIs list. +     * @throws ParsingException +     */ +    private static Pair<List<Long>, List<Long>> parseHomeOIList(PPSNode node) +            throws ParsingException { +        if (node.isLeaf()) { +            throw new ParsingException("Leaf node not expected for HomeOIList"); +        } + +        List<Long> matchAllOIs = new ArrayList<Long>(); +        List<Long> matchAnyOIs = new ArrayList<Long>(); +        for (PPSNode child : node.getChildren()) { +            Pair<Long, Boolean> homeOI = parseHomeOIInstance(child); +            if (homeOI.second.booleanValue()) { +                matchAllOIs.add(homeOI.first); +            } else { +                matchAnyOIs.add(homeOI.first); +            } +        } +        return new Pair<List<Long>, List<Long>>(matchAllOIs, matchAnyOIs); +    } + +    /** +     * Parse configurations under PerProviderSubscription/HomeSP/HomeOIList/<X+> subtree. +     * The instance name (<X+>) is irrelevant and must be unique for each instance, which +     * is verified when the PPS tree is constructed {@link #buildPpsNode}. +     * +     * @param node PPSNode representing the root of the +     *             PerProviderSubscription/HomeSP/HomeOIList/<X+> subtree +     * @return Pair<Long, Boolean> containing a HomeOI and a HomeOIRequired flag +     * @throws ParsingException +     */ +    private static Pair<Long, Boolean> parseHomeOIInstance(PPSNode node) throws ParsingException { +        if (node.isLeaf()) { +            throw new ParsingException("Leaf node not expected for HomeOI instance"); +        } + +        Long oi = null; +        Boolean required = null; +        for (PPSNode child : node.getChildren()) { +            switch (child.getName()) { +                case NODE_HOME_OI: +                    try { +                        oi = Long.valueOf(getPpsNodeValue(child), 16); +                    } catch (NumberFormatException e) { +                        throw new ParsingException("Invalid HomeOI: " + getPpsNodeValue(child)); +                    } +                    break; +                case NODE_HOME_OI_REQUIRED: +                    required = Boolean.valueOf(getPpsNodeValue(child)); +                    break; +                default: +                    throw new ParsingException("Unknown node under NetworkID instance: " + +                            child.getName()); +            } +        } +        if (oi == null) { +            throw new ParsingException("HomeOI instance missing OI field"); +        } +        if (required == null) { +            throw new ParsingException("HomeOI instance missing required field"); +        } +        return new Pair<Long, Boolean>(oi, required); +    } + +    /** +     * Parse configurations under PerProviderSubscription/HomeSP/OtherHomePartners subtree. +     * This contains a list of FQDN (Fully Qualified Domain Name) that are considered +     * home partners. +     * +     * @param node PPSNode representing the root of the +     *             PerProviderSubscription/HomeSP/OtherHomePartners subtree +     * @return String[] list of partner's FQDN +     * @throws ParsingException +     */ +    private static String[] parseOtherHomePartners(PPSNode node) throws ParsingException { +        if (node.isLeaf()) { +            throw new ParsingException("Leaf node not expected for OtherHomePartners"); +        } +        List<String> otherHomePartners = new ArrayList<String>(); +        for (PPSNode child : node.getChildren()) { +            String fqdn = parseOtherHomePartnerInstance(child); +            otherHomePartners.add(fqdn); +        } +        return otherHomePartners.toArray(new String[otherHomePartners.size()]); +    } + +    /** +     * Parse configurations under PerProviderSubscription/HomeSP/OtherHomePartners/<X+> subtree. +     * The instance name (<X+>) is irrelevant and must be unique for each instance, which +     * is verified when the PPS tree is constructed {@link #buildPpsNode}. +     * +     * @param node PPSNode representing the root of the +     *             PerProviderSubscription/HomeSP/OtherHomePartners/<X+> subtree +     * @return String FQDN of the partner +     * @throws ParsingException +     */ +    private static String parseOtherHomePartnerInstance(PPSNode node) throws ParsingException { +        if (node.isLeaf()) { +            throw new ParsingException("Leaf node not expected for OtherHomePartner instance"); +        } +        String fqdn = null; +        for (PPSNode child : node.getChildren()) { +            switch (child.getName()) { +                case NODE_FQDN: +                    fqdn = getPpsNodeValue(child); +                    break; +                default: +                    throw new ParsingException( +                            "Unknown node under OtherHomePartner instance: " + child.getName()); +            } +        } +        if (fqdn == null) { +            throw new ParsingException("OtherHomePartner instance missing FQDN field"); +        } +        return fqdn; +    } + +    /**       * Parse configurations under PerProviderSubscription/Credential subtree.       *       * @param node PPSNode representing the root of the PerProviderSubscription/Credential subtree @@ -783,4 +994,19 @@ public final class PPSMOParser {              throw new ParsingException("Invalid integer value: " + value);          }      } + +    /** +     * Convert a List<Long> to a primitive long array long[]. +     * +     * @param list List to be converted +     * @return long[] +     */ +    private static long[] convertFromLongList(List<Long> list) { +        Long[] objectArray = list.toArray(new Long[list.size()]); +        long[] primitiveArray = new long[objectArray.length]; +        for (int i = 0; i < objectArray.length; i++) { +            primitiveArray[i] = objectArray[i].longValue(); +        } +        return primitiveArray; +    }  } diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java index d4a5792d93fc..4ddf21099751 100644 --- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java +++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java @@ -21,7 +21,11 @@ import android.os.Parcel;  import android.text.TextUtils;  import android.util.Log; +import java.nio.charset.StandardCharsets;  import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map;  /**   * Class representing HomeSP subtree in PerProviderSubscription (PPS) @@ -30,14 +34,22 @@ import java.util.Arrays;   * For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0   * Release 2 Technical Specification.   * - * Currently we only support the nodes that are used by Hotspot 2.0 Release 1. - *   * @hide   */  public final class HomeSP implements Parcelable {      private static final String TAG = "HomeSP";      /** +     * Maximum number of bytes allowed for a SSID. +     */ +    private static final int MAX_SSID_BYTES = 32; + +    /** +     * Integer value used for indicating null value in the Parcel. +     */ +    private static final int NULL_VALUE = -1; + +    /**       * FQDN (Fully Qualified Domain Name) of this home service provider.       */      public String fqdn = null; @@ -48,6 +60,55 @@ public final class HomeSP implements Parcelable {      public String friendlyName = null;      /** +     * Icon URL of this home service provider. +     */ +    public String iconUrl = null; + +    /** +     * <SSID, HESSID> duple of the networks that are consider home networks. +     * +     * According to the Section 9.1.2 of the Hotspot 2.0 Release 2 Technical Specification, +     * all nodes in the PSS MO are encoded using UTF-8 unless stated otherwise.  Thus, the SSID +     * string is assumed to be encoded using UTF-8. +     */ +    public Map<String, Long> homeNetworkIds = null; + +    /** +     * Used for determining if this provider is a member of a given Hotspot provider. +     * Every Organization Identifiers (OIs) in this list are required to match an OI in the +     * the Roaming Consortium advertised by a Hotspot, in order to consider this provider +     * as a member of that Hotspot provider (e.g. successful authentication with such Hotspot +     * is possible). +     * +     * Refer to HomeSP/HomeOIList subtree in PerProviderSubscription (PPS) Management Object +     * (MO) tree for more detail. +     */ +    public long[] matchAllOIs = null; + +    /** +     * Used for determining if this provider is a member of a given Hotspot provider. +     * Matching of any Organization Identifiers (OIs) in this list with an OI in the +     * Roaming Consortium advertised by a Hotspot, will consider this provider as a member +     * of that Hotspot provider (e.g. successful authentication with such Hotspot +     * is possible). +     * +     * {@link #matchAllOIs} will have precedence over this one, meaning this list will +     * only be used for matching if {@link #matchAllOIs} is null or empty. +     * +     * Refer to HomeSP/HomeOIList subtree in PerProviderSubscription (PPS) Management Object +     * (MO) tree for more detail. +     */ +    public long[] matchAnyOIs = null; + +    /** +     * List of FQDN (Fully Qualified Domain Name) of partner providers. +     * These providers should also be regarded as home Hotspot operators. +     * This relationship is most likely achieved via a commercial agreement or +     * operator merges between the providers. +     */ +    public String[] otherHomePartners = null; + +    /**       * List of Organization Identifiers (OIs) identifying a roaming consortium of       * which this provider is a member.       */ @@ -64,13 +125,28 @@ public final class HomeSP implements Parcelable {       * @param source The source to copy from       */      public HomeSP(HomeSP source) { -        if (source != null) { -            fqdn = source.fqdn; -            friendlyName = source.friendlyName; -            if (source.roamingConsortiumOIs != null) { -                roamingConsortiumOIs = Arrays.copyOf(source.roamingConsortiumOIs, -                                                     source.roamingConsortiumOIs.length); -            } +        if (source == null) { +            return; +        } +        fqdn = source.fqdn; +        friendlyName = source.friendlyName; +        iconUrl = source.iconUrl; +        if (source.homeNetworkIds != null) { +            homeNetworkIds = Collections.unmodifiableMap(source.homeNetworkIds); +        } +        if (source.matchAllOIs != null) { +            matchAllOIs = Arrays.copyOf(source.matchAllOIs, source.matchAllOIs.length); +        } +        if (source.matchAnyOIs != null) { +            matchAnyOIs = Arrays.copyOf(source.matchAnyOIs, source.matchAnyOIs.length); +        } +        if (source.otherHomePartners != null) { +            otherHomePartners = Arrays.copyOf(source.otherHomePartners, +                    source.otherHomePartners.length); +        } +        if (source.roamingConsortiumOIs != null) { +            roamingConsortiumOIs = Arrays.copyOf(source.roamingConsortiumOIs, +                    source.roamingConsortiumOIs.length);          }      } @@ -83,6 +159,11 @@ public final class HomeSP implements Parcelable {      public void writeToParcel(Parcel dest, int flags) {          dest.writeString(fqdn);          dest.writeString(friendlyName); +        dest.writeString(iconUrl); +        writeHomeNetworkIds(dest, homeNetworkIds); +        dest.writeLongArray(matchAllOIs); +        dest.writeLongArray(matchAnyOIs); +        dest.writeStringArray(otherHomePartners);          dest.writeLongArray(roamingConsortiumOIs);      } @@ -96,9 +177,15 @@ public final class HomeSP implements Parcelable {          }          HomeSP that = (HomeSP) thatObject; -        return TextUtils.equals(fqdn, that.fqdn) && -                TextUtils.equals(friendlyName, that.friendlyName) && -                Arrays.equals(roamingConsortiumOIs, that.roamingConsortiumOIs); +        return TextUtils.equals(fqdn, that.fqdn) +                && TextUtils.equals(friendlyName, that.friendlyName) +                && TextUtils.equals(iconUrl, that.iconUrl) +                && (homeNetworkIds == null ? that.homeNetworkIds == null +                        : homeNetworkIds.equals(that.homeNetworkIds)) +                && Arrays.equals(matchAllOIs, that.matchAllOIs) +                && Arrays.equals(matchAnyOIs, that.matchAnyOIs) +                && Arrays.equals(otherHomePartners, that.otherHomePartners) +                && Arrays.equals(roamingConsortiumOIs, that.roamingConsortiumOIs);      }      /** @@ -115,6 +202,16 @@ public final class HomeSP implements Parcelable {              Log.d(TAG, "Missing friendly name");              return false;          } +        // Verify SSIDs specified in the NetworkID +        if (homeNetworkIds != null) { +            for (Map.Entry<String, Long> entry : homeNetworkIds.entrySet()) { +                if (entry.getKey() == null || +                        entry.getKey().getBytes(StandardCharsets.UTF_8).length > MAX_SSID_BYTES) { +                    Log.d(TAG, "Invalid SSID in HomeNetworkIDs"); +                    return false; +                } +            } +        }          return true;      } @@ -125,6 +222,11 @@ public final class HomeSP implements Parcelable {                  HomeSP homeSp = new HomeSP();                  homeSp.fqdn = in.readString();                  homeSp.friendlyName = in.readString(); +                homeSp.iconUrl = in.readString(); +                homeSp.homeNetworkIds = readHomeNetworkIds(in); +                homeSp.matchAllOIs = in.createLongArray(); +                homeSp.matchAnyOIs = in.createLongArray(); +                homeSp.otherHomePartners = in.createStringArray();                  homeSp.roamingConsortiumOIs = in.createLongArray();                  return homeSp;              } @@ -133,5 +235,51 @@ public final class HomeSP implements Parcelable {              public HomeSP[] newArray(int size) {                  return new HomeSP[size];              } + +            /** +             * Helper function for reading a Home Network IDs map from a Parcel. +             * +             * @param in The Parcel to read from +             * @return Map of home network IDs +             */ +            private Map<String, Long> readHomeNetworkIds(Parcel in) { +                int size = in.readInt(); +                if (size == NULL_VALUE) { +                    return null; +                } +                Map<String, Long> networkIds = new HashMap<>(size); +                for (int i = 0; i < size; i++) { +                    String key = in.readString(); +                    Long value = null; +                    long readValue = in.readLong(); +                    if (readValue != NULL_VALUE) { +                        value = Long.valueOf(readValue); +                    } +                    networkIds.put(key, value); +                } +                return networkIds; +            }          }; + +    /** +     * Helper function for writing Home Network IDs map to a Parcel. +     * +     * @param dest The Parcel to write to +     * @param networkIds The map of home network IDs +     */ +    private static void writeHomeNetworkIds(Parcel dest, Map<String, Long> networkIds) { +        if (networkIds == null) { +            dest.writeInt(NULL_VALUE); +            return; +        } +        dest.writeInt(networkIds.size()); +        for (Map.Entry<String, Long> entry : networkIds.entrySet()) { +            dest.writeString(entry.getKey()); +            if (entry.getValue() == null) { +                dest.writeLong(NULL_VALUE); +            } else { +                dest.writeLong(entry.getValue()); +            } +        } +    }  } diff --git a/wifi/tests/assets/pps/PerProviderSubscription.xml b/wifi/tests/assets/pps/PerProviderSubscription.xml index 53d38ad23b9b..07ef7b354310 100644 --- a/wifi/tests/assets/pps/PerProviderSubscription.xml +++ b/wifi/tests/assets/pps/PerProviderSubscription.xml @@ -23,6 +23,66 @@            <NodeName>RoamingConsortiumOI</NodeName>            <Value>112233,445566</Value>          </Node> +        <Node> +          <NodeName>IconURL</NodeName> +          <Value>icon.test.com</Value> +        </Node> +        <Node> +          <NodeName>NetworkID</NodeName> +          <Node> +            <NodeName>n001</NodeName> +            <Node> +              <NodeName>SSID</NodeName> +              <Value>TestSSID</Value> +            </Node> +            <Node> +              <NodeName>HESSID</NodeName> +              <Value>12345678</Value> +            </Node> +          </Node> +          <Node> +            <NodeName>n002</NodeName> +            <Node> +              <NodeName>SSID</NodeName> +              <Value>NullHESSID</Value> +            </Node> +          </Node> +        </Node> +        <Node> +          <NodeName>HomeOIList</NodeName> +          <Node> +            <NodeName>h001</NodeName> +            <Node> +              <NodeName>HomeOI</NodeName> +              <Value>11223344</Value> +            </Node> +            <Node> +              <NodeName>HomeOIRequired</NodeName> +              <Value>true</Value> +            </Node> +          </Node> +          <Node> +            <NodeName>h002</NodeName> +            <Node> +              <NodeName>HomeOI</NodeName> +              <Value>55667788</Value> +            </Node> +            <Node> +              <NodeName>HomeOIRequired</NodeName> +              <Value>false</Value> +            </Node> +          </Node> +        </Node> +        <Node> +          <NodeName>OtherHomePartners</NodeName> +          <Node> +            <NodeName>o001</NodeName> +            <Node> +              <NodeName>FQDN</NodeName> +              <Value>other.fqdn.com</Value> +            </Node> +          </Node> +        </Node>        </Node>        <Node>          <NodeName>Credential</NodeName> diff --git a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java index 10b02677a15b..e5537052dc76 100644 --- a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java +++ b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java @@ -32,6 +32,7 @@ import java.io.IOException;  import java.io.InputStream;  import java.io.InputStreamReader;  import java.util.Arrays; +import java.util.HashMap;  /**   * Unit tests for {@link android.net.wifi.hotspot2.omadm.PPSMOParser}. @@ -85,6 +86,13 @@ public class PPSMOParserTest {          config.homeSp.friendlyName = "Century House";          config.homeSp.fqdn = "mi6.co.uk";          config.homeSp.roamingConsortiumOIs = new long[] {0x112233L, 0x445566L}; +        config.homeSp.iconUrl = "icon.test.com"; +        config.homeSp.homeNetworkIds = new HashMap<>(); +        config.homeSp.homeNetworkIds.put("TestSSID", 0x12345678L); +        config.homeSp.homeNetworkIds.put("NullHESSID", null); +        config.homeSp.matchAllOIs = new long[] {0x11223344}; +        config.homeSp.matchAnyOIs = new long[] {0x55667788}; +        config.homeSp.otherHomePartners = new String[] {"other.fqdn.com"};          // Credential configuration.          config.credential = new Credential(); diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java index c70799332b02..45fdbea90769 100644 --- a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java +++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java @@ -24,19 +24,71 @@ import android.test.suitebuilder.annotation.SmallTest;  import org.junit.Test; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +  /**   * Unit tests for {@link android.net.wifi.hotspot2.pps.HomeSP}.   */  @SmallTest  public class HomeSPTest { -    private static HomeSP createHomeSp() { + +    /** +     * Helper function for creating a map of home network IDs for testing. +     * +     * @return Map of home network IDs +     */ +    private static Map<String, Long> createHomeNetworkIds() { +        Map<String, Long> homeNetworkIds = new HashMap<>(); +        homeNetworkIds.put("ssid", 0x1234L); +        homeNetworkIds.put("nullhessid", null); +        return homeNetworkIds; +    } + +    /** +     * Helper function for creating a HomeSP for testing. +     * +     * @param homeNetworkIds The map of home network IDs associated with HomeSP +     * @return {@link HomeSP} +     */ +    private static HomeSP createHomeSp(Map<String, Long> homeNetworkIds) {          HomeSP homeSp = new HomeSP();          homeSp.fqdn = "fqdn";          homeSp.friendlyName = "friendly name"; +        homeSp.iconUrl = "icon.url"; +        homeSp.homeNetworkIds = homeNetworkIds; +        homeSp.matchAllOIs = new long[] {0x11L, 0x22L}; +        homeSp.matchAnyOIs = new long[] {0x33L, 0x44L}; +        homeSp.otherHomePartners = new String[] {"partner1", "partner2"};          homeSp.roamingConsortiumOIs = new long[] {0x55, 0x66};          return homeSp;      } +    /** +     * Helper function for creating a HomeSP with home network IDs for testing. +     * +     * @return {@link HomeSP} +     */ +    private static HomeSP createHomeSpWithHomeNetworkIds() { +        return createHomeSp(createHomeNetworkIds()); +    } + +    /** +     * Helper function for creating a HomeSP without home network IDs for testing. +     * +     * @return {@link HomeSP} +     */ +    private static HomeSP createHomeSpWithoutHomeNetworkIds() { +        return createHomeSp(null); +    } + +    /** +     * Helper function for verifying HomeSP after parcel write then read. +     * @param writeHomeSp +     * @throws Exception +     */      private static void verifyParcel(HomeSP writeHomeSp) throws Exception {          Parcel parcel = Parcel.obtain();          writeHomeSp.writeToParcel(parcel, 0); @@ -57,13 +109,23 @@ public class HomeSPTest {      }      /** -     * Verify parcel read/write for a valid HomeSP. +     * Verify parcel read/write for a HomeSP containing Home Network IDs. +     * +     * @throws Exception +     */ +    @Test +    public void verifyParcelWithHomeNetworkIds() throws Exception { +        verifyParcel(createHomeSpWithHomeNetworkIds()); +    } + +    /** +     * Verify parcel read/write for a HomeSP without Home Network IDs.       *       * @throws Exception       */      @Test -    public void verifyParcelWithValidHomeSP() throws Exception { -        verifyParcel(createHomeSp()); +    public void verifyParcelWithoutHomeNetworkIds() throws Exception { +        verifyParcel(createHomeSpWithoutHomeNetworkIds());      }      /** @@ -120,6 +182,49 @@ public class HomeSPTest {      }      /** +     * Verify that a HomeSP is valid when the optional Home Network IDs are +     * provided. +     * +     * @throws Exception +     */ +    @Test +    public void validateHomeSpWithHomeNetworkIds() throws Exception { +        HomeSP homeSp = createHomeSpWithHomeNetworkIds(); +        assertTrue(homeSp.validate()); +    } + +    /** +     * Verify that a HomeSP is valid when the optional Home Network IDs are +     * not provided. +     * +     * @throws Exception +     */ +    @Test +    public void validateHomeSpWithoutHomeNetworkIds() throws Exception { +        HomeSP homeSp = createHomeSpWithoutHomeNetworkIds(); +        assertTrue(homeSp.validate()); +    } + +    /** +     * Verify that a HomeSP is invalid when the optional Home Network IDs +     * contained an invalid SSID (exceeding maximum number of bytes). +     * +     * @throws Exception +     */ +    @Test +    public void validateHomeSpWithInvalidHomeNetworkIds() throws Exception { +        HomeSP homeSp = new HomeSP(); +        homeSp.fqdn = "fqdn"; +        homeSp.friendlyName = "friendly name"; +        homeSp.homeNetworkIds = new HashMap<>(); +        byte[] rawSsidBytes = new byte[33]; +        Arrays.fill(rawSsidBytes, (byte) 'a'); +        homeSp.homeNetworkIds.put( +                StringFactory.newStringFromBytes(rawSsidBytes, StandardCharsets.UTF_8), 0x1234L); +        assertFalse(homeSp.validate()); +    } + +    /**       * Verify that copy constructor works when pass in a null source.       *       * @throws Exception @@ -138,10 +243,7 @@ public class HomeSPTest {       */      @Test      public void validateCopyConstructorFromValidSource() throws Exception { -        HomeSP sourceSp = new HomeSP(); -        sourceSp.fqdn = "fqdn"; -        sourceSp.friendlyName = "friendlyName"; -        sourceSp.roamingConsortiumOIs = new long[] {0x55, 0x66}; +        HomeSP sourceSp = createHomeSpWithHomeNetworkIds();          HomeSP copySp = new HomeSP(sourceSp);          assertTrue(copySp.equals(sourceSp));      }  |