wifi: hotspot2: initial implementation of PasspointConfiguration
Only support nodes under HomeSP and Credential subtree that are used
by Hotspot 2.0 Release 1.
These classes are used for data exchanges between the app and the system
service (WifiService). All the business logics and validations will be
done on the service side (WifiService).
Bug: 31813706
Test: frameworks/base/wifi/tests/runtests.sh
Change-Id: I6b08f52dd7b1a7b337899ab80f11d062c8e2f532
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.aidl b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.aidl
new file mode 100644
index 0000000..6b1cea8
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2016, 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.wifi.hotspot2;
+
+parcelable PasspointConfiguration;
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
new file mode 100644
index 0000000..18aae53
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2016, 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.wifi.hotspot2;
+
+import android.net.wifi.hotspot2.pps.Credential;
+import android.net.wifi.hotspot2.pps.HomeSP;
+import android.os.Parcelable;
+import android.os.Parcel;
+
+/**
+ * Class representing Passpoint configuration. This contains configurations specified in
+ * PerProviderSubscription (PPS) Management Object (MO) tree.
+ *
+ * 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, only HomeSP and Credential subtrees are supported.
+ *
+ * @hide
+ */
+public final class PasspointConfiguration implements Parcelable {
+ public HomeSP homeSp = null;
+ public Credential credential = null;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(homeSp, flags);
+ dest.writeParcelable(credential, flags);
+ }
+
+ @Override
+ public boolean equals(Object thatObject) {
+ if (this == thatObject) {
+ return true;
+ }
+ if (!(thatObject instanceof PasspointConfiguration)) {
+ return false;
+ }
+ PasspointConfiguration that = (PasspointConfiguration) thatObject;
+ return (homeSp == null ? that.homeSp == null : homeSp.equals(that.homeSp)) &&
+ (credential == null ? that.credential == null :
+ credential.equals(that.credential));
+ }
+
+ public static final Creator<PasspointConfiguration> CREATOR =
+ new Creator<PasspointConfiguration>() {
+ @Override
+ public PasspointConfiguration createFromParcel(Parcel in) {
+ PasspointConfiguration config = new PasspointConfiguration();
+ config.homeSp = in.readParcelable(null);
+ config.credential = in.readParcelable(null);
+ return config;
+ }
+ @Override
+ public PasspointConfiguration[] newArray(int size) {
+ return new PasspointConfiguration[size];
+ }
+ };
+}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.aidl b/wifi/java/android/net/wifi/hotspot2/pps/Credential.aidl
new file mode 100644
index 0000000..3d8e833
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2016, 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.wifi.hotspot2.pps;
+
+parcelable Credential;
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
new file mode 100644
index 0000000..92dbd8a
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -0,0 +1,376 @@
+/**
+ * Copyright (c) 2016, 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.wifi.hotspot2.pps;
+
+import android.net.wifi.ParcelUtil;
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.text.TextUtils;
+
+import java.security.PrivateKey;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+
+/**
+ * Class representing Credential subtree in the PerProviderSubscription (PPS)
+ * Management Object (MO) tree.
+ * For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0
+ * Release 2 Technical Specification.
+ *
+ * In addition to the fields in the Credential subtree, this will also maintain necessary
+ * information for the private key and certificates associated with this credential.
+ *
+ * Currently we only support the nodes that are used by Hotspot 2.0 Release 1.
+ *
+ * @hide
+ */
+public final class Credential implements Parcelable {
+ /**
+ * The realm associated with this credential. It will be used to determine
+ * if this credential can be used to authenticate with a given hotspot by
+ * comparing the realm specified in that hotspot's ANQP element.
+ */
+ public String realm = null;
+
+ /**
+ * Username-password based credential.
+ * Contains the fields under PerProviderSubscription/Credential/UsernamePassword subtree.
+ */
+ public static final class UserCredential implements Parcelable {
+ /**
+ * Username of the credential.
+ */
+ public String username = null;
+
+ /**
+ * Base64-encoded password.
+ */
+ public String password = null;
+
+ /**
+ * EAP (Extensible Authentication Protocol) method type.
+ * Refer to http://www.iana.org/assignments/eap-numbers/eap-numbers.xml#eap-numbers-4
+ * for valid values.
+ * Using Integer.MIN_VALUE to indicate unset value.
+ */
+ public int eapType = Integer.MIN_VALUE;
+
+ /**
+ * Non-EAP inner authentication method.
+ */
+ public String nonEapInnerMethod = null;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(username);
+ dest.writeString(password);
+ dest.writeInt(eapType);
+ dest.writeString(nonEapInnerMethod);
+ }
+
+ @Override
+ public boolean equals(Object thatObject) {
+ if (this == thatObject) {
+ return true;
+ }
+ if (!(thatObject instanceof UserCredential)) {
+ return false;
+ }
+
+ UserCredential that = (UserCredential) thatObject;
+ return TextUtils.equals(username, that.username) &&
+ TextUtils.equals(password, that.password) &&
+ eapType == that.eapType &&
+ TextUtils.equals(nonEapInnerMethod, that.nonEapInnerMethod);
+ }
+
+ public static final Creator<UserCredential> CREATOR =
+ new Creator<UserCredential>() {
+ @Override
+ public UserCredential createFromParcel(Parcel in) {
+ UserCredential userCredential = new UserCredential();
+ userCredential.username = in.readString();
+ userCredential.password = in.readString();
+ userCredential.eapType = in.readInt();
+ userCredential.nonEapInnerMethod = in.readString();
+ return userCredential;
+ }
+
+ @Override
+ public UserCredential[] newArray(int size) {
+ return new UserCredential[size];
+ }
+ };
+ }
+ public UserCredential userCredential = null;
+
+ /**
+ * Certificate based credential.
+ * Contains fields under PerProviderSubscription/Credential/DigitalCertificate subtree.
+ */
+ public static final class CertificateCredential implements Parcelable {
+ /**
+ * Certificate type. Valid values are "802.1ar" and "x509v3".
+ */
+ public String certType = null;
+
+ /**
+ * The SHA-256 fingerprint of the certificate.
+ */
+ public byte[] certSha256FingerPrint = null;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(certType);
+ dest.writeByteArray(certSha256FingerPrint);
+ }
+
+ @Override
+ public boolean equals(Object thatObject) {
+ if (this == thatObject) {
+ return true;
+ }
+ if (!(thatObject instanceof CertificateCredential)) {
+ return false;
+ }
+
+ CertificateCredential that = (CertificateCredential) thatObject;
+ return TextUtils.equals(certType, that.certType) &&
+ Arrays.equals(certSha256FingerPrint, that.certSha256FingerPrint);
+ }
+
+ public static final Creator<CertificateCredential> CREATOR =
+ new Creator<CertificateCredential>() {
+ @Override
+ public CertificateCredential createFromParcel(Parcel in) {
+ CertificateCredential certCredential = new CertificateCredential();
+ certCredential.certType = in.readString();
+ certCredential.certSha256FingerPrint = in.createByteArray();
+ return certCredential;
+ }
+
+ @Override
+ public CertificateCredential[] newArray(int size) {
+ return new CertificateCredential[size];
+ }
+ };
+ }
+ public CertificateCredential certCredential = null;
+
+ /**
+ * SIM (Subscriber Identify Module) based credential.
+ * Contains fields under PerProviderSubscription/Credential/SIM subtree.
+ */
+ public static final class SimCredential implements Parcelable {
+ /**
+ * International Mobile device Subscriber Identity.
+ */
+ public String imsi = null;
+
+ /**
+ * EAP (Extensible Authentication Protocol) method type for using SIM credential.
+ * Refer to http://www.iana.org/assignments/eap-numbers/eap-numbers.xml#eap-numbers-4
+ * for valid values.
+ * Using Integer.MIN_VALUE to indicate unset value.
+ */
+ public int eapType = Integer.MIN_VALUE;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object thatObject) {
+ if (this == thatObject) {
+ return true;
+ }
+ if (!(thatObject instanceof SimCredential)) {
+ return false;
+ }
+
+ SimCredential that = (SimCredential) thatObject;
+ return TextUtils.equals(imsi, that.imsi) &&
+ eapType == that.eapType;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(imsi);
+ dest.writeInt(eapType);
+ }
+
+ public static final Creator<SimCredential> CREATOR =
+ new Creator<SimCredential>() {
+ @Override
+ public SimCredential createFromParcel(Parcel in) {
+ SimCredential simCredential = new SimCredential();
+ simCredential.imsi = in.readString();
+ simCredential.eapType = in.readInt();
+ return simCredential;
+ }
+
+ @Override
+ public SimCredential[] newArray(int size) {
+ return new SimCredential[size];
+ }
+ };
+ }
+ public SimCredential simCredential = null;
+
+ /**
+ * CA (Certificate Authority) X509 certificate.
+ */
+ public X509Certificate caCertificate = null;
+
+ /**
+ * Client side X509 certificate chain.
+ */
+ public X509Certificate[] clientCertificateChain = null;
+
+ /**
+ * Client side private key.
+ */
+ public PrivateKey clientPrivateKey = null;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(realm);
+ dest.writeParcelable(userCredential, flags);
+ dest.writeParcelable(certCredential, flags);
+ dest.writeParcelable(simCredential, flags);
+ ParcelUtil.writeCertificate(dest, caCertificate);
+ ParcelUtil.writeCertificates(dest, clientCertificateChain);
+ ParcelUtil.writePrivateKey(dest, clientPrivateKey);
+ }
+
+ @Override
+ public boolean equals(Object thatObject) {
+ if (this == thatObject) {
+ return true;
+ }
+ if (!(thatObject instanceof Credential)) {
+ return false;
+ }
+
+ Credential that = (Credential) thatObject;
+ return TextUtils.equals(realm, that.realm) &&
+ (userCredential == null ? that.userCredential == null :
+ userCredential.equals(that.userCredential)) &&
+ (certCredential == null ? that.certCredential == null :
+ certCredential.equals(that.certCredential)) &&
+ (simCredential == null ? that.simCredential == null :
+ simCredential.equals(that.simCredential)) &&
+ isX509CertificateEquals(caCertificate, that.caCertificate) &&
+ isX509CertificatesEquals(clientCertificateChain, that.clientCertificateChain) &&
+ isPrivateKeyEquals(clientPrivateKey, that.clientPrivateKey);
+ }
+
+ public static final Creator<Credential> CREATOR =
+ new Creator<Credential>() {
+ @Override
+ public Credential createFromParcel(Parcel in) {
+ Credential credential = new Credential();
+ credential.realm = in.readString();
+ credential.userCredential = in.readParcelable(null);
+ credential.certCredential = in.readParcelable(null);
+ credential.simCredential = in.readParcelable(null);
+ credential.caCertificate = ParcelUtil.readCertificate(in);
+ credential.clientCertificateChain = ParcelUtil.readCertificates(in);
+ credential.clientPrivateKey = ParcelUtil.readPrivateKey(in);
+ return credential;
+ }
+
+ @Override
+ public Credential[] newArray(int size) {
+ return new Credential[size];
+ }
+ };
+
+ private static boolean isPrivateKeyEquals(PrivateKey key1, PrivateKey key2) {
+ if (key1 == null && key2 == null) {
+ return true;
+ }
+
+ /* Return false if only one of them is null */
+ if (key1 == null || key2 == null) {
+ return false;
+ }
+
+ return TextUtils.equals(key1.getAlgorithm(), key2.getAlgorithm()) &&
+ Arrays.equals(key1.getEncoded(), key2.getEncoded());
+ }
+
+ private static boolean isX509CertificateEquals(X509Certificate cert1, X509Certificate cert2) {
+ if (cert1 == null && cert2 == null) {
+ return true;
+ }
+
+ /* Return false if only one of them is null */
+ if (cert1 == null || cert2 == null) {
+ return false;
+ }
+
+ boolean result = false;
+ try {
+ result = Arrays.equals(cert1.getEncoded(), cert2.getEncoded());
+ } catch (CertificateEncodingException e) {
+ /* empty, return false. */
+ }
+ return result;
+ }
+
+ private static boolean isX509CertificatesEquals(X509Certificate[] certs1,
+ X509Certificate[] certs2) {
+ if (certs1 == null && certs2 == null) {
+ return true;
+ }
+
+ /* Return false if only one of them is null */
+ if (certs1 == null || certs2 == null) {
+ return false;
+ }
+
+ if (certs1.length != certs2.length) {
+ return false;
+ }
+
+ for (int i = 0; i < certs1.length; i++) {
+ if (!isX509CertificateEquals(certs1[i], certs2[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.aidl b/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.aidl
new file mode 100644
index 0000000..62d5603
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2016, 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.wifi.hotspot2.pps;
+
+parcelable HomeSP;
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
new file mode 100644
index 0000000..2acc8be
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSP.java
@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) 2016, 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.wifi.hotspot2.pps;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.text.TextUtils;
+
+import java.util.Arrays;
+
+/**
+ * Class representing HomeSP subtree in PerProviderSubscription (PPS)
+ * Management Object (MO) tree.
+ *
+ * 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 {
+ /**
+ * FQDN (Fully Qualified Domain Name) of this home service provider.
+ */
+ public String fqdn = null;
+
+ /**
+ * Friendly name of this home service provider.
+ */
+ public String friendlyName = null;
+
+ /**
+ * List of Organization Identifiers (OIs) identifying a roaming consortium of
+ * which this provider is a member.
+ */
+ public long[] roamingConsortiumOIs = null;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(fqdn);
+ dest.writeString(friendlyName);
+ dest.writeLongArray(roamingConsortiumOIs);
+ }
+
+ @Override
+ public boolean equals(Object thatObject) {
+ if (this == thatObject) {
+ return true;
+ }
+ if (!(thatObject instanceof HomeSP)) {
+ return false;
+ }
+ HomeSP that = (HomeSP) thatObject;
+
+ return TextUtils.equals(fqdn, that.fqdn) &&
+ TextUtils.equals(friendlyName, that.friendlyName) &&
+ Arrays.equals(roamingConsortiumOIs, that.roamingConsortiumOIs);
+ }
+
+ public static final Creator<HomeSP> CREATOR =
+ new Creator<HomeSP>() {
+ @Override
+ public HomeSP createFromParcel(Parcel in) {
+ HomeSP homeSp = new HomeSP();
+ homeSp.fqdn = in.readString();
+ homeSp.friendlyName = in.readString();
+ homeSp.roamingConsortiumOIs = in.createLongArray();
+ return homeSp;
+ }
+
+ @Override
+ public HomeSP[] newArray(int size) {
+ return new HomeSP[size];
+ }
+ };
+}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
new file mode 100644
index 0000000..be11f0e
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 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.wifi.hotspot2;
+
+import static org.junit.Assert.assertTrue;
+
+import android.net.wifi.hotspot2.pps.Credential;
+import android.net.wifi.hotspot2.pps.HomeSP;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.hotspot2.PasspointConfiguration}.
+ */
+@SmallTest
+public class PasspointConfigurationTest {
+
+ private static HomeSP createHomeSp() {
+ HomeSP homeSp = new HomeSP();
+ homeSp.fqdn = "fqdn";
+ homeSp.friendlyName = "friendly name";
+ homeSp.roamingConsortiumOIs = new long[] {0x55, 0x66};
+ return homeSp;
+ }
+
+ private static Credential createCredential() {
+ Credential cred = new Credential();
+ cred.realm = "realm";
+ cred.userCredential = null;
+ cred.certCredential = null;
+ cred.simCredential = null;
+ cred.caCertificate = null;
+ cred.clientCertificateChain = null;
+ cred.clientPrivateKey = null;
+ return cred;
+ }
+
+ private static void verifyParcel(PasspointConfiguration writeConfig) throws Exception {
+ Parcel parcel = Parcel.obtain();
+ writeConfig.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0); // Rewind data position back to the beginning for read.
+ PasspointConfiguration readConfig =
+ PasspointConfiguration.CREATOR.createFromParcel(parcel);
+ assertTrue(readConfig.equals(writeConfig));
+ }
+
+ @Test
+ public void verifyParcelWithDefault() throws Exception {
+ verifyParcel(new PasspointConfiguration());
+ }
+
+ @Test
+ public void verifyParcelWithHomeSPAndCredential() throws Exception {
+ PasspointConfiguration config = new PasspointConfiguration();
+ config.homeSp = createHomeSp();
+ config.credential = createCredential();
+ verifyParcel(config);
+ }
+
+ @Test
+ public void verifyParcelWithHomeSPOnly() throws Exception {
+ PasspointConfiguration config = new PasspointConfiguration();
+ config.homeSp = createHomeSp();
+ verifyParcel(config);
+ }
+
+ @Test
+ public void verifyParcelWithCredentialOnly() throws Exception {
+ PasspointConfiguration config = new PasspointConfiguration();
+ config.credential = createCredential();
+ verifyParcel(config);
+ }
+}
\ No newline at end of file
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
new file mode 100644
index 0000000..68ac4ef
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 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.wifi.hotspot2.pps;
+
+import static org.junit.Assert.assertTrue;
+
+import android.net.wifi.FakeKeys;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.hotspot2.pps.CredentialTest}.
+ */
+@SmallTest
+public class CredentialTest {
+ private static Credential createCredential(Credential.UserCredential userCred,
+ Credential.CertificateCredential certCred,
+ Credential.SimCredential simCred,
+ X509Certificate caCert,
+ X509Certificate[] clientCertificateChain,
+ PrivateKey clientPrivateKey) {
+ Credential cred = new Credential();
+ cred.realm = "realm";
+ cred.userCredential = userCred;
+ cred.certCredential = certCred;
+ cred.simCredential = simCred;
+ cred.caCertificate = caCert;
+ cred.clientCertificateChain = clientCertificateChain;
+ cred.clientPrivateKey = clientPrivateKey;
+ return cred;
+ }
+
+ private static Credential createCredentialWithCertificateCredential() {
+ Credential.CertificateCredential certCred = new Credential.CertificateCredential();
+ certCred.certType = "x509v3";
+ certCred.certSha256FingerPrint = new byte[256];
+ return createCredential(null, certCred, null, FakeKeys.CA_CERT0,
+ new X509Certificate[] {FakeKeys.CLIENT_CERT}, FakeKeys.RSA_KEY1);
+ }
+
+ private static Credential createCredentialWithSimCredential() {
+ Credential.SimCredential simCred = new Credential.SimCredential();
+ simCred.imsi = "imsi";
+ simCred.eapType = 1;
+ return createCredential(null, null, simCred, null, null, null);
+ }
+
+ private static Credential createCredentialWithUserCredential() {
+ Credential.UserCredential userCred = new Credential.UserCredential();
+ userCred.username = "username";
+ userCred.password = "password";
+ userCred.eapType = 1;
+ userCred.nonEapInnerMethod = "MS-CHAP";
+ return createCredential(userCred, null, null, FakeKeys.CA_CERT0,
+ new X509Certificate[] {FakeKeys.CLIENT_CERT}, FakeKeys.RSA_KEY1);
+ }
+
+ private static void verifyParcel(Credential writeCred) {
+ Parcel parcel = Parcel.obtain();
+ writeCred.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0); // Rewind data position back to the beginning for read.
+ Credential readCred = Credential.CREATOR.createFromParcel(parcel);
+ assertTrue(readCred.equals(writeCred));
+ }
+
+ @Test
+ public void verifyParcelWithDefault() throws Exception {
+ verifyParcel(new Credential());
+ }
+
+ @Test
+ public void verifyParcelWithCertificateCredential() throws Exception {
+ verifyParcel(createCredentialWithCertificateCredential());
+ }
+
+ @Test
+ public void verifyParcelWithSimCredential() throws Exception {
+ verifyParcel(createCredentialWithSimCredential());
+ }
+
+ @Test
+ public void verifyParcelWithUserCredential() throws Exception {
+ verifyParcel(createCredentialWithUserCredential());
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
new file mode 100644
index 0000000..0d2da64
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSPTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 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.wifi.hotspot2.pps;
+
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.HashMap;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.hotspot2.pps.HomeSP}.
+ */
+@SmallTest
+public class HomeSPTest {
+ private static HomeSP createHomeSp() {
+ HomeSP homeSp = new HomeSP();
+ homeSp.fqdn = "fqdn";
+ homeSp.friendlyName = "friendly name";
+ homeSp.roamingConsortiumOIs = new long[] {0x55, 0x66};
+ return homeSp;
+ }
+
+ private static void verifyParcel(HomeSP writeHomeSp) throws Exception {
+ Parcel parcel = Parcel.obtain();
+ writeHomeSp.writeToParcel(parcel, 0);
+
+ parcel.setDataPosition(0); // Rewind data position back to the beginning for read.
+ HomeSP readHomeSp = HomeSP.CREATOR.createFromParcel(parcel);
+ assertTrue(readHomeSp.equals(writeHomeSp));
+ }
+
+ @Test
+ public void verifyParcelWithEmptyHomeSP() throws Exception {
+ verifyParcel(new HomeSP());
+ }
+
+ @Test
+ public void verifyParcelWithValidHomeSP() throws Exception {
+ verifyParcel(createHomeSp());
+ }
+}