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