• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
OSUInfo(ScanResult scanResult, String ssid, OSUProvider osuProvider, int osuID)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 
getOSUBssid()51     public long getOSUBssid() {
52         return mOSUBssid;
53     }
54 
setOSUBssid(long OSUBssid)55     public void setOSUBssid(long OSUBssid) {
56         mOSUBssid = OSUBssid;
57     }
58 
getHESSID()59     public long getHESSID() {
60         return mHESSID;
61     }
62 
getAnqpDomID()63     public int getAnqpDomID() {
64         return mAnqpDomID;
65     }
66 
getAdvertisingSSID()67     public String getAdvertisingSSID() {
68         return mAdvertisingSSID;
69     }
70 
getNameLocales()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 
getServiceLocales()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 
getIconLanguages()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 
getName(Locale locale)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 
getServiceDescription(Locale locale)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 
getOsuID()121     public int getOsuID() {
122         return mOsuID;
123     }
124 
setIconStatus(IconStatus iconStatus)125     public void setIconStatus(IconStatus iconStatus) {
126         synchronized (mOSUProvider) {
127             mIconStatus = iconStatus;
128         }
129     }
130 
getIconStatus()131     public IconStatus getIconStatus() {
132         synchronized (mOSUProvider) {
133             return mIconStatus;
134         }
135     }
136 
getIconFileElement()137     public HSIconFileElement getIconFileElement() {
138         synchronized (mOSUProvider) {
139             return mIconFileElement;
140         }
141     }
142 
getIconInfo()143     public IconInfo getIconInfo() {
144         synchronized (mOSUProvider) {
145             return mIconInfo;
146         }
147     }
148 
setIconFileElement(HSIconFileElement iconFileElement, String fileName)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 
ScoreEntry(T data, int score)166         private ScoreEntry(T data, int score) {
167             mData = data;
168             mScore = score;
169         }
170 
getData()171         public T getData() {
172             return mData;
173         }
174 
175         @Override
compareTo(ScoreEntry other)176         public int compareTo(ScoreEntry other) {
177             return Integer.compare(mScore, other.mScore);
178         }
179     }
180 
getIconInfo(Locale locale, Set<String> types, int width, int height)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 
languageScore(String language, Locale locale)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 
getBSSID()235     public long getBSSID() {
236         return mBSSID;
237     }
238 
getSSID()239     public String getSSID() {
240         return mSSID;
241     }
242 
getOSUProvider()243     public OSUProvider getOSUProvider() {
244         return mOSUProvider;
245     }
246 
247     @Override
toString()248     public String toString() {
249         return String.format("OSU Info '%s' %012x -> %s, icon %s",
250                 mSSID, mBSSID, getServiceDescription(null), mIconStatus);
251     }
252 }
253