• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
OSUInfo(ScanResult scanResult, OSUProvider osuProvider, int osuID)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 
getOSUBssid()55     public long getOSUBssid() {
56         return mOSUBssid;
57     }
58 
setOSUBssid(long OSUBssid)59     public void setOSUBssid(long OSUBssid) {
60         mOSUBssid = OSUBssid;
61     }
62 
getHESSID()63     public long getHESSID() {
64         return mHESSID;
65     }
66 
getAnqpDomID()67     public int getAnqpDomID() {
68         return mAnqpDomID;
69     }
70 
getAdvertisingSsid()71     public String getAdvertisingSsid() {
72         return mAdvertisingSSID;
73     }
74 
getNameLocales()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 
getServiceLocales()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 
getIconLanguages()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 
getName(Locale locale)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 
getServiceDescription(Locale locale)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 
getOsuID()125     public int getOsuID() {
126         return mOsuID;
127     }
128 
setIconStatus(IconStatus iconStatus)129     public void setIconStatus(IconStatus iconStatus) {
130         synchronized (mOSUProvider) {
131             mIconStatus = iconStatus;
132         }
133     }
134 
getIconStatus()135     public IconStatus getIconStatus() {
136         synchronized (mOSUProvider) {
137             return mIconStatus;
138         }
139     }
140 
getIconFileElement()141     public HSIconFileElement getIconFileElement() {
142         synchronized (mOSUProvider) {
143             return mIconFileElement;
144         }
145     }
146 
getIconInfo()147     public IconInfo getIconInfo() {
148         synchronized (mOSUProvider) {
149             return mIconInfo;
150         }
151     }
152 
getIconFileName()153     public String getIconFileName() {
154         return mIconFileName;
155     }
156 
setIconFileElement(HSIconFileElement iconFileElement, String fileName)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 
ScoreEntry(T data, int score)175         private ScoreEntry(T data, int score) {
176             mData = data;
177             mScore = score;
178         }
179 
getData()180         public T getData() {
181             return mData;
182         }
183 
184         @Override
compareTo(ScoreEntry other)185         public int compareTo(ScoreEntry other) {
186             return Integer.compare(mScore, other.mScore);
187         }
188 
189         @Override
toString()190         public String toString() {
191             return String.format("%d for '%s'", mScore, mData);
192         }
193     }
194 
getIconInfo(Locale locale, Set<String> types, int width, int height)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 
languageScore(String language, Locale locale)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 
getBSSID()250     public long getBSSID() {
251         return mBSSID;
252     }
253 
getOsuSsid()254     public String getOsuSsid() {
255         return mOSUProvider.getSSID();
256     }
257 
getOSUProvider()258     public OSUProvider getOSUProvider() {
259         return mOSUProvider;
260     }
261 
262     @Override
toString()263     public String toString() {
264         return String.format("OSU Info '%s' %012x -> %s, icon %s",
265                 getOsuSsid(), mBSSID, getServiceDescription(null), mIconStatus);
266     }
267 
OSUInfo(Parcel in)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