diff options
| -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);      }  }  |