Home | History | Annotate | Download | only in flow
      1 package com.android.hotspot2.flow;
      2 
      3 import android.net.wifi.ScanResult;
      4 import android.os.Parcel;
      5 import android.os.Parcelable;
      6 import android.util.Log;
      7 
      8 import com.android.anqp.HSIconFileElement;
      9 import com.android.anqp.I18Name;
     10 import com.android.anqp.IconInfo;
     11 import com.android.anqp.OSUProvider;
     12 import com.android.hotspot2.Utils;
     13 import com.android.hotspot2.osu.OSUManager;
     14 
     15 import java.io.IOException;
     16 import java.util.ArrayList;
     17 import java.util.Collections;
     18 import java.util.HashSet;
     19 import java.util.List;
     20 import java.util.ListIterator;
     21 import java.util.Locale;
     22 import java.util.Set;
     23 
     24 public class OSUInfo implements Parcelable {
     25     public static final String GenericLocale = "zxx";
     26 
     27     public enum IconStatus {
     28         NotQueried,     //
     29         InProgress,     // Query pending
     30         NotAvailable,   // Deterministically unavailable
     31         Available       // Icon data retrieved
     32     }
     33 
     34     private final long mBSSID;
     35     private final long mHESSID;
     36     private final int mAnqpDomID;
     37     private final String mAdvertisingSSID;
     38     private final OSUProvider mOSUProvider;
     39     private final int mOsuID;
     40     private long mOSUBssid;
     41     private IconStatus mIconStatus = IconStatus.NotQueried;
     42     private HSIconFileElement mIconFileElement;
     43     private String mIconFileName;
     44     private IconInfo mIconInfo;
     45 
     46     public OSUInfo(ScanResult scanResult, OSUProvider osuProvider, int osuID) {
     47         mOsuID = osuID;
     48         mBSSID = Utils.parseMac(scanResult.BSSID);
     49         mHESSID = scanResult.hessid;
     50         mAnqpDomID = scanResult.anqpDomainId;
     51         mAdvertisingSSID = scanResult.SSID;
     52         mOSUProvider = osuProvider;
     53     }
     54 
     55     public long getOSUBssid() {
     56         return mOSUBssid;
     57     }
     58 
     59     public void setOSUBssid(long OSUBssid) {
     60         mOSUBssid = OSUBssid;
     61     }
     62 
     63     public long getHESSID() {
     64         return mHESSID;
     65     }
     66 
     67     public int getAnqpDomID() {
     68         return mAnqpDomID;
     69     }
     70 
     71     public String getAdvertisingSsid() {
     72         return mAdvertisingSSID;
     73     }
     74 
     75     public Set<Locale> getNameLocales() {
     76         Set<Locale> locales = new HashSet<>(mOSUProvider.getNames().size());
     77         for (I18Name name : mOSUProvider.getNames()) {
     78             locales.add(name.getLocale());
     79         }
     80         return locales;
     81     }
     82 
     83     public Set<Locale> getServiceLocales() {
     84         Set<Locale> locales = new HashSet<>(mOSUProvider.getServiceDescriptions().size());
     85         for (I18Name name : mOSUProvider.getServiceDescriptions()) {
     86             locales.add(name.getLocale());
     87         }
     88         return locales;
     89     }
     90 
     91     public Set<String> getIconLanguages() {
     92         Set<String> locales = new HashSet<>(mOSUProvider.getIcons().size());
     93         for (IconInfo iconInfo : mOSUProvider.getIcons()) {
     94             locales.add(iconInfo.getLanguage());
     95         }
     96         return locales;
     97     }
     98 
     99     public String getName(Locale locale) {
    100         List<ScoreEntry<String>> scoreList = new ArrayList<>();
    101         for (I18Name name : mOSUProvider.getNames()) {
    102             if (locale == null || name.getLocale().equals(locale)) {
    103                 return name.getText();
    104             }
    105             scoreList.add(new ScoreEntry<>(name.getText(),
    106                     languageScore(name.getLanguage(), locale)));
    107         }
    108         Collections.sort(scoreList);
    109         return scoreList.isEmpty() ? null : scoreList.get(scoreList.size() - 1).getData();
    110     }
    111 
    112     public String getServiceDescription(Locale locale) {
    113         List<ScoreEntry<String>> scoreList = new ArrayList<>();
    114         for (I18Name service : mOSUProvider.getServiceDescriptions()) {
    115             if (locale == null || service.getLocale().equals(locale)) {
    116                 return service.getText();
    117             }
    118             scoreList.add(new ScoreEntry<>(service.getText(),
    119                     languageScore(service.getLanguage(), locale)));
    120         }
    121         Collections.sort(scoreList);
    122         return scoreList.isEmpty() ? null : scoreList.get(scoreList.size() - 1).getData();
    123     }
    124 
    125     public int getOsuID() {
    126         return mOsuID;
    127     }
    128 
    129     public void setIconStatus(IconStatus iconStatus) {
    130         synchronized (mOSUProvider) {
    131             mIconStatus = iconStatus;
    132         }
    133     }
    134 
    135     public IconStatus getIconStatus() {
    136         synchronized (mOSUProvider) {
    137             return mIconStatus;
    138         }
    139     }
    140 
    141     public HSIconFileElement getIconFileElement() {
    142         synchronized (mOSUProvider) {
    143             return mIconFileElement;
    144         }
    145     }
    146 
    147     public IconInfo getIconInfo() {
    148         synchronized (mOSUProvider) {
    149             return mIconInfo;
    150         }
    151     }
    152 
    153     public String getIconFileName() {
    154         return mIconFileName;
    155     }
    156 
    157     public void setIconFileElement(HSIconFileElement iconFileElement, String fileName) {
    158         synchronized (mOSUProvider) {
    159             mIconFileElement = iconFileElement;
    160             for (IconInfo iconInfo : mOSUProvider.getIcons()) {
    161                 if (iconInfo.getFileName().equals(fileName)) {
    162                     mIconInfo = iconInfo;
    163                     mIconFileName = fileName;
    164                     break;
    165                 }
    166             }
    167             mIconStatus = IconStatus.Available;
    168         }
    169     }
    170 
    171     private static class ScoreEntry<T> implements Comparable<ScoreEntry> {
    172         private final T mData;
    173         private final int mScore;
    174 
    175         private ScoreEntry(T data, int score) {
    176             mData = data;
    177             mScore = score;
    178         }
    179 
    180         public T getData() {
    181             return mData;
    182         }
    183 
    184         @Override
    185         public int compareTo(ScoreEntry other) {
    186             return Integer.compare(mScore, other.mScore);
    187         }
    188 
    189         @Override
    190         public String toString() {
    191             return String.format("%d for '%s'", mScore, mData);
    192         }
    193     }
    194 
    195     public List<IconInfo> getIconInfo(Locale locale, Set<String> types, int width, int height) {
    196         if (mOSUProvider.getIcons().isEmpty()) {
    197             return null;
    198         }
    199         Log.d(OSUManager.TAG, "Matching icons against " + locale
    200                 + ", types " + types + ", " + width + "*" + height);
    201 
    202         List<ScoreEntry<IconInfo>> matches = new ArrayList<>();
    203         for (IconInfo iconInfo : mOSUProvider.getIcons()) {
    204             Log.d(OSUManager.TAG, "Checking icon " + iconInfo.toString());
    205             if (!types.contains(iconInfo.getIconType())) {
    206                 continue;
    207             }
    208 
    209             int score = languageScore(iconInfo.getLanguage(), locale);
    210             int delta = iconInfo.getWidth() - width;
    211             // Best size score is 1024 for a exact match, i.e. 2048 if both sides match
    212             if (delta >= 0) {
    213                 score += (256 - delta) * 4;  // Prefer down-scaling
    214             } else {
    215                 score += 256 + delta;    // Before up-scaling
    216             }
    217             delta = iconInfo.getHeight() - height;
    218             if (delta >= 0) {
    219                 score += (256 - delta) * 4;
    220             } else {
    221                 score += 256 + delta;
    222             }
    223             matches.add(new ScoreEntry<>(iconInfo, score));
    224         }
    225         if (matches.isEmpty()) {
    226             return Collections.emptyList();
    227         }
    228         Collections.sort(matches);
    229         List<IconInfo> icons = new ArrayList<>(matches.size());
    230         ListIterator<ScoreEntry<IconInfo>> matchIterator = matches.listIterator(matches.size());
    231         while (matchIterator.hasPrevious()) {
    232             icons.add(matchIterator.previous().getData());
    233         }
    234         return icons;
    235     }
    236 
    237     private static int languageScore(String language, Locale locale) {
    238         if (language.length() == 3 && language.equalsIgnoreCase(locale.getISO3Language()) ||
    239                 language.length() == 2 && language.equalsIgnoreCase(locale.getLanguage())) {
    240             return 4096;
    241         } else if (language.equalsIgnoreCase(GenericLocale)) {
    242             return 3072;
    243         } else if (language.equalsIgnoreCase("eng")) {
    244             return 2048;
    245         } else {
    246             return 1024;
    247         }
    248     }
    249 
    250     public long getBSSID() {
    251         return mBSSID;
    252     }
    253 
    254     public String getOsuSsid() {
    255         return mOSUProvider.getSSID();
    256     }
    257 
    258     public OSUProvider getOSUProvider() {
    259         return mOSUProvider;
    260     }
    261 
    262     @Override
    263     public String toString() {
    264         return String.format("OSU Info '%s' %012x -> %s, icon %s",
    265                 getOsuSsid(), mBSSID, getServiceDescription(null), mIconStatus);
    266     }
    267 
    268     private OSUInfo(Parcel in) {
    269         mBSSID = in.readLong();
    270         mHESSID = in.readLong();
    271         mAnqpDomID = in.readInt();
    272         mAdvertisingSSID = in.readString();
    273         mOsuID = in.readInt();
    274         mOSUBssid = in.readLong();
    275         mIconFileName = in.readString();
    276         mIconStatus = Utils.mapEnum(in.readInt(), IconStatus.class);
    277         OSUProvider osuProvider;
    278         try {
    279             osuProvider = new OSUProvider(in);
    280         } catch (IOException ioe) {
    281             osuProvider = null;
    282         }
    283         mOSUProvider = osuProvider;
    284         if (osuProvider == null) {
    285             return;
    286         }
    287         mIconFileElement = new HSIconFileElement(in);
    288         int iconIndex = in.readInt();
    289         mIconInfo = iconIndex >= 0 && iconIndex < mOSUProvider.getIcons().size()
    290                 ? mOSUProvider.getIcons().get(iconIndex) : null;
    291     }
    292 
    293     public static final Parcelable.Creator<OSUInfo> CREATOR = new Parcelable.Creator<OSUInfo>() {
    294         public OSUInfo createFromParcel(Parcel in) {
    295             return new OSUInfo(in);
    296         }
    297 
    298         public OSUInfo[] newArray(int size) {
    299             return new OSUInfo[size];
    300         }
    301     };
    302 
    303     @Override
    304     public int describeContents() {
    305         return 0;
    306     }
    307 
    308     @Override
    309     public void writeToParcel(Parcel dest, int flags) {
    310         dest.writeLong(mBSSID);
    311         dest.writeLong(mHESSID);
    312         dest.writeInt(mAnqpDomID);
    313         dest.writeString(mAdvertisingSSID);
    314         dest.writeInt(mOsuID);
    315         dest.writeLong(mOSUBssid);
    316         dest.writeString(mIconFileName);
    317         dest.writeInt(mIconStatus.ordinal());
    318         mOSUProvider.writeParcel(dest);
    319         mIconFileElement.writeParcel(dest);
    320     }
    321 }
    322