summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Etan Cohen <etancohen@google.com> 2017-09-27 13:58:42 -0700
committer Etan Cohen <etancohen@google.com> 2017-10-19 14:48:29 -0700
commit5a100a07b10424f45567e2efa6f11cf0110eb6b9 (patch)
tree76f824e5c397065cb7d5c8fe278aaf617e4ea2af
parentf73f9ed57068d8256ae386f7a8be6ee2dda7cbf2 (diff)
[RTT2] Add support for RTT to Wi-Fi Aware peers
Add API to specify RTT requests to Wi-FI Aware peers specified either using their MAC address (out-of-band discovery) or their PeerHandle (in-band discovery). Bug: 65015034 Test: unit tests + integration tests Change-Id: I1cb8e90cab7c1acc621576703c9d0c6f4f5ac8d4
-rw-r--r--wifi/java/android/net/wifi/rtt/RangingRequest.java159
-rw-r--r--wifi/java/android/net/wifi/rtt/RangingResult.java66
-rw-r--r--wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java54
3 files changed, 265 insertions, 14 deletions
diff --git a/wifi/java/android/net/wifi/rtt/RangingRequest.java b/wifi/java/android/net/wifi/rtt/RangingRequest.java
index 997b6800e97c..42ea05ef6dff 100644
--- a/wifi/java/android/net/wifi/rtt/RangingRequest.java
+++ b/wifi/java/android/net/wifi/rtt/RangingRequest.java
@@ -17,13 +17,22 @@
package android.net.wifi.rtt;
import android.net.wifi.ScanResult;
+import android.net.wifi.aware.AttachCallback;
+import android.net.wifi.aware.DiscoverySessionCallback;
+import android.net.wifi.aware.IdentityChangedListener;
+import android.net.wifi.aware.PeerHandle;
+import android.net.wifi.aware.WifiAwareManager;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import libcore.util.HexEncoding;
+
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.StringJoiner;
/**
@@ -94,11 +103,34 @@ public final class RangingRequest implements Parcelable {
}
/** @hide */
- public void enforceValidity() {
+ public void enforceValidity(boolean awareSupported) {
if (mRttPeers.size() > MAX_PEERS) {
throw new IllegalArgumentException(
"Ranging to too many peers requested. Use getMaxPeers() API to get limit.");
}
+
+ for (RttPeer peer: mRttPeers) {
+ if (peer instanceof RttPeerAp) {
+ RttPeerAp apPeer = (RttPeerAp) peer;
+ if (apPeer.scanResult == null || apPeer.scanResult.BSSID == null) {
+ throw new IllegalArgumentException("Invalid AP peer specification");
+ }
+ } else if (peer instanceof RttPeerAware) {
+ if (!awareSupported) {
+ throw new IllegalArgumentException(
+ "Request contains Aware peers - but Aware isn't supported on this "
+ + "device");
+ }
+
+ RttPeerAware awarePeer = (RttPeerAware) peer;
+ if (awarePeer.peerMacAddress == null && awarePeer.peerHandle == null) {
+ throw new IllegalArgumentException("Invalid Aware peer specification");
+ }
+ } else {
+ throw new IllegalArgumentException(
+ "Request contains unknown peer specification types");
+ }
+ }
}
/**
@@ -144,6 +176,44 @@ public final class RangingRequest implements Parcelable {
}
/**
+ * Add the device specified by the {@code peerMacAddress} to the list of devices with
+ * which to measure range.
+ *
+ * The MAC address may be obtained out-of-band from a peer Wi-Fi Aware device. A Wi-Fi
+ * Aware device may obtain its MAC address using the {@link IdentityChangedListener}
+ * provided to
+ * {@link WifiAwareManager#attach(AttachCallback, IdentityChangedListener, Handler)}.
+ *
+ * * Note: in order to use this API the device must support Wi-Fi Aware
+ * {@link android.net.wifi.aware}.
+ *
+ * @param peerMacAddress The MAC address of the Wi-Fi Aware peer.
+ * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ */
+ public Builder addWifiAwarePeer(byte[] peerMacAddress) {
+ mRttPeers.add(new RttPeerAware(peerMacAddress));
+ return this;
+ }
+
+ /**
+ * Add a device specified by a {@link PeerHandle} to the list of devices with which to
+ * measure range.
+ *
+ * The {@link PeerHandle} may be obtained as part of the Wi-Fi Aware discovery process. E.g.
+ * using {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], List)}.
+ *
+ * Note: in order to use this API the device must support Wi-Fi Aware
+ * {@link android.net.wifi.aware}.
+ *
+ * @param peerHandle The peer handler of the peer Wi-Fi Aware device.
+ * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
+ */
+ public Builder addWifiAwarePeer(PeerHandle peerHandle) {
+ mRttPeers.add(new RttPeerAware(peerHandle));
+ return this;
+ }
+
+ /**
* Build {@link RangingRequest} given the current configurations made on the
* builder.
*/
@@ -234,4 +304,89 @@ public final class RangingRequest implements Parcelable {
return scanResult.hashCode();
}
}
-} \ No newline at end of file
+
+ /** @hide */
+ public static class RttPeerAware implements RttPeer, Parcelable {
+ public PeerHandle peerHandle;
+ public byte[] peerMacAddress;
+
+ public RttPeerAware(PeerHandle peerHandle) {
+ if (peerHandle == null) {
+ throw new IllegalArgumentException("Null peerHandle");
+ }
+ this.peerHandle = peerHandle;
+ peerMacAddress = null;
+ }
+
+ public RttPeerAware(byte[] peerMacAddress) {
+ if (peerMacAddress == null) {
+ throw new IllegalArgumentException("Null peerMacAddress");
+ }
+
+ this.peerMacAddress = peerMacAddress;
+ peerHandle = null;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (peerHandle == null) {
+ dest.writeBoolean(false);
+ dest.writeByteArray(peerMacAddress);
+ } else {
+ dest.writeBoolean(true);
+ dest.writeInt(peerHandle.peerId);
+ }
+ }
+
+ public static final Creator<RttPeerAware> CREATOR = new Creator<RttPeerAware>() {
+ @Override
+ public RttPeerAware[] newArray(int size) {
+ return new RttPeerAware[size];
+ }
+
+ @Override
+ public RttPeerAware createFromParcel(Parcel in) {
+ boolean peerHandleAvail = in.readBoolean();
+ if (peerHandleAvail) {
+ return new RttPeerAware(new PeerHandle(in.readInt()));
+ } else {
+ return new RttPeerAware(in.createByteArray());
+ }
+ }
+ };
+
+ @Override
+ public String toString() {
+ return new StringBuilder("RttPeerAware: peerHandle=").append(
+ peerHandle == null ? "<null>" : Integer.toString(peerHandle.peerId)).append(
+ ", peerMacAddress=").append(peerMacAddress == null ? "<null>"
+ : new String(HexEncoding.encode(peerMacAddress))).toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof RttPeerAware)) {
+ return false;
+ }
+
+ RttPeerAware lhs = (RttPeerAware) o;
+
+ return Objects.equals(peerHandle, lhs.peerHandle) && Arrays.equals(peerMacAddress,
+ lhs.peerMacAddress);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(peerHandle.peerId, peerMacAddress);
+ }
+ }
+}
diff --git a/wifi/java/android/net/wifi/rtt/RangingResult.java b/wifi/java/android/net/wifi/rtt/RangingResult.java
index 918803ef2018..d3a520cb4e56 100644
--- a/wifi/java/android/net/wifi/rtt/RangingResult.java
+++ b/wifi/java/android/net/wifi/rtt/RangingResult.java
@@ -16,6 +16,7 @@
package android.net.wifi.rtt;
+import android.net.wifi.aware.PeerHandle;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
@@ -42,6 +43,7 @@ public final class RangingResult implements Parcelable {
private final int mStatus;
private final byte[] mMac;
+ private final PeerHandle mPeerHandle;
private final int mDistanceCm;
private final int mDistanceStdDevCm;
private final int mRssi;
@@ -52,6 +54,19 @@ public final class RangingResult implements Parcelable {
long timestamp) {
mStatus = status;
mMac = mac;
+ mPeerHandle = null;
+ mDistanceCm = distanceCm;
+ mDistanceStdDevCm = distanceStdDevCm;
+ mRssi = rssi;
+ mTimestamp = timestamp;
+ }
+
+ /** @hide */
+ public RangingResult(int status, PeerHandle peerHandle, int distanceCm, int distanceStdDevCm,
+ int rssi, long timestamp) {
+ mStatus = status;
+ mMac = null;
+ mPeerHandle = peerHandle;
mDistanceCm = distanceCm;
mDistanceStdDevCm = distanceStdDevCm;
mRssi = rssi;
@@ -70,13 +85,30 @@ public final class RangingResult implements Parcelable {
* @return The MAC address of the device whose range measurement was requested. Will correspond
* to the MAC address of the device in the {@link RangingRequest}.
* <p>
- * Always valid (i.e. when {@link #getStatus()} is either SUCCESS or FAIL.
+ * Will return a {@code null} for results corresponding to requests issued using a {@code
+ * PeerHandle}, i.e. using the {@link RangingRequest.Builder#addWifiAwarePeer(PeerHandle)} API.
+ * <p>
+ * Valid whether {@link #getStatus()} is SUCCESS or FAIL.
*/
public byte[] getMacAddress() {
return mMac;
}
/**
+ * @return The PeerHandle of the device whose reange measurement was requested. Will correspond
+ * to the PeerHandle of the devices requested using
+ * {@link RangingRequest.Builder#addWifiAwarePeer(PeerHandle)}.
+ * <p>
+ * Will return a {@code null} for results corresponding to requests issued using a MAC address.
+ * <p>
+ *
+ * Valid whether {@link #getStatus()} is SUCCESS or FAIL.
+ */
+ public PeerHandle getPeerHandle() {
+ return mPeerHandle;
+ }
+
+ /**
* @return The distance (in cm) to the device specified by {@link #getMacAddress()}.
* <p>
* Only valid if {@link #getStatus()} returns {@link RangingResultCallback#STATUS_SUCCESS}.
@@ -135,6 +167,12 @@ public final class RangingResult implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mStatus);
dest.writeByteArray(mMac);
+ if (mPeerHandle == null) {
+ dest.writeBoolean(false);
+ } else {
+ dest.writeBoolean(true);
+ dest.writeInt(mPeerHandle.peerId);
+ }
dest.writeInt(mDistanceCm);
dest.writeInt(mDistanceStdDevCm);
dest.writeInt(mRssi);
@@ -152,11 +190,22 @@ public final class RangingResult implements Parcelable {
public RangingResult createFromParcel(Parcel in) {
int status = in.readInt();
byte[] mac = in.createByteArray();
+ boolean peerHandlePresent = in.readBoolean();
+ PeerHandle peerHandle = null;
+ if (peerHandlePresent) {
+ peerHandle = new PeerHandle(in.readInt());
+ }
int distanceCm = in.readInt();
int distanceStdDevCm = in.readInt();
int rssi = in.readInt();
long timestamp = in.readLong();
- return new RangingResult(status, mac, distanceCm, distanceStdDevCm, rssi, timestamp);
+ if (peerHandlePresent) {
+ return new RangingResult(status, peerHandle, distanceCm, distanceStdDevCm, rssi,
+ timestamp);
+ } else {
+ return new RangingResult(status, mac, distanceCm, distanceStdDevCm, rssi,
+ timestamp);
+ }
}
};
@@ -164,7 +213,8 @@ public final class RangingResult implements Parcelable {
@Override
public String toString() {
return new StringBuilder("RangingResult: [status=").append(mStatus).append(", mac=").append(
- mMac == null ? "<null>" : HexEncoding.encodeToString(mMac)).append(
+ mMac == null ? "<null>" : new String(HexEncoding.encodeToString(mMac))).append(
+ ", peerHandle=").append(mPeerHandle == null ? "<null>" : mPeerHandle.peerId).append(
", distanceCm=").append(mDistanceCm).append(", distanceStdDevCm=").append(
mDistanceStdDevCm).append(", rssi=").append(mRssi).append(", timestamp=").append(
mTimestamp).append("]").toString();
@@ -182,13 +232,15 @@ public final class RangingResult implements Parcelable {
RangingResult lhs = (RangingResult) o;
- return mStatus == lhs.mStatus && Arrays.equals(mMac, lhs.mMac)
- && mDistanceCm == lhs.mDistanceCm && mDistanceStdDevCm == lhs.mDistanceStdDevCm
- && mRssi == lhs.mRssi && mTimestamp == lhs.mTimestamp;
+ return mStatus == lhs.mStatus && Arrays.equals(mMac, lhs.mMac) && Objects.equals(
+ mPeerHandle, lhs.mPeerHandle) && mDistanceCm == lhs.mDistanceCm
+ && mDistanceStdDevCm == lhs.mDistanceStdDevCm && mRssi == lhs.mRssi
+ && mTimestamp == lhs.mTimestamp;
}
@Override
public int hashCode() {
- return Objects.hash(mStatus, mMac, mDistanceCm, mDistanceStdDevCm, mRssi, mTimestamp);
+ return Objects.hash(mStatus, mMac, mPeerHandle, mDistanceCm, mDistanceStdDevCm, mRssi,
+ mTimestamp);
}
} \ No newline at end of file
diff --git a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
index 23c75ce02e75..a55adb34ceb4 100644
--- a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.wifi.ScanResult;
+import android.net.wifi.aware.PeerHandle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Parcel;
@@ -78,7 +79,9 @@ public class WifiRttManagerTest {
public void testRangeSuccess() throws Exception {
RangingRequest request = new RangingRequest.Builder().build();
List<RangingResult> results = new ArrayList<>();
- results.add(new RangingResult(RangingResultCallback.STATUS_SUCCESS, null, 15, 5, 10, 666));
+ results.add(
+ new RangingResult(RangingResultCallback.STATUS_SUCCESS, (byte[]) null, 15, 5, 10,
+ 666));
RangingResultCallback callbackMock = mock(RangingResultCallback.class);
ArgumentCaptor<IRttCallback> callbackCaptor = ArgumentCaptor.forClass(IRttCallback.class);
@@ -132,10 +135,14 @@ public class WifiRttManagerTest {
List<ScanResult> scanResults2and3 = new ArrayList<>(2);
scanResults2and3.add(scanResult2);
scanResults2and3.add(scanResult3);
+ final byte[] mac1 = HexEncoding.decode("000102030405".toCharArray(), false);
+ PeerHandle peerHandle1 = new PeerHandle(12);
RangingRequest.Builder builder = new RangingRequest.Builder();
builder.addAp(scanResult1);
builder.addAps(scanResults2and3);
+ builder.addWifiAwarePeer(mac1);
+ builder.addWifiAwarePeer(peerHandle1);
RangingRequest request = builder.build();
Parcel parcelW = Parcel.obtain();
@@ -157,20 +164,23 @@ public class WifiRttManagerTest {
@Test
public void testRangingRequestAtLimit() {
ScanResult scanResult = new ScanResult();
+ scanResult.BSSID = "AA:BB:CC:DD:EE:FF";
List<ScanResult> scanResultList = new ArrayList<>();
- for (int i = 0; i < RangingRequest.getMaxPeers() - 2; ++i) {
+ for (int i = 0; i < RangingRequest.getMaxPeers() - 3; ++i) {
scanResultList.add(scanResult);
}
+ final byte[] mac1 = HexEncoding.decode("000102030405".toCharArray(), false);
// create request
RangingRequest.Builder builder = new RangingRequest.Builder();
builder.addAp(scanResult);
builder.addAps(scanResultList);
builder.addAp(scanResult);
+ builder.addWifiAwarePeer(mac1);
RangingRequest request = builder.build();
// verify request
- request.enforceValidity();
+ request.enforceValidity(true);
}
/**
@@ -180,19 +190,35 @@ public class WifiRttManagerTest {
public void testRangingRequestPastLimit() {
ScanResult scanResult = new ScanResult();
List<ScanResult> scanResultList = new ArrayList<>();
- for (int i = 0; i < RangingRequest.getMaxPeers() - 1; ++i) {
+ for (int i = 0; i < RangingRequest.getMaxPeers() - 2; ++i) {
scanResultList.add(scanResult);
}
+ final byte[] mac1 = HexEncoding.decode("000102030405".toCharArray(), false);
// create request
RangingRequest.Builder builder = new RangingRequest.Builder();
builder.addAp(scanResult);
builder.addAps(scanResultList);
builder.addAp(scanResult);
+ builder.addWifiAwarePeer(mac1);
+ RangingRequest request = builder.build();
+
+ // verify request
+ request.enforceValidity(true);
+ }
+
+ /**
+ * Validate that Aware requests are invalid on devices which do not support Aware
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testRangingRequestWithAwareWithNoAwareSupport() {
+ // create request
+ RangingRequest.Builder builder = new RangingRequest.Builder();
+ builder.addWifiAwarePeer(new PeerHandle(10));
RangingRequest request = builder.build();
// verify request
- request.enforceValidity();
+ request.enforceValidity(false);
}
/**
@@ -203,11 +229,13 @@ public class WifiRttManagerTest {
// Note: not validating parcel code of ScanResult (assumed to work)
int status = RangingResultCallback.STATUS_SUCCESS;
final byte[] mac = HexEncoding.decode("000102030405".toCharArray(), false);
+ PeerHandle peerHandle = new PeerHandle(10);
int distanceCm = 105;
int distanceStdDevCm = 10;
int rssi = 5;
long timestamp = System.currentTimeMillis();
+ // RangingResults constructed with a MAC address
RangingResult result = new RangingResult(status, mac, distanceCm, distanceStdDevCm, rssi,
timestamp);
@@ -222,5 +250,21 @@ public class WifiRttManagerTest {
RangingResult rereadResult = RangingResult.CREATOR.createFromParcel(parcelR);
assertEquals(result, rereadResult);
+
+ // RangingResults constructed with a PeerHandle
+ result = new RangingResult(status, peerHandle, distanceCm, distanceStdDevCm, rssi,
+ timestamp);
+
+ parcelW = Parcel.obtain();
+ result.writeToParcel(parcelW, 0);
+ bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ rereadResult = RangingResult.CREATOR.createFromParcel(parcelR);
+
+ assertEquals(result, rereadResult);
}
}