blob: 3724cf06d15bd0985d392ee2799372c81c769cd2 [file] [log] [blame]
package com.android.anqp;
import android.os.Parcel;
import com.android.hotspot2.Utils;
import java.io.IOException;
import java.net.ProtocolException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import static com.android.anqp.Constants.BYTE_MASK;
import static com.android.anqp.Constants.SHORT_MASK;
/**
* An OSU Provider, as specified in
* Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00,
* section 4.8.1
*/
public class OSUProvider {
public enum OSUMethod {OmaDm, SoapXml}
private final String mSSID;
private final List<I18Name> mNames;
private final String mOSUServer;
private final List<OSUMethod> mOSUMethods;
private final List<IconInfo> mIcons;
private final String mOsuNai;
private final List<I18Name> mServiceDescriptions;
private final int mHashCode;
public OSUProvider(String ssid, ByteBuffer payload) throws ProtocolException {
if (payload.remaining() < 11) {
throw new ProtocolException("Truncated OSU provider: " + payload.remaining());
}
mSSID = ssid;
int length = payload.getShort() & SHORT_MASK;
int namesLength = payload.getShort() & SHORT_MASK;
ByteBuffer namesBuffer = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN);
namesBuffer.limit(namesBuffer.position() + namesLength);
payload.position(payload.position() + namesLength);
mNames = new ArrayList<>();
while (namesBuffer.hasRemaining()) {
mNames.add(new I18Name(namesBuffer));
}
mOSUServer = Constants.getPrefixedString(payload, 1, StandardCharsets.UTF_8);
int methodLength = payload.get() & BYTE_MASK;
mOSUMethods = new ArrayList<>(methodLength);
while (methodLength > 0) {
int methodID = payload.get() & BYTE_MASK;
mOSUMethods.add(methodID < OSUMethod.values().length ?
OSUMethod.values()[methodID] :
null);
methodLength--;
}
int iconsLength = payload.getShort() & SHORT_MASK;
ByteBuffer iconsBuffer = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN);
iconsBuffer.limit(iconsBuffer.position() + iconsLength);
payload.position(payload.position() + iconsLength);
mIcons = new ArrayList<>();
while (iconsBuffer.hasRemaining()) {
mIcons.add(new IconInfo(iconsBuffer));
}
mOsuNai = Constants.getPrefixedString(payload, 1, StandardCharsets.UTF_8, true);
int descriptionsLength = payload.getShort() & SHORT_MASK;
ByteBuffer descriptionsBuffer = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN);
descriptionsBuffer.limit(descriptionsBuffer.position() + descriptionsLength);
payload.position(payload.position() + descriptionsLength);
mServiceDescriptions = new ArrayList<>();
while (descriptionsBuffer.hasRemaining()) {
mServiceDescriptions.add(new I18Name(descriptionsBuffer));
}
int result = mNames.hashCode();
result = 31 * result + mSSID.hashCode();
result = 31 * result + mOSUServer.hashCode();
result = 31 * result + mOSUMethods.hashCode();
result = 31 * result + mIcons.hashCode();
result = 31 * result + (mOsuNai != null ? mOsuNai.hashCode() : 0);
result = 31 * result + mServiceDescriptions.hashCode();
mHashCode = result;
}
public String getSSID() {
return mSSID;
}
public List<I18Name> getNames() {
return mNames;
}
public String getOSUServer() {
return mOSUServer;
}
public List<OSUMethod> getOSUMethods() {
return mOSUMethods;
}
public List<IconInfo> getIcons() {
return mIcons;
}
public String getOsuNai() {
return mOsuNai;
}
public List<I18Name> getServiceDescriptions() {
return mServiceDescriptions;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OSUProvider that = (OSUProvider) o;
if (!mSSID.equals(that.mSSID)) return false;
if (!mOSUServer.equals(that.mOSUServer)) return false;
if (!mNames.equals(that.mNames)) return false;
if (!mServiceDescriptions.equals(that.mServiceDescriptions)) return false;
if (!mIcons.equals(that.mIcons)) return false;
if (!mOSUMethods.equals(that.mOSUMethods)) return false;
if (mOsuNai != null ? !mOsuNai.equals(that.mOsuNai) : that.mOsuNai != null) return false;
return true;
}
@Override
public int hashCode() {
return mHashCode;
}
@Override
public String toString() {
return "OSUProvider{" +
"names=" + mNames +
", OSUServer='" + mOSUServer + '\'' +
", OSUMethods=" + mOSUMethods +
", icons=" + mIcons +
", NAI='" + mOsuNai + '\'' +
", serviceDescriptions=" + mServiceDescriptions +
'}';
}
public OSUProvider(Parcel in) throws IOException {
mSSID = in.readString();
int nameCount = in.readInt();
mNames = new ArrayList<>(nameCount);
for (int n = 0; n < nameCount; n++) {
mNames.add(new I18Name(in));
}
mOSUServer = in.readString();
int methodCount = in.readInt();
mOSUMethods = new ArrayList<>(methodCount);
for (int n = 0; n < methodCount; n++) {
mOSUMethods.add(Utils.mapEnum(in.readInt(), OSUMethod.class));
}
int iconCount = in.readInt();
mIcons = new ArrayList<>(iconCount);
for (int n = 0; n < iconCount; n++) {
mIcons.add(new IconInfo(in));
}
mOsuNai = in.readString();
int serviceCount = in.readInt();
mServiceDescriptions = new ArrayList<>(serviceCount);
for (int n = 0; n < serviceCount; n++) {
mServiceDescriptions.add(new I18Name(in));
}
mHashCode = in.readInt();
}
public void writeParcel(Parcel out) {
out.writeString(mSSID);
out.writeInt(mNames.size());
for (I18Name name : mNames) {
name.writeParcel(out);
}
out.writeString(mOSUServer);
out.writeInt(mOSUMethods.size());
for (OSUMethod method : mOSUMethods) {
out.writeInt(method.ordinal());
}
out.writeInt(mIcons.size());
for (IconInfo iconInfo : mIcons) {
iconInfo.writeParcel(out);
}
out.writeString(mOsuNai);
out.writeInt(mServiceDescriptions.size());
for (I18Name serviceDescription : mServiceDescriptions) {
serviceDescription.writeParcel(out);
}
out.writeInt(mHashCode);
}
}