10701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistpackage com.android.hotspot2.flow;
2ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
3ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.net.wifi.ScanResult;
40701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport android.os.Parcel;
50701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport android.os.Parcelable;
6ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport android.util.Log;
7ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
8ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.anqp.HSIconFileElement;
9ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.anqp.I18Name;
10ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.anqp.IconInfo;
11ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.anqp.OSUProvider;
12ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport com.android.hotspot2.Utils;
130701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport com.android.hotspot2.osu.OSUManager;
14ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
150701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport java.io.IOException;
16ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.ArrayList;
17ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Collections;
18ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.HashSet;
19ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.List;
200701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistimport java.util.ListIterator;
21ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Locale;
22ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvistimport java.util.Set;
23ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
240701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvistpublic class OSUInfo implements Parcelable {
25ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public static final String GenericLocale = "zxx";
26ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
27ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public enum IconStatus {
28ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        NotQueried,     //
29ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        InProgress,     // Query pending
30ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        NotAvailable,   // Deterministically unavailable
31ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        Available       // Icon data retrieved
32ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
33ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
34ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private final long mBSSID;
35ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private final long mHESSID;
36ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private final int mAnqpDomID;
37ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private final String mAdvertisingSSID;
38ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private final OSUProvider mOSUProvider;
39ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private final int mOsuID;
40ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private long mOSUBssid;
41ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private IconStatus mIconStatus = IconStatus.NotQueried;
42ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private HSIconFileElement mIconFileElement;
430ff7a0a25679b1a4d483c6f750973c57b25b6826Jan Nordqvist    private String mIconFileName;
44ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private IconInfo mIconInfo;
45ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
460701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist    public OSUInfo(ScanResult scanResult, OSUProvider osuProvider, int osuID) {
47ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mOsuID = osuID;
48ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mBSSID = Utils.parseMac(scanResult.BSSID);
49ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mHESSID = scanResult.hessid;
50ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mAnqpDomID = scanResult.anqpDomainId;
51ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mAdvertisingSSID = scanResult.SSID;
52ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mOSUProvider = osuProvider;
53ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
54ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
55ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public long getOSUBssid() {
56ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return mOSUBssid;
57ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
58ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
59ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public void setOSUBssid(long OSUBssid) {
60ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        mOSUBssid = OSUBssid;
61ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
62ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
63ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public long getHESSID() {
64ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return mHESSID;
65ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
66ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
67ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public int getAnqpDomID() {
68ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return mAnqpDomID;
69ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
70ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
710ff7a0a25679b1a4d483c6f750973c57b25b6826Jan Nordqvist    public String getAdvertisingSsid() {
72ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return mAdvertisingSSID;
73ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
74ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
75ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public Set<Locale> getNameLocales() {
76ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        Set<Locale> locales = new HashSet<>(mOSUProvider.getNames().size());
77ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (I18Name name : mOSUProvider.getNames()) {
78ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            locales.add(name.getLocale());
79ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
80ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return locales;
81ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
82ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
83ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public Set<Locale> getServiceLocales() {
84ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        Set<Locale> locales = new HashSet<>(mOSUProvider.getServiceDescriptions().size());
85ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (I18Name name : mOSUProvider.getServiceDescriptions()) {
86ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            locales.add(name.getLocale());
87ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
88ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return locales;
89ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
90ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
91ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public Set<String> getIconLanguages() {
92ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        Set<String> locales = new HashSet<>(mOSUProvider.getIcons().size());
93ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (IconInfo iconInfo : mOSUProvider.getIcons()) {
94ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            locales.add(iconInfo.getLanguage());
95ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
96ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return locales;
97ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
98ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
99ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public String getName(Locale locale) {
100ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        List<ScoreEntry<String>> scoreList = new ArrayList<>();
101ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (I18Name name : mOSUProvider.getNames()) {
102ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            if (locale == null || name.getLocale().equals(locale)) {
103ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                return name.getText();
104ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
1050701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist            scoreList.add(new ScoreEntry<>(name.getText(),
106ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    languageScore(name.getLanguage(), locale)));
107ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
108ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        Collections.sort(scoreList);
1090701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        return scoreList.isEmpty() ? null : scoreList.get(scoreList.size() - 1).getData();
110ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
111ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
112ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public String getServiceDescription(Locale locale) {
113ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        List<ScoreEntry<String>> scoreList = new ArrayList<>();
114ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (I18Name service : mOSUProvider.getServiceDescriptions()) {
115ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            if (locale == null || service.getLocale().equals(locale)) {
116ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                return service.getText();
117ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
118ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            scoreList.add(new ScoreEntry<>(service.getText(),
119ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    languageScore(service.getLanguage(), locale)));
120ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
121ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        Collections.sort(scoreList);
1220701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        return scoreList.isEmpty() ? null : scoreList.get(scoreList.size() - 1).getData();
123ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
124ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
125ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public int getOsuID() {
126ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return mOsuID;
127ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
128ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
129ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public void setIconStatus(IconStatus iconStatus) {
130ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        synchronized (mOSUProvider) {
131ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            mIconStatus = iconStatus;
132ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
133ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
134ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
135ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public IconStatus getIconStatus() {
136ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        synchronized (mOSUProvider) {
137ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return mIconStatus;
138ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
139ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
140ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
141ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public HSIconFileElement getIconFileElement() {
142ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        synchronized (mOSUProvider) {
143ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return mIconFileElement;
144ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
145ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
146ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
147ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public IconInfo getIconInfo() {
148ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        synchronized (mOSUProvider) {
149ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return mIconInfo;
150ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
151ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
152ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
1530ff7a0a25679b1a4d483c6f750973c57b25b6826Jan Nordqvist    public String getIconFileName() {
1540ff7a0a25679b1a4d483c6f750973c57b25b6826Jan Nordqvist        return mIconFileName;
1550ff7a0a25679b1a4d483c6f750973c57b25b6826Jan Nordqvist    }
1560ff7a0a25679b1a4d483c6f750973c57b25b6826Jan Nordqvist
157ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public void setIconFileElement(HSIconFileElement iconFileElement, String fileName) {
158ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        synchronized (mOSUProvider) {
159ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            mIconFileElement = iconFileElement;
160ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            for (IconInfo iconInfo : mOSUProvider.getIcons()) {
161ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                if (iconInfo.getFileName().equals(fileName)) {
162ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    mIconInfo = iconInfo;
1630ff7a0a25679b1a4d483c6f750973c57b25b6826Jan Nordqvist                    mIconFileName = fileName;
164ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                    break;
165ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                }
166ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
167ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            mIconStatus = IconStatus.Available;
168ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
169ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
170ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
171ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private static class ScoreEntry<T> implements Comparable<ScoreEntry> {
172ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        private final T mData;
173ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        private final int mScore;
174ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
175ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        private ScoreEntry(T data, int score) {
176ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            mData = data;
177ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            mScore = score;
178ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
179ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
180ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        public T getData() {
181ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return mData;
182ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
183ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
184ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        @Override
185ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        public int compareTo(ScoreEntry other) {
186ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return Integer.compare(mScore, other.mScore);
187ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
1880701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist
1890701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        @Override
1900701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        public String toString() {
1910701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist            return String.format("%d for '%s'", mScore, mData);
1920701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        }
193ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
194ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
195ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public List<IconInfo> getIconInfo(Locale locale, Set<String> types, int width, int height) {
196ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (mOSUProvider.getIcons().isEmpty()) {
197ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return null;
198ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
199ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        Log.d(OSUManager.TAG, "Matching icons against " + locale
200ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                + ", types " + types + ", " + width + "*" + height);
201ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
202ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        List<ScoreEntry<IconInfo>> matches = new ArrayList<>();
203ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        for (IconInfo iconInfo : mOSUProvider.getIcons()) {
204ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            Log.d(OSUManager.TAG, "Checking icon " + iconInfo.toString());
205ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            if (!types.contains(iconInfo.getIconType())) {
206ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                continue;
207ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
208ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
209ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            int score = languageScore(iconInfo.getLanguage(), locale);
210ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            int delta = iconInfo.getWidth() - width;
211ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            // Best size score is 1024 for a exact match, i.e. 2048 if both sides match
212ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            if (delta >= 0) {
213ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                score += (256 - delta) * 4;  // Prefer down-scaling
214ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            } else {
215ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                score += 256 + delta;    // Before up-scaling
216ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
217ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            delta = iconInfo.getHeight() - height;
218ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            if (delta >= 0) {
219ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                score += (256 - delta) * 4;
220ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            } else {
221ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                score += 256 + delta;
222ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            }
223ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            matches.add(new ScoreEntry<>(iconInfo, score));
224ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
225ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (matches.isEmpty()) {
226ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return Collections.emptyList();
227ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
228ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        Collections.sort(matches);
229ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        List<IconInfo> icons = new ArrayList<>(matches.size());
2300701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        ListIterator<ScoreEntry<IconInfo>> matchIterator = matches.listIterator(matches.size());
2310701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        while (matchIterator.hasPrevious()) {
2320701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist            icons.add(matchIterator.previous().getData());
233ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
234ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return icons;
235ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
236ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
237ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    private static int languageScore(String language, Locale locale) {
238ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        if (language.length() == 3 && language.equalsIgnoreCase(locale.getISO3Language()) ||
239ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist                language.length() == 2 && language.equalsIgnoreCase(locale.getLanguage())) {
240ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return 4096;
241ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        } else if (language.equalsIgnoreCase(GenericLocale)) {
242ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return 3072;
243ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        } else if (language.equalsIgnoreCase("eng")) {
244ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return 2048;
245ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        } else {
246ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist            return 1024;
247ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        }
248ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
249ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
250ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public long getBSSID() {
251ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return mBSSID;
252ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
253ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
2540ff7a0a25679b1a4d483c6f750973c57b25b6826Jan Nordqvist    public String getOsuSsid() {
2550701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        return mOSUProvider.getSSID();
256ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
257ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
258ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public OSUProvider getOSUProvider() {
259ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return mOSUProvider;
260ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
261ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist
262ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    @Override
263ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    public String toString() {
264ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist        return String.format("OSU Info '%s' %012x -> %s, icon %s",
2650701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist                getOsuSsid(), mBSSID, getServiceDescription(null), mIconStatus);
2660701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist    }
2670701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist
2680701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist    private OSUInfo(Parcel in) {
2690701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mBSSID = in.readLong();
2700701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mHESSID = in.readLong();
2710701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mAnqpDomID = in.readInt();
2720701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mAdvertisingSSID = in.readString();
2730701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mOsuID = in.readInt();
2740701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mOSUBssid = in.readLong();
2750701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mIconFileName = in.readString();
2760701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mIconStatus = Utils.mapEnum(in.readInt(), IconStatus.class);
2770701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        OSUProvider osuProvider;
2780701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        try {
2790701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist            osuProvider = new OSUProvider(in);
2800701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        } catch (IOException ioe) {
2810701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist            osuProvider = null;
2820701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        }
2830701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mOSUProvider = osuProvider;
2840701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        if (osuProvider == null) {
2850701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist            return;
2860701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        }
2870701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mIconFileElement = new HSIconFileElement(in);
2880701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        int iconIndex = in.readInt();
2890701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mIconInfo = iconIndex >= 0 && iconIndex < mOSUProvider.getIcons().size()
2900701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist                ? mOSUProvider.getIcons().get(iconIndex) : null;
2910701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist    }
2920701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist
2930701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist    public static final Parcelable.Creator<OSUInfo> CREATOR = new Parcelable.Creator<OSUInfo>() {
2940701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        public OSUInfo createFromParcel(Parcel in) {
2950701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist            return new OSUInfo(in);
2960701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        }
2970701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist
2980701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        public OSUInfo[] newArray(int size) {
2990701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist            return new OSUInfo[size];
3000701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        }
3010701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist    };
3020701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist
3030701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist    @Override
3040701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist    public int describeContents() {
3050701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        return 0;
3060701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist    }
3070701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist
3080701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist    @Override
3090701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist    public void writeToParcel(Parcel dest, int flags) {
3100701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        dest.writeLong(mBSSID);
3110701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        dest.writeLong(mHESSID);
3120701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        dest.writeInt(mAnqpDomID);
3130701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        dest.writeString(mAdvertisingSSID);
3140701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        dest.writeInt(mOsuID);
3150701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        dest.writeLong(mOSUBssid);
3160701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        dest.writeString(mIconFileName);
3170701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        dest.writeInt(mIconStatus.ordinal());
3180701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mOSUProvider.writeParcel(dest);
3190701952aaa17dcef461d3a538048243d9fe690f1Jan Nordqvist        mIconFileElement.writeParcel(dest);
320ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist    }
321ee699a61a5687d7c8518b639a940c8e9d1b384ddJan Nordqvist}
322