1 package com.android.anqp; 2 3 import java.net.ProtocolException; 4 import java.nio.ByteBuffer; 5 import java.nio.ByteOrder; 6 import java.nio.charset.StandardCharsets; 7 import java.util.ArrayList; 8 import java.util.List; 9 10 import static com.android.anqp.Constants.BYTE_MASK; 11 import static com.android.anqp.Constants.SHORT_MASK; 12 13 /** 14 * An OSU Provider, as specified in 15 * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00, 16 * section 4.8.1 17 */ 18 public class OSUProvider { 19 20 public enum OSUMethod {OmaDm, SoapXml} 21 22 private final String mSSID; 23 private final List<I18Name> mNames; 24 private final String mOSUServer; 25 private final List<OSUMethod> mOSUMethods; 26 private final List<IconInfo> mIcons; 27 private final String mOsuNai; 28 private final List<I18Name> mServiceDescriptions; 29 private final int mHashCode; 30 31 public OSUProvider(String ssid, ByteBuffer payload) throws ProtocolException { 32 if (payload.remaining() < 11) { 33 throw new ProtocolException("Truncated OSU provider: " + payload.remaining()); 34 } 35 36 mSSID = ssid; 37 38 int length = payload.getShort() & SHORT_MASK; 39 int namesLength = payload.getShort() & SHORT_MASK; 40 41 ByteBuffer namesBuffer = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN); 42 namesBuffer.limit(namesBuffer.position() + namesLength); 43 payload.position(payload.position() + namesLength); 44 45 mNames = new ArrayList<>(); 46 47 while (namesBuffer.hasRemaining()) { 48 mNames.add(new I18Name(namesBuffer)); 49 } 50 51 mOSUServer = Constants.getPrefixedString(payload, 1, StandardCharsets.UTF_8); 52 int methodLength = payload.get() & BYTE_MASK; 53 mOSUMethods = new ArrayList<>(methodLength); 54 while (methodLength > 0) { 55 int methodID = payload.get() & BYTE_MASK; 56 mOSUMethods.add(methodID < OSUMethod.values().length ? 57 OSUMethod.values()[methodID] : 58 null); 59 methodLength--; 60 } 61 62 int iconsLength = payload.getShort() & SHORT_MASK; 63 ByteBuffer iconsBuffer = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN); 64 iconsBuffer.limit(iconsBuffer.position() + iconsLength); 65 payload.position(payload.position() + iconsLength); 66 67 mIcons = new ArrayList<>(); 68 69 while (iconsBuffer.hasRemaining()) { 70 mIcons.add(new IconInfo(iconsBuffer)); 71 } 72 73 mOsuNai = Constants.getPrefixedString(payload, 1, StandardCharsets.UTF_8, true); 74 75 int descriptionsLength = payload.getShort() & SHORT_MASK; 76 ByteBuffer descriptionsBuffer = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN); 77 descriptionsBuffer.limit(descriptionsBuffer.position() + descriptionsLength); 78 payload.position(payload.position() + descriptionsLength); 79 80 mServiceDescriptions = new ArrayList<>(); 81 82 while (descriptionsBuffer.hasRemaining()) { 83 mServiceDescriptions.add(new I18Name(descriptionsBuffer)); 84 } 85 86 int result = mNames.hashCode(); 87 result = 31 * result + mSSID.hashCode(); 88 result = 31 * result + mOSUServer.hashCode(); 89 result = 31 * result + mOSUMethods.hashCode(); 90 result = 31 * result + mIcons.hashCode(); 91 result = 31 * result + (mOsuNai != null ? mOsuNai.hashCode() : 0); 92 result = 31 * result + mServiceDescriptions.hashCode(); 93 mHashCode = result; 94 } 95 96 public String getSSID() { 97 return mSSID; 98 } 99 100 public List<I18Name> getNames() { 101 return mNames; 102 } 103 104 public String getOSUServer() { 105 return mOSUServer; 106 } 107 108 public List<OSUMethod> getOSUMethods() { 109 return mOSUMethods; 110 } 111 112 public List<IconInfo> getIcons() { 113 return mIcons; 114 } 115 116 public String getOsuNai() { 117 return mOsuNai; 118 } 119 120 public List<I18Name> getServiceDescriptions() { 121 return mServiceDescriptions; 122 } 123 124 @Override 125 public boolean equals(Object o) { 126 if (this == o) return true; 127 if (o == null || getClass() != o.getClass()) return false; 128 129 OSUProvider that = (OSUProvider) o; 130 131 if (!mSSID.equals(that.mSSID)) return false; 132 if (!mOSUServer.equals(that.mOSUServer)) return false; 133 if (!mNames.equals(that.mNames)) return false; 134 if (!mServiceDescriptions.equals(that.mServiceDescriptions)) return false; 135 if (!mIcons.equals(that.mIcons)) return false; 136 if (!mOSUMethods.equals(that.mOSUMethods)) return false; 137 if (mOsuNai != null ? !mOsuNai.equals(that.mOsuNai) : that.mOsuNai != null) return false; 138 139 return true; 140 } 141 142 @Override 143 public int hashCode() { 144 return mHashCode; 145 } 146 147 @Override 148 public String toString() { 149 return "OSUProvider{" + 150 "names=" + mNames + 151 ", OSUServer='" + mOSUServer + '\'' + 152 ", OSUMethods=" + mOSUMethods + 153 ", icons=" + mIcons + 154 ", NAI='" + mOsuNai + '\'' + 155 ", serviceDescriptions=" + mServiceDescriptions + 156 '}'; 157 } 158 } 159