Loading wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java +33 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.net.wifi.hotspot2; import android.annotation.Nullable; import android.net.wifi.hotspot2.pps.Credential; import android.net.wifi.hotspot2.pps.HomeSp; import android.net.wifi.hotspot2.pps.Policy; Loading Loading @@ -77,6 +78,29 @@ public final class PasspointConfiguration implements Parcelable { */ public HomeSp getHomeSp() { return mHomeSp; } /** * Configurations under AAAServerTrustedNames subtree. */ private String[] mAaaServerTrustedNames = null; /** * Set the AAA server trusted names information. * * @param aaaServerTrustedNames The AAA server trusted names information to set to * @hide */ public void setAaaServerTrustedNames(@Nullable String[] aaaServerTrustedNames) { mAaaServerTrustedNames = aaaServerTrustedNames; } /** * Get the AAA server trusted names information. * * @return AAA server trusted names information * @hide */ public @Nullable String[] getAaaServerTrustedNames() { return mAaaServerTrustedNames; } /** * Configurations under Credential subtree. */ Loading Loading @@ -409,6 +433,7 @@ public final class PasspointConfiguration implements Parcelable { mUsageLimitTimeLimitInMinutes = source.mUsageLimitTimeLimitInMinutes; mUsageLimitUsageTimePeriodInMinutes = source.mUsageLimitUsageTimePeriodInMinutes; mServiceFriendlyNames = source.mServiceFriendlyNames; mAaaServerTrustedNames = source.mAaaServerTrustedNames; } @Override Loading @@ -432,6 +457,7 @@ public final class PasspointConfiguration implements Parcelable { dest.writeLong(mUsageLimitStartTimeInMillis); dest.writeLong(mUsageLimitDataLimit); dest.writeLong(mUsageLimitTimeLimitInMinutes); dest.writeStringArray(mAaaServerTrustedNames); Bundle bundle = new Bundle(); bundle.putSerializable("serviceFriendlyNames", (HashMap<String, String>) mServiceFriendlyNames); Loading @@ -448,6 +474,8 @@ public final class PasspointConfiguration implements Parcelable { } PasspointConfiguration that = (PasspointConfiguration) thatObject; return (mHomeSp == null ? that.mHomeSp == null : mHomeSp.equals(that.mHomeSp)) && (mAaaServerTrustedNames == null ? that.mAaaServerTrustedNames == null : Arrays.equals(mAaaServerTrustedNames, that.mAaaServerTrustedNames)) && (mCredential == null ? that.mCredential == null : mCredential.equals(that.mCredential)) && (mPolicy == null ? that.mPolicy == null : mPolicy.equals(that.mPolicy)) Loading Loading @@ -517,6 +545,10 @@ public final class PasspointConfiguration implements Parcelable { builder.append("TrustRootCertServers: ").append(mTrustRootCertList.keySet()) .append("\n"); } if (mAaaServerTrustedNames != null) { builder.append("AAAServerTrustedNames: ") .append(String.join(";", mAaaServerTrustedNames)).append("\n"); } if (mServiceFriendlyNames != null) { builder.append("ServiceFriendlyNames: ").append(mServiceFriendlyNames); } Loading Loading @@ -619,6 +651,7 @@ public final class PasspointConfiguration implements Parcelable { config.setUsageLimitStartTimeInMillis(in.readLong()); config.setUsageLimitDataLimit(in.readLong()); config.setUsageLimitTimeLimitInMinutes(in.readLong()); config.setAaaServerTrustedNames(in.createStringArray()); Bundle bundle = in.readBundle(); Map<String, String> friendlyNamesMap = (HashMap) bundle.getSerializable( "serviceFriendlyNames"); Loading wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java +130 −3 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; import org.xml.sax.SAXException; import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; Loading @@ -36,8 +38,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import org.xml.sax.SAXException; /** * Utility class for converting OMA-DM (Open Mobile Alliance's Device Management) * PPS-MO (PerProviderSubscription Management Object) XML tree to a Loading Loading @@ -146,6 +146,47 @@ public final class PpsMoParser { private static final String NODE_CREDENTIAL_PRIORITY = "CredentialPriority"; private static final String NODE_EXTENSION = "Extension"; /** * Fields under Extension/Android subtree. */ /* * This node is used to put Android specific extension nodes and must be put * under "Extension" node. Nodes with unknown names are allowed under this subtree. * If there is any new node added in later release, it won't break older release parsing. * <p> * Ex: * <Node> * <NodeName>Extension</NodeName> * <Node> * <NodeName>Android</NodeName> * <Node> * <NodeName>AndroidSpecificAttribute</NodeName> * <Value>AndroidSpecificValue</Value> * </Node> * <Node> * <NodeName>AndroidSpecificAttribute2</NodeName> * <Value>AndroidSpecificValue2</Value> * </Node> * </Node> * </Node> */ private static final String NODE_VENDOR_ANDROID = "Android"; /* * This node describes AAA server trusted names. The trusted name must be put in * a leaf named "FQDN". More than one trusted names can be provided by using * semicolons to separate the strings (e.g., example.org;example.com). * <p> * Ex: * <Node> * <NodeName>AAAServerTrustedNames</NodeName> * <Node> * <NodeName>FQDN</NodeName> * <Value>trusted.com;auth.net</Value> * </Node> * <Node> */ private static final String NODE_AAA_SERVER_TRUSTED_NAMES = "AAAServerTrustedNames"; /** * Fields under HomeSP subtree. */ Loading Loading @@ -633,7 +674,7 @@ public final class PpsMoParser { break; case NODE_EXTENSION: // All vendor specific information will be under this node. Log.d(TAG, "Ignore Extension node for vendor specific information"); parseExtension(child, config); break; default: throw new ParsingException("Unknown node: " + child.getName()); Loading Loading @@ -1571,6 +1612,92 @@ public final class PpsMoParser { } } /** * Parse configurations under PerProviderSubscription/Extension/Android/AAAServerTrustedNames * subtree. * * @param node PPSNode representing the root of the * PerProviderSubscription/Extension/Android/AAAServerTrustedNames subtree * @return String[] list of trusted name * @throws ParsingException */ private static String[] parseAaaServerTrustedNames(PPSNode node) throws ParsingException { if (node.isLeaf()) { throw new ParsingException("Leaf node not expected for AAAServerTrustedNames instance"); } String fqdnListStr = null; String[] fqdnListArray = null; for (PPSNode child : node.getChildren()) { switch (child.getName()) { case NODE_FQDN: fqdnListStr = getPpsNodeValue(child); fqdnListArray = fqdnListStr.split(";"); break; default: throw new ParsingException( "Unknown node under AAAServerTrustedNames instance: " + child.getName()); } } if (fqdnListArray == null) { throw new ParsingException("AAAServerTrustedNames instance missing FQDN field"); } return fqdnListArray; } /** * Parse configurations under PerProviderSubscription/Extension/Android subtree. * * @param node PPSNode representing the root of PerProviderSubscription/Extension * subtree * @param config Instance of {@link PasspointConfiguration} * @throws ParsingException */ private static void parseVendorAndroidExtension(PPSNode node, PasspointConfiguration config) throws ParsingException { if (node.isLeaf()) { throw new ParsingException("Leaf node not expected for Extension"); } for (PPSNode child : node.getChildren()) { switch (child.getName()) { case NODE_AAA_SERVER_TRUSTED_NAMES: config.setAaaServerTrustedNames(parseAaaServerTrustedNames(child)); break; default: // Don't raise an exception for unknown nodes to avoid breaking old release Log.w(TAG, "Unknown node under Android Extension: " + child.getName()); } } } /** * Parse configurations under PerProviderSubscription/Extension subtree. * * @param node PPSNode representing the root of PerProviderSubscription/Extension * subtree * @param config Instance of {@link PasspointConfiguration} * @throws ParsingException */ private static void parseExtension(PPSNode node, PasspointConfiguration config) throws ParsingException { if (node.isLeaf()) { throw new ParsingException("Leaf node not expected for Extension"); } for (PPSNode child : node.getChildren()) { switch (child.getName()) { case NODE_VENDOR_ANDROID: parseVendorAndroidExtension(child, config); break; default: // Unknown nodes under Extension won't raise exception. // This allows adding new nodes in the future and // won't break older release. Log.w(TAG, "Unknown node under Extension: " + child.getName()); } } } /** * Convert a hex string to a byte array. * Loading wifi/java/android/net/wifi/hotspot2/pps/Credential.java +1 −0 Original line number Diff line number Diff line Loading @@ -1135,6 +1135,7 @@ public final class Credential implements Parcelable { Log.d(TAG, "Missing CA Certificate for user credential"); return false; } return true; } Loading wifi/tests/assets/pps/PerProviderSubscription.xml +24 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,30 @@ <NodeName>VendorSpecific</NodeName> <Value>Test</Value> </Node> <Node> <NodeName>VendorExtension</NodeName> <Node> <NodeName>VendorAttribute</NodeName> <Value>VendorValue</Value> </Node> </Node> <Node> <NodeName>Android</NodeName> <Node> <NodeName>AAAServerTrustedNames</NodeName> <Node> <NodeName>FQDN</NodeName> <Value>trusted.fqdn.com;another-trusted.fqdn.com</Value> </Node> </Node> <Node> <NodeName>NewSubTree</NodeName> <Node> <NodeName>NewAttribute</NodeName> <Value>NewValue</Value> </Node> </Node> </Node> </Node> <Node> <NodeName>HomeSP</NodeName> Loading wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java +30 −0 Original line number Diff line number Diff line Loading @@ -149,6 +149,8 @@ public class PasspointConfigurationTest { PasspointConfiguration config = new PasspointConfiguration(); config.setUpdateIdentifier(1234); config.setHomeSp(createHomeSp()); config.setAaaServerTrustedNames( new String[] {"trusted.fqdn.com", "another-trusted.fqdn.com"}); config.setCredential(createCredential()); config.setPolicy(createPolicy()); config.setSubscriptionUpdate(createSubscriptionUpdate()); Loading Loading @@ -283,6 +285,19 @@ public class PasspointConfigurationTest { verifyParcel(config); } /** * Verify parcel read/write for a configuration that doesn't contain AAA server trusted names * list. * * @throws Exception */ @Test public void verifyParcelWithoutAaaServerTrustedNames() throws Exception { PasspointConfiguration config = createConfig(); config.setAaaServerTrustedNames(null); verifyParcel(config); } /** * Verify that a default/empty configuration is invalid. * Loading Loading @@ -382,6 +397,21 @@ public class PasspointConfigurationTest { assertFalse(config.validateForR2()); } /** * Verify that a configuration without AAA server trusted names is valid for R1 and R2, * since AAA server trusted names are optional for R1 and R2. * * @throws Exception */ @Test public void validateConfigWithoutAaaServerTrustedNames() throws Exception { PasspointConfiguration config = createConfig(); config.setAaaServerTrustedNames(null); assertTrue(config.validate()); assertTrue(config.validateForR2()); } /** * Verify that a configuration with a trust root certificate URL exceeding the max size * is invalid. Loading Loading
wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java +33 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.net.wifi.hotspot2; import android.annotation.Nullable; import android.net.wifi.hotspot2.pps.Credential; import android.net.wifi.hotspot2.pps.HomeSp; import android.net.wifi.hotspot2.pps.Policy; Loading Loading @@ -77,6 +78,29 @@ public final class PasspointConfiguration implements Parcelable { */ public HomeSp getHomeSp() { return mHomeSp; } /** * Configurations under AAAServerTrustedNames subtree. */ private String[] mAaaServerTrustedNames = null; /** * Set the AAA server trusted names information. * * @param aaaServerTrustedNames The AAA server trusted names information to set to * @hide */ public void setAaaServerTrustedNames(@Nullable String[] aaaServerTrustedNames) { mAaaServerTrustedNames = aaaServerTrustedNames; } /** * Get the AAA server trusted names information. * * @return AAA server trusted names information * @hide */ public @Nullable String[] getAaaServerTrustedNames() { return mAaaServerTrustedNames; } /** * Configurations under Credential subtree. */ Loading Loading @@ -409,6 +433,7 @@ public final class PasspointConfiguration implements Parcelable { mUsageLimitTimeLimitInMinutes = source.mUsageLimitTimeLimitInMinutes; mUsageLimitUsageTimePeriodInMinutes = source.mUsageLimitUsageTimePeriodInMinutes; mServiceFriendlyNames = source.mServiceFriendlyNames; mAaaServerTrustedNames = source.mAaaServerTrustedNames; } @Override Loading @@ -432,6 +457,7 @@ public final class PasspointConfiguration implements Parcelable { dest.writeLong(mUsageLimitStartTimeInMillis); dest.writeLong(mUsageLimitDataLimit); dest.writeLong(mUsageLimitTimeLimitInMinutes); dest.writeStringArray(mAaaServerTrustedNames); Bundle bundle = new Bundle(); bundle.putSerializable("serviceFriendlyNames", (HashMap<String, String>) mServiceFriendlyNames); Loading @@ -448,6 +474,8 @@ public final class PasspointConfiguration implements Parcelable { } PasspointConfiguration that = (PasspointConfiguration) thatObject; return (mHomeSp == null ? that.mHomeSp == null : mHomeSp.equals(that.mHomeSp)) && (mAaaServerTrustedNames == null ? that.mAaaServerTrustedNames == null : Arrays.equals(mAaaServerTrustedNames, that.mAaaServerTrustedNames)) && (mCredential == null ? that.mCredential == null : mCredential.equals(that.mCredential)) && (mPolicy == null ? that.mPolicy == null : mPolicy.equals(that.mPolicy)) Loading Loading @@ -517,6 +545,10 @@ public final class PasspointConfiguration implements Parcelable { builder.append("TrustRootCertServers: ").append(mTrustRootCertList.keySet()) .append("\n"); } if (mAaaServerTrustedNames != null) { builder.append("AAAServerTrustedNames: ") .append(String.join(";", mAaaServerTrustedNames)).append("\n"); } if (mServiceFriendlyNames != null) { builder.append("ServiceFriendlyNames: ").append(mServiceFriendlyNames); } Loading Loading @@ -619,6 +651,7 @@ public final class PasspointConfiguration implements Parcelable { config.setUsageLimitStartTimeInMillis(in.readLong()); config.setUsageLimitDataLimit(in.readLong()); config.setUsageLimitTimeLimitInMinutes(in.readLong()); config.setAaaServerTrustedNames(in.createStringArray()); Bundle bundle = in.readBundle(); Map<String, String> friendlyNamesMap = (HashMap) bundle.getSerializable( "serviceFriendlyNames"); Loading
wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java +130 −3 Original line number Diff line number Diff line Loading @@ -25,6 +25,8 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; import org.xml.sax.SAXException; import java.io.IOException; import java.text.DateFormat; import java.text.ParseException; Loading @@ -36,8 +38,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import org.xml.sax.SAXException; /** * Utility class for converting OMA-DM (Open Mobile Alliance's Device Management) * PPS-MO (PerProviderSubscription Management Object) XML tree to a Loading Loading @@ -146,6 +146,47 @@ public final class PpsMoParser { private static final String NODE_CREDENTIAL_PRIORITY = "CredentialPriority"; private static final String NODE_EXTENSION = "Extension"; /** * Fields under Extension/Android subtree. */ /* * This node is used to put Android specific extension nodes and must be put * under "Extension" node. Nodes with unknown names are allowed under this subtree. * If there is any new node added in later release, it won't break older release parsing. * <p> * Ex: * <Node> * <NodeName>Extension</NodeName> * <Node> * <NodeName>Android</NodeName> * <Node> * <NodeName>AndroidSpecificAttribute</NodeName> * <Value>AndroidSpecificValue</Value> * </Node> * <Node> * <NodeName>AndroidSpecificAttribute2</NodeName> * <Value>AndroidSpecificValue2</Value> * </Node> * </Node> * </Node> */ private static final String NODE_VENDOR_ANDROID = "Android"; /* * This node describes AAA server trusted names. The trusted name must be put in * a leaf named "FQDN". More than one trusted names can be provided by using * semicolons to separate the strings (e.g., example.org;example.com). * <p> * Ex: * <Node> * <NodeName>AAAServerTrustedNames</NodeName> * <Node> * <NodeName>FQDN</NodeName> * <Value>trusted.com;auth.net</Value> * </Node> * <Node> */ private static final String NODE_AAA_SERVER_TRUSTED_NAMES = "AAAServerTrustedNames"; /** * Fields under HomeSP subtree. */ Loading Loading @@ -633,7 +674,7 @@ public final class PpsMoParser { break; case NODE_EXTENSION: // All vendor specific information will be under this node. Log.d(TAG, "Ignore Extension node for vendor specific information"); parseExtension(child, config); break; default: throw new ParsingException("Unknown node: " + child.getName()); Loading Loading @@ -1571,6 +1612,92 @@ public final class PpsMoParser { } } /** * Parse configurations under PerProviderSubscription/Extension/Android/AAAServerTrustedNames * subtree. * * @param node PPSNode representing the root of the * PerProviderSubscription/Extension/Android/AAAServerTrustedNames subtree * @return String[] list of trusted name * @throws ParsingException */ private static String[] parseAaaServerTrustedNames(PPSNode node) throws ParsingException { if (node.isLeaf()) { throw new ParsingException("Leaf node not expected for AAAServerTrustedNames instance"); } String fqdnListStr = null; String[] fqdnListArray = null; for (PPSNode child : node.getChildren()) { switch (child.getName()) { case NODE_FQDN: fqdnListStr = getPpsNodeValue(child); fqdnListArray = fqdnListStr.split(";"); break; default: throw new ParsingException( "Unknown node under AAAServerTrustedNames instance: " + child.getName()); } } if (fqdnListArray == null) { throw new ParsingException("AAAServerTrustedNames instance missing FQDN field"); } return fqdnListArray; } /** * Parse configurations under PerProviderSubscription/Extension/Android subtree. * * @param node PPSNode representing the root of PerProviderSubscription/Extension * subtree * @param config Instance of {@link PasspointConfiguration} * @throws ParsingException */ private static void parseVendorAndroidExtension(PPSNode node, PasspointConfiguration config) throws ParsingException { if (node.isLeaf()) { throw new ParsingException("Leaf node not expected for Extension"); } for (PPSNode child : node.getChildren()) { switch (child.getName()) { case NODE_AAA_SERVER_TRUSTED_NAMES: config.setAaaServerTrustedNames(parseAaaServerTrustedNames(child)); break; default: // Don't raise an exception for unknown nodes to avoid breaking old release Log.w(TAG, "Unknown node under Android Extension: " + child.getName()); } } } /** * Parse configurations under PerProviderSubscription/Extension subtree. * * @param node PPSNode representing the root of PerProviderSubscription/Extension * subtree * @param config Instance of {@link PasspointConfiguration} * @throws ParsingException */ private static void parseExtension(PPSNode node, PasspointConfiguration config) throws ParsingException { if (node.isLeaf()) { throw new ParsingException("Leaf node not expected for Extension"); } for (PPSNode child : node.getChildren()) { switch (child.getName()) { case NODE_VENDOR_ANDROID: parseVendorAndroidExtension(child, config); break; default: // Unknown nodes under Extension won't raise exception. // This allows adding new nodes in the future and // won't break older release. Log.w(TAG, "Unknown node under Extension: " + child.getName()); } } } /** * Convert a hex string to a byte array. * Loading
wifi/java/android/net/wifi/hotspot2/pps/Credential.java +1 −0 Original line number Diff line number Diff line Loading @@ -1135,6 +1135,7 @@ public final class Credential implements Parcelable { Log.d(TAG, "Missing CA Certificate for user credential"); return false; } return true; } Loading
wifi/tests/assets/pps/PerProviderSubscription.xml +24 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,30 @@ <NodeName>VendorSpecific</NodeName> <Value>Test</Value> </Node> <Node> <NodeName>VendorExtension</NodeName> <Node> <NodeName>VendorAttribute</NodeName> <Value>VendorValue</Value> </Node> </Node> <Node> <NodeName>Android</NodeName> <Node> <NodeName>AAAServerTrustedNames</NodeName> <Node> <NodeName>FQDN</NodeName> <Value>trusted.fqdn.com;another-trusted.fqdn.com</Value> </Node> </Node> <Node> <NodeName>NewSubTree</NodeName> <Node> <NodeName>NewAttribute</NodeName> <Value>NewValue</Value> </Node> </Node> </Node> </Node> <Node> <NodeName>HomeSP</NodeName> Loading
wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java +30 −0 Original line number Diff line number Diff line Loading @@ -149,6 +149,8 @@ public class PasspointConfigurationTest { PasspointConfiguration config = new PasspointConfiguration(); config.setUpdateIdentifier(1234); config.setHomeSp(createHomeSp()); config.setAaaServerTrustedNames( new String[] {"trusted.fqdn.com", "another-trusted.fqdn.com"}); config.setCredential(createCredential()); config.setPolicy(createPolicy()); config.setSubscriptionUpdate(createSubscriptionUpdate()); Loading Loading @@ -283,6 +285,19 @@ public class PasspointConfigurationTest { verifyParcel(config); } /** * Verify parcel read/write for a configuration that doesn't contain AAA server trusted names * list. * * @throws Exception */ @Test public void verifyParcelWithoutAaaServerTrustedNames() throws Exception { PasspointConfiguration config = createConfig(); config.setAaaServerTrustedNames(null); verifyParcel(config); } /** * Verify that a default/empty configuration is invalid. * Loading Loading @@ -382,6 +397,21 @@ public class PasspointConfigurationTest { assertFalse(config.validateForR2()); } /** * Verify that a configuration without AAA server trusted names is valid for R1 and R2, * since AAA server trusted names are optional for R1 and R2. * * @throws Exception */ @Test public void validateConfigWithoutAaaServerTrustedNames() throws Exception { PasspointConfiguration config = createConfig(); config.setAaaServerTrustedNames(null); assertTrue(config.validate()); assertTrue(config.validateForR2()); } /** * Verify that a configuration with a trust root certificate URL exceeding the max size * is invalid. Loading