ScanDetailCache.java revision 4d381bc39f5263effdae73ec99065eb299b806ca
1 2package com.android.server.wifi; 3 4import android.net.wifi.ScanResult; 5import android.net.wifi.WifiConfiguration; 6 7import com.android.server.wifi.ScanDetail; 8import com.android.server.wifi.hotspot2.PasspointMatch; 9import com.android.server.wifi.hotspot2.PasspointMatchInfo; 10import com.android.server.wifi.hotspot2.pps.HomeSP; 11 12import java.util.ArrayList; 13import java.util.Collection; 14import java.util.Collections; 15import java.util.Comparator; 16import java.util.HashMap; 17import java.util.Iterator; 18import java.util.List; 19 20class ScanDetailCache { 21 private WifiConfiguration mConfig; 22 private HashMap<String, ScanDetail> mMap; 23 private HashMap<String, PasspointMatchInfo> mPasspointMatches; 24 25 ScanDetailCache(WifiConfiguration config) { 26 mConfig = config; 27 mMap = new HashMap(); 28 mPasspointMatches = new HashMap(); 29 } 30 31 void put(ScanDetail scanDetail) { 32 put(scanDetail, null, null); 33 } 34 35 void put(ScanDetail scanDetail, PasspointMatch match, HomeSP homeSp) { 36 mMap.put(scanDetail.getBSSIDString(), scanDetail); 37 mPasspointMatches.put(scanDetail.getBSSIDString(), 38 new PasspointMatchInfo(match, scanDetail, homeSp)); 39 } 40 41 ScanResult get(String bssid) { 42 ScanDetail scanDetail = getScanDetail(bssid); 43 return scanDetail == null ? null : scanDetail.getScanResult(); 44 } 45 46 ScanDetail getScanDetail(String bssid) { 47 return mMap.get(bssid); 48 } 49 50 void remove(String bssid) { 51 mMap.remove(bssid); 52 } 53 54 int size() { 55 return mMap.size(); 56 } 57 58 boolean isEmpty() { 59 return size() == 0; 60 } 61 62 ScanDetail getFirst() { 63 Iterator<ScanDetail> it = mMap.values().iterator(); 64 return it.hasNext() ? it.next() : null; 65 } 66 67 Collection<String> keySet() { 68 return mMap.keySet(); 69 } 70 71 Collection<ScanDetail> values() { 72 return mMap.values(); 73 } 74 75 public void trim(int num) { 76 int currentSize = mMap.size(); 77 if (currentSize <= num) { 78 return; // Nothing to trim 79 } 80 ArrayList<ScanDetail> list = new ArrayList<ScanDetail>(mMap.values()); 81 if (list.size() != 0) { 82 // Sort by descending timestamp 83 Collections.sort(list, new Comparator() { 84 public int compare(Object o1, Object o2) { 85 ScanDetail a = (ScanDetail) o1; 86 ScanDetail b = (ScanDetail) o2; 87 if (a.getSeen() > b.getSeen()) { 88 return 1; 89 } 90 if (a.getSeen() < b.getSeen()) { 91 return -1; 92 } 93 return a.getBSSIDString().compareTo(b.getBSSIDString()); 94 } 95 }); 96 } 97 for (int i = 0; i < currentSize - num ; i++) { 98 // Remove oldest results from scan cache 99 ScanDetail result = list.get(i); 100 mMap.remove(result.getBSSIDString()); 101 mPasspointMatches.remove(result.getBSSIDString()); 102 } 103 } 104 105 /* @hide */ 106 private ArrayList<ScanDetail> sort() { 107 ArrayList<ScanDetail> list = new ArrayList<ScanDetail>(mMap.values()); 108 if (list.size() != 0) { 109 Collections.sort(list, new Comparator() { 110 public int compare(Object o1, Object o2) { 111 ScanResult a = ((ScanDetail)o1).getScanResult(); 112 ScanResult b = ((ScanDetail)o2).getScanResult(); 113 if (a.numIpConfigFailures > b.numIpConfigFailures) { 114 return 1; 115 } 116 if (a.numIpConfigFailures < b.numIpConfigFailures) { 117 return -1; 118 } 119 if (a.seen > b.seen) { 120 return -1; 121 } 122 if (a.seen < b.seen) { 123 return 1; 124 } 125 if (a.level > b.level) { 126 return -1; 127 } 128 if (a.level < b.level) { 129 return 1; 130 } 131 return a.BSSID.compareTo(b.BSSID); 132 } 133 }); 134 } 135 return list; 136 } 137 138 public WifiConfiguration.Visibility getVisibilityByRssi(long age) { 139 WifiConfiguration.Visibility status = new WifiConfiguration.Visibility(); 140 141 long now_ms = System.currentTimeMillis(); 142 for(ScanDetail scanDetail : values()) { 143 ScanResult result = scanDetail.getScanResult(); 144 if (scanDetail.getSeen() == 0) 145 continue; 146 147 if (result.is5GHz()) { 148 //strictly speaking: [4915, 5825] 149 //number of known BSSID on 5GHz band 150 status.num5 = status.num5 + 1; 151 } else if (result.is24GHz()) { 152 //strictly speaking: [2412, 2482] 153 //number of known BSSID on 2.4Ghz band 154 status.num24 = status.num24 + 1; 155 } 156 157 if ((now_ms - result.seen) > age) continue; 158 159 if (result.is5GHz()) { 160 if (result.level > status.rssi5) { 161 status.rssi5 = result.level; 162 status.age5 = result.seen; 163 status.BSSID5 = result.BSSID; 164 } 165 } else if (result.is24GHz()) { 166 if (result.level > status.rssi24) { 167 status.rssi24 = result.level; 168 status.age24 = result.seen; 169 status.BSSID24 = result.BSSID; 170 } 171 } 172 } 173 174 return status; 175 } 176 177 public WifiConfiguration.Visibility getVisibilityByPasspointMatch(long age) { 178 WifiConfiguration.Visibility status = new WifiConfiguration.Visibility(); 179 180 long now_ms = System.currentTimeMillis(); 181 for(ScanDetail scanDetail : values()) { 182 ScanResult result = scanDetail.getScanResult(); 183 if (scanDetail.getSeen() == 0) 184 continue; 185 186 if (result.is5GHz()) { 187 //strictly speaking: [4915, 5825] 188 //number of known BSSID on 5GHz band 189 status.num5 = status.num5 + 1; 190 } else if (result.is24GHz()) { 191 //strictly speaking: [2412, 2482] 192 //number of known BSSID on 2.4Ghz band 193 status.num24 = status.num24 + 1; 194 } 195 196 if ((now_ms - result.seen) > age) continue; 197 198 if (result.is5GHz()) { 199 if (result.level > status.rssi5) { 200 status.rssi5 = result.level; 201 status.age5 = result.seen; 202 status.BSSID5 = result.BSSID; 203 } 204 } else if (result.is24GHz()) { 205 if (result.level > status.rssi24) { 206 status.rssi24 = result.level; 207 status.age24 = result.seen; 208 status.BSSID24 = result.BSSID; 209 } 210 } 211 } 212 213 return status; 214 } 215 216 public WifiConfiguration.Visibility getVisibility(long age) { 217 if (mConfig.isPasspoint()) { 218 return getVisibilityByPasspointMatch(age); 219 } else { 220 return getVisibilityByRssi(age); 221 } 222 } 223 224 225 226 @Override 227 public String toString() { 228 StringBuilder sbuf = new StringBuilder(); 229 sbuf.append("Scan Cache: ").append('\n'); 230 231 ArrayList<ScanDetail> list = sort(); 232 long now_ms = System.currentTimeMillis(); 233 if (list.size() > 0) { 234 for (ScanDetail scanDetail : list) { 235 ScanResult result = scanDetail.getScanResult(); 236 long milli = now_ms - scanDetail.getSeen(); 237 long ageSec = 0; 238 long ageMin = 0; 239 long ageHour = 0; 240 long ageMilli = 0; 241 long ageDay = 0; 242 if (now_ms > scanDetail.getSeen() && scanDetail.getSeen() > 0) { 243 ageMilli = milli % 1000; 244 ageSec = (milli / 1000) % 60; 245 ageMin = (milli / (60*1000)) % 60; 246 ageHour = (milli / (60*60*1000)) % 24; 247 ageDay = (milli / (24*60*60*1000)); 248 } 249 sbuf.append("{").append(result.BSSID).append(",").append(result.frequency); 250 sbuf.append(",").append(String.format("%3d", result.level)); 251 if (result.autoJoinStatus > 0) { 252 sbuf.append(",st=").append(result.autoJoinStatus); 253 } 254 if (ageSec > 0 || ageMilli > 0) { 255 sbuf.append(String.format(",%4d.%02d.%02d.%02d.%03dms", ageDay, 256 ageHour, ageMin, ageSec, ageMilli)); 257 } 258 if (result.numIpConfigFailures > 0) { 259 sbuf.append(",ipfail="); 260 sbuf.append(result.numIpConfigFailures); 261 } 262 sbuf.append("} "); 263 } 264 sbuf.append('\n'); 265 } 266 267 return sbuf.toString(); 268 } 269 270} 271