summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2016-12-22 03:03:26 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2016-12-22 03:03:26 +0000
commit12c5e255507bceb0bdc915f709dd0275705df461 (patch)
treed263113633d2ee43dffec824323bb0df14b08a77
parent3121bb5254ff46122939a52e9e0d54ac39199eff (diff)
parent1dc52f076977039a6bf112885feca6638c05cd29 (diff)
Merge "hotspot2: ANQP elements cleanup Part 2"
-rw-r--r--service/java/com/android/server/wifi/hotspot2/PasspointMatchInfo.java13
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java8
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java67
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElement.java104
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElement.java162
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/ProtocolPortTuple.java108
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/RawByteElement.java56
-rw-r--r--tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/DomainNameElementTest.java112
-rw-r--r--tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElementTest.java131
-rw-r--r--tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElementTest.java117
-rw-r--r--tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ProtocolPortTupleTest.java92
-rw-r--r--tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/RawByteElementTest.java62
12 files changed, 927 insertions, 105 deletions
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointMatchInfo.java b/service/java/com/android/server/wifi/hotspot2/PasspointMatchInfo.java
index 9f26675ad..dccd2fd8a 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointMatchInfo.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointMatchInfo.java
@@ -6,6 +6,7 @@ import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType;
import com.android.server.wifi.hotspot2.anqp.HSConnectionCapabilityElement;
import com.android.server.wifi.hotspot2.anqp.HSWanMetricsElement;
import com.android.server.wifi.hotspot2.anqp.IPAddressTypeAvailabilityElement;
+import com.android.server.wifi.hotspot2.anqp.ProtocolPortTuple;
import java.util.HashMap;
import java.util.Map;
@@ -119,12 +120,12 @@ public class PasspointMatchInfo implements Comparable<PasspointMatchInfo> {
HSWanMetricsElement wm = (HSWanMetricsElement) anqp.get(ANQPElementType.HSWANMetrics);
if (wm != null) {
- if (wm.getStatus() != HSWanMetricsElement.LinkStatus.Up || wm.isCapped()) {
+ if (wm.getStatus() != HSWanMetricsElement.LINK_STATUS_UP || wm.isCapped()) {
score -= 1000;
} else {
long scaledSpeed =
- wm.getDlSpeed() * (255 - wm.getDlLoad()) * 8 +
- wm.getUlSpeed() * (255 - wm.getUlLoad()) * 2;
+ wm.getDownlinkSpeed() * (255 - wm.getDownlinkLoad()) * 8
+ + wm.getUplinkSpeed() * (255 - wm.getUplinkLoad()) * 2;
score += Math.min(scaledSpeed, 255000000L) >>> 23;
// Max value is 30 capped at 100Mb/s
}
@@ -176,9 +177,9 @@ public class PasspointMatchInfo implements Comparable<PasspointMatchInfo> {
private static int protoScore(HSConnectionCapabilityElement cce) {
int score = 0;
- for (HSConnectionCapabilityElement.ProtocolTuple tuple : cce.getStatusList()) {
- int sign = tuple.getStatus() == HSConnectionCapabilityElement.ProtoStatus.Open ?
- 1 : -1;
+ for (ProtocolPortTuple tuple : cce.getStatusList()) {
+ int sign = tuple.getStatus() == ProtocolPortTuple.PROTO_STATUS_OPEN
+ ? 1 : -1;
int elementScore = 1;
if (tuple.getProtocol() == IPPROTO_ICMP) {
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java b/service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java
index 6944a6e00..8ef75a600 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java
@@ -98,7 +98,7 @@ public class ANQPFactory {
case ANQP3GPPNetwork:
return new ThreeGPPNetworkElement(infoID, payload);
case ANQPDomName:
- return new DomainNameElement(infoID, payload);
+ return DomainNameElement.parse(payload);
case ANQPVendorSpec:
if (payload.remaining() > 5) {
int oi = payload.getInt();
@@ -135,11 +135,11 @@ public class ANQPFactory {
case HSFriendlyName:
return HSFriendlyNameElement.parse(payload);
case HSWANMetrics:
- return new HSWanMetricsElement(infoID, payload);
+ return HSWanMetricsElement.parse(payload);
case HSConnCapability:
- return new HSConnectionCapabilityElement(infoID, payload);
+ return HSConnectionCapabilityElement.parse(payload);
case HSOSUProviders:
- return new RawByteElement(infoID, payload);
+ return RawByteElement.parse(infoID, payload);
default:
throw new ProtocolException("Unknown element ID: " + infoID);
}
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java
index 0b5352eb8..35b39565e 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java
@@ -1,8 +1,25 @@
+/*
+ * 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 com.android.server.wifi.hotspot2.anqp;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wifi.ByteBufferReader;
-import java.net.ProtocolException;
+import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -10,21 +27,40 @@ import java.util.Collections;
import java.util.List;
/**
- * The Domain Name ANQP Element, IEEE802.11-2012 section 8.4.4.15
+ * The Domain Name ANQP Element, IEEE802.11-2012 section 8.4.4.15.
+ *
+ * Format:
+ * | Domain Name Field #1 (optional) | ...
+ * variable
+ *
+ * Domain Name Field Format:
+ * | Length | Domain Name |
+ * 1 variable
*/
public class DomainNameElement extends ANQPElement {
private final List<String> mDomains;
- public DomainNameElement(Constants.ANQPElementType infoID, ByteBuffer payload)
- throws ProtocolException {
- super(infoID);
- mDomains = new ArrayList<>();
+ @VisibleForTesting
+ public DomainNameElement(List<String> domains) {
+ super(Constants.ANQPElementType.ANQPDomName);
+ mDomains = domains;
+ }
+ /**
+ * Parse a DomainNameElement from the given buffer.
+ *
+ * @param payload The byte buffer to read from
+ * @return {@link DomainNameElement}
+ * @throws BufferUnderflowException
+ */
+ public static DomainNameElement parse(ByteBuffer payload) {
+ List<String> domains = new ArrayList<>();
while (payload.hasRemaining()) {
// Use latin-1 to decode for now - safe for ASCII and retains encoding
- mDomains.add(ByteBufferReader.readStringWithByteLength(
+ domains.add(ByteBufferReader.readStringWithByteLength(
payload, StandardCharsets.ISO_8859_1));
}
+ return new DomainNameElement(domains);
}
public List<String> getDomains() {
@@ -32,6 +68,23 @@ public class DomainNameElement extends ANQPElement {
}
@Override
+ public boolean equals(Object thatObject) {
+ if (this == thatObject) {
+ return true;
+ }
+ if (!(thatObject instanceof DomainNameElement)) {
+ return false;
+ }
+ DomainNameElement that = (DomainNameElement) thatObject;
+ return mDomains.equals(that.mDomains);
+ }
+
+ @Override
+ public int hashCode() {
+ return mDomains.hashCode();
+ }
+
+ @Override
public String toString() {
return "DomainName{" +
"mDomains=" + mDomains +
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElement.java
index d4b55dcb6..2c9a2b30c 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElement.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElement.java
@@ -1,6 +1,24 @@
+/*
+ * 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 com.android.server.wifi.hotspot2.anqp;
-import java.net.ProtocolException;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
@@ -10,64 +28,54 @@ import java.util.List;
* The Connection Capability vendor specific ANQP Element,
* Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00,
* section 4.5
+ *
+ * Format:
+ * | ProtoPort Tuple #1 (optiional) | ....
+ * 4
*/
public class HSConnectionCapabilityElement extends ANQPElement {
+ private final List<ProtocolPortTuple> mStatusList;
- public enum ProtoStatus {Closed, Open, Unknown}
-
- private final List<ProtocolTuple> mStatusList;
-
- public static class ProtocolTuple {
- private final int mProtocol;
- private final int mPort;
- private final ProtoStatus mStatus;
-
- private ProtocolTuple(ByteBuffer payload) throws ProtocolException {
- if (payload.remaining() < 4) {
- throw new ProtocolException("Runt protocol tuple: " + payload.remaining());
- }
- mProtocol = payload.get() & Constants.BYTE_MASK;
- mPort = payload.getShort() & Constants.SHORT_MASK;
- int statusNumber = payload.get() & Constants.BYTE_MASK;
- mStatus = statusNumber < ProtoStatus.values().length ?
- ProtoStatus.values()[statusNumber] :
- null;
- }
-
- public int getProtocol() {
- return mProtocol;
- }
-
- public int getPort() {
- return mPort;
- }
-
- public ProtoStatus getStatus() {
- return mStatus;
- }
+ @VisibleForTesting
+ public HSConnectionCapabilityElement(List<ProtocolPortTuple> statusList) {
+ super(Constants.ANQPElementType.HSConnCapability);
+ mStatusList = statusList;
+ }
- @Override
- public String toString() {
- return "ProtocolTuple{" +
- "mProtocol=" + mProtocol +
- ", mPort=" + mPort +
- ", mStatus=" + mStatus +
- '}';
+ /**
+ * Parse a HSConnectionCapabilityElement from the given buffer.
+ *
+ * @param payload The byte buffer to read from
+ * @return {@link HSConnectionCapabilityElement}
+ * @throws BufferUnderflowException
+ */
+ public static HSConnectionCapabilityElement parse(ByteBuffer payload) {
+ List<ProtocolPortTuple> statusList = new ArrayList<>();
+ while (payload.hasRemaining()) {
+ statusList.add(ProtocolPortTuple.parse(payload));
}
+ return new HSConnectionCapabilityElement(statusList);
}
- public HSConnectionCapabilityElement(Constants.ANQPElementType infoID, ByteBuffer payload)
- throws ProtocolException {
- super(infoID);
+ public List<ProtocolPortTuple> getStatusList() {
+ return Collections.unmodifiableList(mStatusList);
+ }
- mStatusList = new ArrayList<>();
- while (payload.hasRemaining()) {
- mStatusList.add(new ProtocolTuple(payload));
+ @Override
+ public boolean equals(Object thatObject) {
+ if (this == thatObject) {
+ return true;
+ }
+ if (!(thatObject instanceof HSConnectionCapabilityElement)) {
+ return false;
}
+ HSConnectionCapabilityElement that = (HSConnectionCapabilityElement) thatObject;
+ return mStatusList.equals(that.mStatusList);
}
- public List<ProtocolTuple> getStatusList() {
- return Collections.unmodifiableList(mStatusList);
+ @Override
+ public int hashCode() {
+ return mStatusList.hashCode();
}
@Override
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElement.java
index d76bfaf18..b55fefb9b 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElement.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElement.java
@@ -1,50 +1,113 @@
+/*
+ * 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 com.android.server.wifi.hotspot2.anqp;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wifi.ByteBufferReader;
+
import java.net.ProtocolException;
import java.nio.ByteBuffer;
-
-import static com.android.server.wifi.hotspot2.anqp.Constants.BYTE_MASK;
-import static com.android.server.wifi.hotspot2.anqp.Constants.INT_MASK;
-import static com.android.server.wifi.hotspot2.anqp.Constants.SHORT_MASK;
+import java.nio.ByteOrder;
/**
* The WAN Metrics vendor specific ANQP Element,
* Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00,
* section 4.4
+ *
+ * Format:
+ * | WAN Info | Downlink Speed | Uplink Speed | Downlink Load | Uplink Load | LMD |
+ * 1 4 4 1 1 2
+ *
+ * WAN Info Format:
+ * | Link Status | Symmetric Link | At Capacity | Reserved |
+ * B0 B1 B2 B3 B4 - B7
*/
public class HSWanMetricsElement extends ANQPElement {
+ public static final int LINK_STATUS_RESERVED = 0;
+ public static final int LINK_STATUS_UP = 1;
+ public static final int LINK_STATUS_DOWN = 2;
+ public static final int LINK_STATUS_TEST = 3;
+
+ @VisibleForTesting
+ public static final int EXPECTED_BUFFER_SIZE = 13;
- public enum LinkStatus {Reserved, Up, Down, Test}
+ @VisibleForTesting
+ public static final int LINK_STATUS_MASK = (1 << 0 | 1 << 1);
- private final LinkStatus mStatus;
+ @VisibleForTesting
+ public static final int SYMMETRIC_LINK_MASK = 1 << 2;
+
+ @VisibleForTesting
+ public static final int AT_CAPACITY_MASK = 1 << 3;
+
+ private static final int MAX_LOAD = 256;
+
+ private final int mStatus;
private final boolean mSymmetric;
private final boolean mCapped;
- private final long mDlSpeed;
- private final long mUlSpeed;
- private final int mDlLoad;
- private final int mUlLoad;
- private final int mLMD;
+ private final long mDownlinkSpeed;
+ private final long mUplinkSpeed;
+ private final int mDownlinkLoad;
+ private final int mUplinkLoad;
+ private final int mLMD; // Load Measurement Duration.
+
+ @VisibleForTesting
+ public HSWanMetricsElement(int status, boolean symmetric, boolean capped, long downlinkSpeed,
+ long uplinkSpeed, int downlinkLoad, int uplinkLoad, int lmd) {
+ super(Constants.ANQPElementType.HSWANMetrics);
+ mStatus = status;
+ mSymmetric = symmetric;
+ mCapped = capped;
+ mDownlinkSpeed = downlinkSpeed;
+ mUplinkSpeed = uplinkSpeed;
+ mDownlinkLoad = downlinkLoad;
+ mUplinkLoad = uplinkLoad;
+ mLMD = lmd;
+ }
- public HSWanMetricsElement(Constants.ANQPElementType infoID, ByteBuffer payload)
+ /**
+ * Parse a HSWanMetricsElement from the given buffer.
+ *
+ * @param payload The byte buffer to read from
+ * @return {@link HSWanMetricsElement}
+ * @throws ProtocolException
+ */
+ public static HSWanMetricsElement parse(ByteBuffer payload)
throws ProtocolException {
- super(infoID);
-
- if (payload.remaining() != 13) {
- throw new ProtocolException("Bad WAN metrics length: " + payload.remaining());
+ if (payload.remaining() != EXPECTED_BUFFER_SIZE) {
+ throw new ProtocolException("Unexpected buffer size: " + payload.remaining());
}
- int status = payload.get() & BYTE_MASK;
- mStatus = LinkStatus.values()[status & 0x03];
- mSymmetric = (status & 0x04) != 0;
- mCapped = (status & 0x08) != 0;
- mDlSpeed = payload.getInt() & INT_MASK;
- mUlSpeed = payload.getInt() & INT_MASK;
- mDlLoad = payload.get() & BYTE_MASK;
- mUlLoad = payload.get() & BYTE_MASK;
- mLMD = payload.getShort() & SHORT_MASK;
+ int wanInfo = payload.get() & 0xFF;
+ int status = wanInfo & LINK_STATUS_MASK;
+ boolean symmetric = (wanInfo & SYMMETRIC_LINK_MASK) != 0;
+ boolean capped = (wanInfo & AT_CAPACITY_MASK) != 0;
+ long downlinkSpeed = ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 4)
+ & 0xFFFFFFFFL;
+ long uplinkSpeed = ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 4)
+ & 0xFFFFFFFFL;
+ int downlinkLoad = payload.get() & 0xFF;
+ int uplinkLoad = payload.get() & 0xFF;
+ int lmd = (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) & 0xFFFF;
+ return new HSWanMetricsElement(status, symmetric, capped, downlinkSpeed, uplinkSpeed,
+ downlinkLoad, uplinkLoad, lmd);
}
- public LinkStatus getStatus() {
+ public int getStatus() {
return mStatus;
}
@@ -56,20 +119,20 @@ public class HSWanMetricsElement extends ANQPElement {
return mCapped;
}
- public long getDlSpeed() {
- return mDlSpeed;
+ public long getDownlinkSpeed() {
+ return mDownlinkSpeed;
}
- public long getUlSpeed() {
- return mUlSpeed;
+ public long getUplinkSpeed() {
+ return mUplinkSpeed;
}
- public int getDlLoad() {
- return mDlLoad;
+ public int getDownlinkLoad() {
+ return mDownlinkLoad;
}
- public int getUlLoad() {
- return mUlLoad;
+ public int getUplinkLoad() {
+ return mUplinkLoad;
}
public int getLMD() {
@@ -77,13 +140,38 @@ public class HSWanMetricsElement extends ANQPElement {
}
@Override
+ public boolean equals(Object thatObject) {
+ if (this == thatObject) {
+ return true;
+ }
+ if (!(thatObject instanceof HSWanMetricsElement)) {
+ return false;
+ }
+ HSWanMetricsElement that = (HSWanMetricsElement) thatObject;
+ return mStatus == that.mStatus
+ && mSymmetric == that.mSymmetric
+ && mCapped == that.mCapped
+ && mDownlinkSpeed == that.mDownlinkSpeed
+ && mUplinkSpeed == that.mUplinkSpeed
+ && mDownlinkLoad == that.mDownlinkLoad
+ && mUplinkLoad == that.mUplinkLoad
+ && mLMD == that.mLMD;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) (mStatus + mDownlinkSpeed + mUplinkSpeed + mDownlinkLoad
+ + mUplinkLoad + mLMD);
+ }
+
+ @Override
public String toString() {
return String.format("HSWanMetrics{mStatus=%s, mSymmetric=%s, mCapped=%s, " +
"mDlSpeed=%d, mUlSpeed=%d, mDlLoad=%f, mUlLoad=%f, mLMD=%d}",
mStatus, mSymmetric, mCapped,
- mDlSpeed, mUlSpeed,
- (double)mDlLoad * 100.0 / 256.0,
- (double)mUlLoad * 100.0 / 256.0,
+ mDownlinkSpeed, mUplinkSpeed,
+ mDownlinkLoad * 100.0 / MAX_LOAD,
+ mUplinkLoad * 100.0 / MAX_LOAD,
mLMD);
}
}
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/ProtocolPortTuple.java b/service/java/com/android/server/wifi/hotspot2/anqp/ProtocolPortTuple.java
new file mode 100644
index 000000000..c097ad349
--- /dev/null
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/ProtocolPortTuple.java
@@ -0,0 +1,108 @@
+/*
+ * 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 com.android.server.wifi.hotspot2.anqp;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wifi.ByteBufferReader;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * The ProtoPort Tuple used by Connection Capability vendor specific ANQP Element,
+ * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00,
+ * section 4.5
+ *
+ * Format:
+ * | IP Procotol | Port Number | Status |
+ * 1 2 1
+ */
+public class ProtocolPortTuple {
+ /**
+ * Number of raw bytes needed for the tuple.
+ */
+ @VisibleForTesting
+ public static final int RAW_BYTE_SIZE = 4;
+
+ public static final int PROTO_STATUS_CLOSED = 0;
+ public static final int PROTO_STATUS_OPEN = 1;
+ public static final int PROTO_STATUS_UNKNOWN = 2;
+
+ private final int mProtocol;
+ private final int mPort;
+ private final int mStatus;
+
+ @VisibleForTesting
+ public ProtocolPortTuple(int protocol, int port, int status) {
+ mProtocol = protocol;
+ mPort = port;
+ mStatus = status;
+ }
+
+ /**
+ * Parse a ProtocolPortTuple from the given buffer.
+ *
+ * @param payload The byte buffer to read from
+ * @return {@link ProtocolPortTuple}
+ * @throws BufferUnderflowException
+ */
+ public static ProtocolPortTuple parse(ByteBuffer payload) {
+ int protocol = payload.get();
+ int port = (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2)
+ & 0xFFFF;
+ int status = payload.get() & 0xFF;
+ return new ProtocolPortTuple(protocol, port, status);
+ }
+
+ public int getProtocol() {
+ return mProtocol;
+ }
+
+ public int getPort() {
+ return mPort;
+ }
+
+ public int getStatus() {
+ return mStatus;
+ }
+
+ @Override
+ public boolean equals(Object thatObject) {
+ if (this == thatObject) {
+ return true;
+ }
+ if (!(thatObject instanceof ProtocolPortTuple)) {
+ return false;
+ }
+ ProtocolPortTuple that = (ProtocolPortTuple) thatObject;
+ return mProtocol == that.mProtocol
+ && mPort == that.mPort
+ && mStatus == that.mStatus;
+ }
+
+ @Override
+ public int hashCode() {
+ return (mProtocol * 31 + mPort) * 31 + mStatus;
+ }
+
+ @Override
+ public String toString() {
+ return "ProtocolTuple{" + "mProtocol=" + mProtocol + ", mPort=" + mPort
+ + ", mStatus=" + mStatus + '}';
+ }
+}
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/RawByteElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/RawByteElement.java
index ae301c425..633147d45 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/RawByteElement.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/RawByteElement.java
@@ -1,6 +1,25 @@
+/*
+ * 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 com.android.server.wifi.hotspot2.anqp;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.nio.ByteBuffer;
+import java.util.Arrays;
/**
* An object holding the raw octets of an ANQP element as provided by the wpa_supplicant.
@@ -8,13 +27,44 @@ import java.nio.ByteBuffer;
public class RawByteElement extends ANQPElement {
private final byte[] mPayload;
- public RawByteElement(Constants.ANQPElementType infoID, ByteBuffer payload) {
+ @VisibleForTesting
+ public RawByteElement(Constants.ANQPElementType infoID, byte[] payload) {
super(infoID);
- mPayload = new byte[payload.remaining()];
- payload.get(mPayload);
+ mPayload = payload;
+ }
+
+ /**
+ * Parse a RawByteElement from the given buffer.
+ *
+ * @param payload The byte buffer to read from
+ * @return {@link HSConnectionCapabilityElement}
+ */
+ public static RawByteElement parse(Constants.ANQPElementType infoID, ByteBuffer payload) {
+ byte[] rawBytes = new byte[payload.remaining()];
+ if (payload.hasRemaining()) {
+ payload.get(rawBytes);
+ }
+ return new RawByteElement(infoID, rawBytes);
}
public byte[] getPayload() {
return mPayload;
}
+
+ @Override
+ public boolean equals(Object thatObject) {
+ if (this == thatObject) {
+ return true;
+ }
+ if (!(thatObject instanceof RawByteElement)) {
+ return false;
+ }
+ RawByteElement that = (RawByteElement) thatObject;
+ return getID() == that.getID() && Arrays.equals(mPayload, that.mPayload);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(mPayload);
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/DomainNameElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/DomainNameElementTest.java
new file mode 100644
index 000000000..d17a7fa1d
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/DomainNameElementTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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 com.android.server.wifi.hotspot2.anqp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.DomainNameElement}.
+ */
+@SmallTest
+public class DomainNameElementTest {
+ private static final String TEST_DOMAIN_NAME1 = "test1.com";
+ private static final String TEST_DOMAIN_NAME2 = "test2.com";
+
+ /**
+ * Helper function for appending a Domain Name to an output stream.
+ *
+ * @param stream Stream to write to
+ * @param domain The domain name string
+ * @throws IOException
+ */
+ private void appendDomain(ByteArrayOutputStream stream, String domain) throws IOException {
+ byte[] domainBytes = domain.getBytes(StandardCharsets.ISO_8859_1);
+ stream.write((byte) domainBytes.length);
+ stream.write(domainBytes);
+ }
+
+ /**
+ * Helper function for generating test data.
+ *
+ * @return byte[] of data
+ * @throws IOException
+ */
+ private byte[] getTestData(String[] domains) throws IOException {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ for (String domain : domains) {
+ appendDomain(stream, domain);
+ }
+ return stream.toByteArray();
+ }
+
+ /**
+ * Verify that a DomainNameElement with empty domain list will be returned when parsing an
+ * empty buffer.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void parseEmptyBuffer() throws Exception {
+ assertTrue(DomainNameElement.parse(ByteBuffer.allocate(0)).getDomains().isEmpty());
+ }
+
+ /**
+ * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer
+ * (missing a byte at the end).
+ *
+ * @throws Exception
+ */
+ @Test(expected = BufferUnderflowException.class)
+ public void parseTruncatedBuffer() throws Exception {
+ ByteBuffer buffer = ByteBuffer.wrap(getTestData(new String[] {TEST_DOMAIN_NAME1}));
+ buffer.limit(buffer.remaining() - 1);
+ DomainNameElement.parse(buffer);
+ }
+
+ /**
+ * Verify that a DomainNameElement with expected domain list will be returned when parsing a
+ * buffer contained valid domain name list.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void parseBufferWithValidDomainNames() throws Exception {
+ byte[] testData = getTestData(new String[] {TEST_DOMAIN_NAME1, TEST_DOMAIN_NAME2});
+ ByteBuffer buffer = ByteBuffer.wrap(testData);
+
+ // Setup expected element.
+ List<String> domainList = new ArrayList<>();
+ domainList.add(TEST_DOMAIN_NAME1);
+ domainList.add(TEST_DOMAIN_NAME2);
+ DomainNameElement expectedElement = new DomainNameElement(domainList);
+
+ assertEquals(expectedElement, DomainNameElement.parse(buffer));
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElementTest.java
new file mode 100644
index 000000000..aef2b86d1
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSConnectionCapabilityElementTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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 com.android.server.wifi.hotspot2.anqp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.HSConnectionCapabilityElement}.
+ */
+@SmallTest
+public class HSConnectionCapabilityElementTest {
+ private static final ProtocolPortTuple TEST_TUPLE1 =
+ new ProtocolPortTuple(1, 2, ProtocolPortTuple.PROTO_STATUS_CLOSED);
+ private static final ProtocolPortTuple TEST_TUPLE2 =
+ new ProtocolPortTuple(3, 4, ProtocolPortTuple.PROTO_STATUS_OPEN);
+
+ /**
+ * Helper function for writing a ProtocolPortTuple into a buffer.
+ *
+ * @param buffer The buffer to write to
+ * @param tuple The tuple to write
+ */
+ private void appendProtocolPortTuple(ByteBuffer buffer, ProtocolPortTuple tuple) {
+ buffer.put((byte) tuple.getProtocol());
+ buffer.putShort((short) tuple.getPort());
+ buffer.put((byte) tuple.getStatus());
+ }
+
+ /**
+ * Helper function for generating a buffer with test data.
+ *
+ * @param tuples Tuples to put in the buffer
+ * @return {@link ByteBuffer}
+ */
+ private ByteBuffer getTestBuffer(ProtocolPortTuple[] tuples) {
+ ByteBuffer buffer = ByteBuffer.allocate(tuples.length * ProtocolPortTuple.RAW_BYTE_SIZE)
+ .order(ByteOrder.LITTLE_ENDIAN);
+ for (ProtocolPortTuple tuple : tuples) {
+ appendProtocolPortTuple(buffer, tuple);
+ }
+ buffer.position(0);
+ return buffer;
+ }
+
+ /**
+ * Verify that a HSConnectionCapabilityElement with an empty status list will be returned
+ * when parsing an empty buffer.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void parseEmptyBuffer() throws Exception {
+ HSConnectionCapabilityElement element =
+ HSConnectionCapabilityElement.parse(ByteBuffer.allocate(0));
+ assertTrue(element.getStatusList().isEmpty());
+ }
+
+ /**
+ * Verify that BufferUnderflowException will be thrown when parsing a buffer without
+ * the complete tuple data (missing status field).
+ *
+ * @throws Exception
+ */
+ @Test(expected = BufferUnderflowException.class)
+ public void parseBufferWithLessThanMinimumSize() throws Exception {
+ ByteBuffer buffer = ByteBuffer.allocate(ProtocolPortTuple.RAW_BYTE_SIZE - 1);
+ buffer.put(new byte[ProtocolPortTuple.RAW_BYTE_SIZE - 1]);
+ buffer.position(0);
+ HSConnectionCapabilityElement.parse(buffer);
+ }
+
+ /**
+ * Verify that BufferUnderflowException will be thrown when parsing a buffer that contained
+ * incomplete bytes for a tuple.
+ *
+ * @throws Exception
+ */
+ @Test(expected = BufferUnderflowException.class)
+ public void parseBufferWithIncompleteTupleBytes() throws Exception {
+ // Construct a buffer which will contained a tuple and an extra byte at the end.
+ ByteBuffer buffer = ByteBuffer.allocate(ProtocolPortTuple.RAW_BYTE_SIZE + 1);
+ appendProtocolPortTuple(buffer, TEST_TUPLE1);
+ buffer.put((byte) 0);
+ buffer.position(0);
+ HSConnectionCapabilityElement.parse(buffer);
+ }
+
+ /**
+ * Verify that the expected HSConnectionCapabilityElement is returned when parsing
+ * a buffer containing the test data.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void parseBufferWithTestData() throws Exception {
+ ByteBuffer buffer = getTestBuffer(new ProtocolPortTuple[] {TEST_TUPLE1, TEST_TUPLE2});
+
+ // Setup expected element.
+ List<ProtocolPortTuple> tupleList = new ArrayList<>();
+ tupleList.add(TEST_TUPLE1);
+ tupleList.add(TEST_TUPLE2);
+ HSConnectionCapabilityElement expected = new HSConnectionCapabilityElement(tupleList);
+
+ assertEquals(expected, HSConnectionCapabilityElement.parse(buffer));
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElementTest.java
new file mode 100644
index 000000000..8c53fe3a7
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/HSWanMetricsElementTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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 com.android.server.wifi.hotspot2.anqp;
+
+import static org.junit.Assert.assertEquals;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+
+import java.net.ProtocolException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.HSWanMetricsElement}.
+ */
+@SmallTest
+public class HSWanMetricsElementTest {
+ private static final int TEST_LINK_STATUS = HSWanMetricsElement.LINK_STATUS_UP;
+ private static final boolean TEST_SYMMETRIC_LINK = true;
+ private static final boolean TEST_AT_CAPACITY = true;
+ private static final long TEST_DOWNLINK_SPEED = 0x1234556L;
+ private static final long TEST_UPLINK_SPEED = 0x342343L;
+ private static final int TEST_DOWNLINK_LOAD = 0x23;
+ private static final int TEST_UPLINK_LOAD = 0x45;
+ private static final int TEST_LMD = 0x2132;
+
+ /**
+ * Helper function for generating a ByteBuffer with the test data.
+ *
+ * @return {@link ByteBuffer}
+ */
+ private ByteBuffer getTestBuffer() {
+ ByteBuffer buffer = ByteBuffer.allocate(HSWanMetricsElement.EXPECTED_BUFFER_SIZE)
+ .order(ByteOrder.LITTLE_ENDIAN);
+ int wanInfo = TEST_LINK_STATUS & HSWanMetricsElement.LINK_STATUS_MASK;
+ if (TEST_SYMMETRIC_LINK) wanInfo |= HSWanMetricsElement.SYMMETRIC_LINK_MASK;
+ if (TEST_AT_CAPACITY) wanInfo |= HSWanMetricsElement.AT_CAPACITY_MASK;
+ buffer.put((byte) wanInfo);
+ buffer.putInt((int) (TEST_DOWNLINK_SPEED & 0xFFFFFFFFL));
+ buffer.putInt((int) (TEST_UPLINK_SPEED & 0xFFFFFFFFL));
+ buffer.put((byte) (TEST_DOWNLINK_LOAD & 0xFF));
+ buffer.put((byte) (TEST_UPLINK_LOAD & 0xFF));
+ buffer.putShort((short) (TEST_LMD & 0xFFFF));
+ buffer.position(0);
+ return buffer;
+ }
+
+ /**
+ * Verify that ProtocolException will be thrown when parsing an empty buffer.
+ *
+ * @throws Exception
+ */
+ @Test(expected = ProtocolException.class)
+ public void parseEmptyBuffer() throws Exception {
+ HSWanMetricsElement.parse(ByteBuffer.allocate(0));
+ }
+
+ /**
+ * Verify that ProtocolException will be thrown when a buffer with size less than the
+ * expected.
+ *
+ * @throws Exception
+ */
+ @Test(expected = ProtocolException.class)
+ public void parseBufferWithLessThanExpectedSize() throws Exception {
+ ByteBuffer buffer = ByteBuffer.allocate(HSWanMetricsElement.EXPECTED_BUFFER_SIZE - 1);
+ buffer.put(new byte[HSWanMetricsElement.EXPECTED_BUFFER_SIZE - 1]);
+ buffer.position(0);
+ HSWanMetricsElement.parse(buffer);
+ }
+
+ /**
+ * Verify that ProtocolException will be thrown when a buffer with size more than the
+ * expected.
+ *
+ * @throws Exception
+ */
+ @Test(expected = ProtocolException.class)
+ public void parseBufferWithMoreThanExpectedSize() throws Exception {
+ ByteBuffer buffer = ByteBuffer.allocate(HSWanMetricsElement.EXPECTED_BUFFER_SIZE + 1);
+ buffer.put(new byte[HSWanMetricsElement.EXPECTED_BUFFER_SIZE + 1]);
+ buffer.position(0);
+ HSWanMetricsElement.parse(buffer);
+ }
+
+ /**
+ * Verify that the expected HSWanMetricsElement is returned when parsing
+ * a buffer containing the test data.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void parseBufferWithTestData() throws Exception {
+ ByteBuffer buffer = getTestBuffer();
+ HSWanMetricsElement expectedElement = new HSWanMetricsElement(
+ TEST_LINK_STATUS, TEST_SYMMETRIC_LINK, TEST_AT_CAPACITY,
+ TEST_DOWNLINK_SPEED, TEST_UPLINK_SPEED, TEST_DOWNLINK_LOAD,
+ TEST_UPLINK_LOAD, TEST_LMD);
+ assertEquals(expectedElement, HSWanMetricsElement.parse(buffer));
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ProtocolPortTupleTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ProtocolPortTupleTest.java
new file mode 100644
index 000000000..b4bfaf1c5
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ProtocolPortTupleTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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 com.android.server.wifi.hotspot2.anqp;
+
+import static org.junit.Assert.assertEquals;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.ProtocolPortTuple}.
+ */
+@SmallTest
+public class ProtocolPortTupleTest {
+ private static final int TEST_PROTOCOL = 1;
+ private static final int TEST_PORT = 2;
+ private static final int TEST_STATUS = ProtocolPortTuple.PROTO_STATUS_CLOSED;
+
+ /**
+ * Helper function for generating a buffer with test data.
+ *
+ * @param protocol Protocol value
+ * @param port Port value
+ * @param status Status value
+ * @return {@link ByteBuffer}
+ */
+ private ByteBuffer getTestBuffer(int protocol, int port, int status) {
+ ByteBuffer buffer = ByteBuffer.allocate(ProtocolPortTuple.RAW_BYTE_SIZE)
+ .order(ByteOrder.LITTLE_ENDIAN);
+ buffer.put((byte) protocol);
+ buffer.putShort((short) port);
+ buffer.put((byte) status);
+ buffer.position(0);
+ return buffer;
+ }
+
+ /**
+ * Verify that BufferUnderflowException will be thrown when parsing an empty buffer.
+ *
+ * @throws Exception
+ */
+ @Test(expected = BufferUnderflowException.class)
+ public void parseEmptyBuffer() throws Exception {
+ ProtocolPortTuple.parse(ByteBuffer.allocate(0));
+ }
+
+ /**
+ * Verify that BufferUnderflowException will be thrown when parsing a buffer without
+ * the complete tuple data (missing status field).
+ *
+ * @throws Exception
+ */
+ @Test(expected = BufferUnderflowException.class)
+ public void parseBufferWithIncompleteData() throws Exception {
+ ByteBuffer buffer = ByteBuffer.allocate(ProtocolPortTuple.RAW_BYTE_SIZE - 1);
+ buffer.put(new byte[ProtocolPortTuple.RAW_BYTE_SIZE - 1]);
+ buffer.position(0);
+ ProtocolPortTuple.parse(buffer);
+ }
+
+ /**
+ * Verify that the expected ProtocolPortTuple is returned when parsing a buffer contained
+ * the test data.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void parseBufferWithTestData() throws Exception {
+ ByteBuffer buffer = getTestBuffer(TEST_PROTOCOL, TEST_PORT, TEST_STATUS);
+ ProtocolPortTuple expected = new ProtocolPortTuple(TEST_PROTOCOL, TEST_PORT, TEST_STATUS);
+ assertEquals(expected, ProtocolPortTuple.parse(buffer));
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/RawByteElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/RawByteElementTest.java
new file mode 100644
index 000000000..e61797a87
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/RawByteElementTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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 com.android.server.wifi.hotspot2.anqp;
+
+import static org.junit.Assert.assertEquals;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.RawByteElement}.
+ */
+@SmallTest
+public class RawByteElementTest {
+ private static final Constants.ANQPElementType TEST_ELEMENT_ID =
+ Constants.ANQPElementType.HSOSUProviders;
+
+ /**
+ * Verify that a RawByteElement with an empty payload will be returned when parsing
+ * an empty buffer.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void parseEmptyBuffer() throws Exception {
+ byte[] data = new byte[0];
+ RawByteElement actual = RawByteElement.parse(TEST_ELEMENT_ID, ByteBuffer.wrap(data));
+ RawByteElement expected = new RawByteElement(TEST_ELEMENT_ID, data);
+ assertEquals(expected, actual);
+ }
+
+ /**
+ * Verify that the expected RawByteElement will be returned when parsing a non-empty
+ * buffer.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void parseNonEmptyBuffer() throws Exception {
+ byte[] data = new byte[10];
+ RawByteElement actual = RawByteElement.parse(TEST_ELEMENT_ID, ByteBuffer.wrap(data));
+ RawByteElement expected = new RawByteElement(TEST_ELEMENT_ID, data);
+ assertEquals(expected, actual);
+ }
+}