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