diff options
| author | 2017-09-27 13:58:42 -0700 | |
|---|---|---|
| committer | 2017-10-19 14:48:29 -0700 | |
| commit | 5a100a07b10424f45567e2efa6f11cf0110eb6b9 (patch) | |
| tree | 76f824e5c397065cb7d5c8fe278aaf617e4ea2af | |
| parent | f73f9ed57068d8256ae386f7a8be6ee2dda7cbf2 (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.java | 159 | ||||
| -rw-r--r-- | wifi/java/android/net/wifi/rtt/RangingResult.java | 66 | ||||
| -rw-r--r-- | wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java | 54 |
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); } } |