Home | History | Annotate | Download | only in anqp
      1 package com.android.anqp;
      2 
      3 import android.os.Parcel;
      4 
      5 import com.android.hotspot2.Utils;
      6 
      7 import java.io.IOException;
      8 import java.net.ProtocolException;
      9 import java.nio.ByteBuffer;
     10 import java.nio.ByteOrder;
     11 import java.nio.charset.StandardCharsets;
     12 import java.util.ArrayList;
     13 import java.util.List;
     14 
     15 import static com.android.anqp.Constants.BYTE_MASK;
     16 import static com.android.anqp.Constants.SHORT_MASK;
     17 
     18 /**
     19  * An OSU Provider, as specified in
     20  * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00,
     21  * section 4.8.1
     22  */
     23 public class OSUProvider {
     24 
     25     public enum OSUMethod {OmaDm, SoapXml}
     26 
     27     private final String mSSID;
     28     private final List<I18Name> mNames;
     29     private final String mOSUServer;
     30     private final List<OSUMethod> mOSUMethods;
     31     private final List<IconInfo> mIcons;
     32     private final String mOsuNai;
     33     private final List<I18Name> mServiceDescriptions;
     34     private final int mHashCode;
     35 
     36     public OSUProvider(String ssid, ByteBuffer payload) throws ProtocolException {
     37         if (payload.remaining() < 11) {
     38             throw new ProtocolException("Truncated OSU provider: " + payload.remaining());
     39         }
     40 
     41         mSSID = ssid;
     42 
     43         int length = payload.getShort() & SHORT_MASK;
     44         int namesLength = payload.getShort() & SHORT_MASK;
     45 
     46         ByteBuffer namesBuffer = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN);
     47         namesBuffer.limit(namesBuffer.position() + namesLength);
     48         payload.position(payload.position() + namesLength);
     49 
     50         mNames = new ArrayList<>();
     51 
     52         while (namesBuffer.hasRemaining()) {
     53             mNames.add(new I18Name(namesBuffer));
     54         }
     55 
     56         mOSUServer = Constants.getPrefixedString(payload, 1, StandardCharsets.UTF_8);
     57         int methodLength = payload.get() & BYTE_MASK;
     58         mOSUMethods = new ArrayList<>(methodLength);
     59         while (methodLength > 0) {
     60             int methodID = payload.get() & BYTE_MASK;
     61             mOSUMethods.add(methodID < OSUMethod.values().length ?
     62                     OSUMethod.values()[methodID] :
     63                     null);
     64             methodLength--;
     65         }
     66 
     67         int iconsLength = payload.getShort() & SHORT_MASK;
     68         ByteBuffer iconsBuffer = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN);
     69         iconsBuffer.limit(iconsBuffer.position() + iconsLength);
     70         payload.position(payload.position() + iconsLength);
     71 
     72         mIcons = new ArrayList<>();
     73 
     74         while (iconsBuffer.hasRemaining()) {
     75             mIcons.add(new IconInfo(iconsBuffer));
     76         }
     77 
     78         mOsuNai = Constants.getPrefixedString(payload, 1, StandardCharsets.UTF_8, true);
     79 
     80         int descriptionsLength = payload.getShort() & SHORT_MASK;
     81         ByteBuffer descriptionsBuffer = payload.duplicate().order(ByteOrder.LITTLE_ENDIAN);
     82         descriptionsBuffer.limit(descriptionsBuffer.position() + descriptionsLength);
     83         payload.position(payload.position() + descriptionsLength);
     84 
     85         mServiceDescriptions = new ArrayList<>();
     86 
     87         while (descriptionsBuffer.hasRemaining()) {
     88             mServiceDescriptions.add(new I18Name(descriptionsBuffer));
     89         }
     90 
     91         int result = mNames.hashCode();
     92         result = 31 * result + mSSID.hashCode();
     93         result = 31 * result + mOSUServer.hashCode();
     94         result = 31 * result + mOSUMethods.hashCode();
     95         result = 31 * result + mIcons.hashCode();
     96         result = 31 * result + (mOsuNai != null ? mOsuNai.hashCode() : 0);
     97         result = 31 * result + mServiceDescriptions.hashCode();
     98         mHashCode = result;
     99     }
    100 
    101     public String getSSID() {
    102         return mSSID;
    103     }
    104 
    105     public List<I18Name> getNames() {
    106         return mNames;
    107     }
    108 
    109     public String getOSUServer() {
    110         return mOSUServer;
    111     }
    112 
    113     public List<OSUMethod> getOSUMethods() {
    114         return mOSUMethods;
    115     }
    116 
    117     public List<IconInfo> getIcons() {
    118         return mIcons;
    119     }
    120 
    121     public String getOsuNai() {
    122         return mOsuNai;
    123     }
    124 
    125     public List<I18Name> getServiceDescriptions() {
    126         return mServiceDescriptions;
    127     }
    128 
    129     @Override
    130     public boolean equals(Object o) {
    131         if (this == o) return true;
    132         if (o == null || getClass() != o.getClass()) return false;
    133 
    134         OSUProvider that = (OSUProvider) o;
    135 
    136         if (!mSSID.equals(that.mSSID)) return false;
    137         if (!mOSUServer.equals(that.mOSUServer)) return false;
    138         if (!mNames.equals(that.mNames)) return false;
    139         if (!mServiceDescriptions.equals(that.mServiceDescriptions)) return false;
    140         if (!mIcons.equals(that.mIcons)) return false;
    141         if (!mOSUMethods.equals(that.mOSUMethods)) return false;
    142         if (mOsuNai != null ? !mOsuNai.equals(that.mOsuNai) : that.mOsuNai != null) return false;
    143 
    144         return true;
    145     }
    146 
    147     @Override
    148     public int hashCode() {
    149         return mHashCode;
    150     }
    151 
    152     @Override
    153     public String toString() {
    154         return "OSUProvider{" +
    155                 "names=" + mNames +
    156                 ", OSUServer='" + mOSUServer + '\'' +
    157                 ", OSUMethods=" + mOSUMethods +
    158                 ", icons=" + mIcons +
    159                 ", NAI='" + mOsuNai + '\'' +
    160                 ", serviceDescriptions=" + mServiceDescriptions +
    161                 '}';
    162     }
    163 
    164     public OSUProvider(Parcel in) throws IOException {
    165         mSSID = in.readString();
    166         int nameCount = in.readInt();
    167         mNames = new ArrayList<>(nameCount);
    168         for (int n = 0; n < nameCount; n++) {
    169             mNames.add(new I18Name(in));
    170         }
    171         mOSUServer = in.readString();
    172         int methodCount = in.readInt();
    173         mOSUMethods = new ArrayList<>(methodCount);
    174         for (int n = 0; n < methodCount; n++) {
    175             mOSUMethods.add(Utils.mapEnum(in.readInt(), OSUMethod.class));
    176         }
    177         int iconCount = in.readInt();
    178         mIcons = new ArrayList<>(iconCount);
    179         for (int n = 0; n < iconCount; n++) {
    180             mIcons.add(new IconInfo(in));
    181         }
    182         mOsuNai = in.readString();
    183         int serviceCount = in.readInt();
    184         mServiceDescriptions = new ArrayList<>(serviceCount);
    185         for (int n = 0; n < serviceCount; n++) {
    186             mServiceDescriptions.add(new I18Name(in));
    187         }
    188         mHashCode = in.readInt();
    189     }
    190 
    191     public void writeParcel(Parcel out) {
    192         out.writeString(mSSID);
    193         out.writeInt(mNames.size());
    194         for (I18Name name : mNames) {
    195             name.writeParcel(out);
    196         }
    197         out.writeString(mOSUServer);
    198         out.writeInt(mOSUMethods.size());
    199         for (OSUMethod method : mOSUMethods) {
    200             out.writeInt(method.ordinal());
    201         }
    202         out.writeInt(mIcons.size());
    203         for (IconInfo iconInfo : mIcons) {
    204             iconInfo.writeParcel(out);
    205         }
    206         out.writeString(mOsuNai);
    207         out.writeInt(mServiceDescriptions.size());
    208         for (I18Name serviceDescription : mServiceDescriptions) {
    209             serviceDescription.writeParcel(out);
    210         }
    211         out.writeInt(mHashCode);
    212     }
    213 }
    214