• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.server.wifi.hotspot2;
2 
3 import com.android.server.wifi.ScanDetail;
4 import com.android.server.wifi.anqp.ANQPElement;
5 import com.android.server.wifi.anqp.HSConnectionCapabilityElement;
6 import com.android.server.wifi.anqp.HSWanMetricsElement;
7 import com.android.server.wifi.anqp.IPAddressTypeAvailabilityElement;
8 import com.android.server.wifi.hotspot2.pps.HomeSP;
9 
10 import java.util.EnumMap;
11 import java.util.HashMap;
12 import java.util.Map;
13 
14 import static com.android.server.wifi.anqp.Constants.ANQPElementType;
15 import static com.android.server.wifi.anqp.IPAddressTypeAvailabilityElement.IPv4Availability;
16 import static com.android.server.wifi.anqp.IPAddressTypeAvailabilityElement.IPv6Availability;
17 
18 public class PasspointMatchInfo implements Comparable<PasspointMatchInfo> {
19     private final PasspointMatch mPasspointMatch;
20     private final ScanDetail mScanDetail;
21     private final HomeSP mHomeSP;
22     private final int mScore;
23 
24     private static final Map<IPv4Availability, Integer> sIP4Scores =
25             new EnumMap<>(IPv4Availability.class);
26     private static final Map<IPv6Availability, Integer> sIP6Scores =
27             new EnumMap<>(IPv6Availability.class);
28 
29     private static final Map<Integer, Map<Integer, Integer>> sPortScores = new HashMap<>();
30 
31     private static final int IPPROTO_ICMP = 1;
32     private static final int IPPROTO_TCP = 6;
33     private static final int IPPROTO_UDP = 17;
34     private static final int IPPROTO_ESP = 50;
35     private static final Map<NetworkDetail.Ant, Integer> sAntScores = new HashMap<>();
36 
37     static {
38         // These are all arbitrarily chosen scores, subject to tuning.
39 
sAntScores.put(NetworkDetail.Ant.FreePublic, 4)40         sAntScores.put(NetworkDetail.Ant.FreePublic, 4);
sAntScores.put(NetworkDetail.Ant.ChargeablePublic, 4)41         sAntScores.put(NetworkDetail.Ant.ChargeablePublic, 4);
sAntScores.put(NetworkDetail.Ant.PrivateWithGuest, 4)42         sAntScores.put(NetworkDetail.Ant.PrivateWithGuest, 4);
sAntScores.put(NetworkDetail.Ant.Private, 4)43         sAntScores.put(NetworkDetail.Ant.Private, 4);
sAntScores.put(NetworkDetail.Ant.Personal, 2)44         sAntScores.put(NetworkDetail.Ant.Personal, 2);
sAntScores.put(NetworkDetail.Ant.EmergencyOnly, 2)45         sAntScores.put(NetworkDetail.Ant.EmergencyOnly, 2);
sAntScores.put(NetworkDetail.Ant.Wildcard, 1)46         sAntScores.put(NetworkDetail.Ant.Wildcard, 1);
sAntScores.put(NetworkDetail.Ant.TestOrExperimental, 0)47         sAntScores.put(NetworkDetail.Ant.TestOrExperimental, 0);
48 
sIP4Scores.put(IPv4Availability.NotAvailable, 0)49         sIP4Scores.put(IPv4Availability.NotAvailable, 0);
sIP4Scores.put(IPv4Availability.PortRestricted, 1)50         sIP4Scores.put(IPv4Availability.PortRestricted, 1);
sIP4Scores.put(IPv4Availability.PortRestrictedAndSingleNAT, 1)51         sIP4Scores.put(IPv4Availability.PortRestrictedAndSingleNAT, 1);
sIP4Scores.put(IPv4Availability.PortRestrictedAndDoubleNAT, 1)52         sIP4Scores.put(IPv4Availability.PortRestrictedAndDoubleNAT, 1);
sIP4Scores.put(IPv4Availability.Unknown, 1)53         sIP4Scores.put(IPv4Availability.Unknown, 1);
sIP4Scores.put(IPv4Availability.Public, 2)54         sIP4Scores.put(IPv4Availability.Public, 2);
sIP4Scores.put(IPv4Availability.SingleNAT, 2)55         sIP4Scores.put(IPv4Availability.SingleNAT, 2);
sIP4Scores.put(IPv4Availability.DoubleNAT, 2)56         sIP4Scores.put(IPv4Availability.DoubleNAT, 2);
57 
sIP6Scores.put(IPv6Availability.NotAvailable, 0)58         sIP6Scores.put(IPv6Availability.NotAvailable, 0);
sIP6Scores.put(IPv6Availability.Reserved, 1)59         sIP6Scores.put(IPv6Availability.Reserved, 1);
sIP6Scores.put(IPv6Availability.Unknown, 1)60         sIP6Scores.put(IPv6Availability.Unknown, 1);
sIP6Scores.put(IPv6Availability.Available, 2)61         sIP6Scores.put(IPv6Availability.Available, 2);
62 
63         Map<Integer, Integer> tcpMap = new HashMap<>();
64         tcpMap.put(20, 1);
65         tcpMap.put(21, 1);
66         tcpMap.put(22, 3);
67         tcpMap.put(23, 2);
68         tcpMap.put(25, 8);
69         tcpMap.put(26, 8);
70         tcpMap.put(53, 3);
71         tcpMap.put(80, 10);
72         tcpMap.put(110, 6);
73         tcpMap.put(143, 6);
74         tcpMap.put(443, 10);
75         tcpMap.put(993, 6);
76         tcpMap.put(1723, 7);
77 
78         Map<Integer, Integer> udpMap = new HashMap<>();
79         udpMap.put(53, 10);
80         udpMap.put(500, 7);
81         udpMap.put(5060, 10);
82         udpMap.put(4500, 4);
83 
sPortScores.put(IPPROTO_TCP, tcpMap)84         sPortScores.put(IPPROTO_TCP, tcpMap);
sPortScores.put(IPPROTO_UDP, udpMap)85         sPortScores.put(IPPROTO_UDP, udpMap);
86     }
87 
88 
PasspointMatchInfo(PasspointMatch passpointMatch, ScanDetail scanDetail, HomeSP homeSP)89     public PasspointMatchInfo(PasspointMatch passpointMatch,
90                               ScanDetail scanDetail, HomeSP homeSP) {
91         mPasspointMatch = passpointMatch;
92         mScanDetail = scanDetail;
93         mHomeSP = homeSP;
94 
95         int score;
96         if (passpointMatch == PasspointMatch.HomeProvider) {
97             score = 100;
98         }
99         else if (passpointMatch == PasspointMatch.RoamingProvider) {
100             score = 0;
101         }
102         else {
103             score = -1000;  // Don't expect to see anything not home or roaming.
104         }
105 
106         if (getNetworkDetail().getHSRelease() != null) {
107             score += getNetworkDetail().getHSRelease() != NetworkDetail.HSRelease.Unknown ? 50 : 0;
108         }
109 
110         if (getNetworkDetail().hasInterworking()) {
111             score += getNetworkDetail().isInternet() ? 20 : -20;
112         }
113 
114         score += (Math.max(200-getNetworkDetail().getStationCount(), 0) *
115                 (255-getNetworkDetail().getChannelUtilization()) *
116                 getNetworkDetail().getCapacity()) >>> 26;
117                 // Gives a value of 23 max capped at 200 stations and max cap 31250
118 
119         if (getNetworkDetail().hasInterworking()) {
120             score += sAntScores.get(getNetworkDetail().getAnt());
121         }
122 
123         Map<ANQPElementType, ANQPElement> anqp = getNetworkDetail().getANQPElements();
124 
125         if (anqp != null) {
126             HSWanMetricsElement wm = (HSWanMetricsElement) anqp.get(ANQPElementType.HSWANMetrics);
127 
128             if (wm != null) {
129                 if (wm.getStatus() != HSWanMetricsElement.LinkStatus.Up || wm.isCapped()) {
130                     score -= 1000;
131                 } else {
132                     long scaledSpeed =
133                             wm.getDlSpeed() * (255 - wm.getDlLoad()) * 8 +
134                                     wm.getUlSpeed() * (255 - wm.getUlLoad()) * 2;
135                     score += Math.min(scaledSpeed, 255000000L) >>> 23;
136                     // Max value is 30 capped at 100Mb/s
137                 }
138             }
139 
140             IPAddressTypeAvailabilityElement ipa =
141                     (IPAddressTypeAvailabilityElement) anqp.get(ANQPElementType.ANQPIPAddrAvailability);
142 
143             if (ipa != null) {
144                 Integer as14 = sIP4Scores.get(ipa.getV4Availability());
145                 Integer as16 = sIP6Scores.get(ipa.getV6Availability());
146                 as14 = as14 != null ? as14 : 1;
147                 as16 = as16 != null ? as16 : 1;
148                 // Is IPv4 twice as important as IPv6???
149                 score += as14 * 2 + as16;
150             }
151 
152             HSConnectionCapabilityElement cce =
153                     (HSConnectionCapabilityElement) anqp.get(ANQPElementType.HSConnCapability);
154 
155             if (cce != null) {
156                 score = Math.min(Math.max(protoScore(cce) >> 3, -10), 10);
157             }
158         }
159 
160         mScore = score;
161     }
162 
getPasspointMatch()163     public PasspointMatch getPasspointMatch() {
164         return mPasspointMatch;
165     }
166 
getScanDetail()167     public ScanDetail getScanDetail() {
168         return mScanDetail;
169     }
170 
getNetworkDetail()171     public NetworkDetail getNetworkDetail() {
172         return mScanDetail.getNetworkDetail();
173     }
174 
175 
getHomeSP()176     public HomeSP getHomeSP() {
177         return mHomeSP;
178     }
179 
getScore()180     public int getScore() {
181         return mScore;
182     }
183 
184     @Override
compareTo(PasspointMatchInfo that)185     public int compareTo(PasspointMatchInfo that) {
186         return getScore() - that.getScore();
187     }
188 
protoScore(HSConnectionCapabilityElement cce)189     private static int protoScore(HSConnectionCapabilityElement cce) {
190         int score = 0;
191         for (HSConnectionCapabilityElement.ProtocolTuple tuple : cce.getStatusList()) {
192             int sign = tuple.getStatus() == HSConnectionCapabilityElement.ProtoStatus.Open ?
193                     1 : -1;
194 
195             int elementScore = 1;
196             if (tuple.getProtocol() == IPPROTO_ICMP) {
197                 elementScore = 1;
198             }
199             else if (tuple.getProtocol() == IPPROTO_ESP) {
200                 elementScore = 5;
201             }
202             else {
203                 Map<Integer, Integer> protoMap = sPortScores.get(tuple.getProtocol());
204                 if (protoMap != null) {
205                     Integer portScore = protoMap.get(tuple.getPort());
206                     elementScore = portScore != null ? portScore : 0;
207                 }
208             }
209             score += elementScore * sign;
210         }
211         return score;
212     }
213 
214     @Override
equals(Object thatObject)215     public boolean equals(Object thatObject) {
216         if (this == thatObject) {
217             return true;
218         }
219         if (thatObject == null || getClass() != thatObject.getClass()) {
220             return false;
221         }
222 
223         PasspointMatchInfo that = (PasspointMatchInfo)thatObject;
224 
225         return getNetworkDetail().equals(that.getNetworkDetail()) &&
226                 getHomeSP().equals(that.getHomeSP()) &&
227                 getPasspointMatch().equals(that.getPasspointMatch());
228     }
229 
230     @Override
hashCode()231     public int hashCode() {
232         int result = mPasspointMatch != null ? mPasspointMatch.hashCode() : 0;
233         result = 31 * result + getNetworkDetail().hashCode();
234         result = 31 * result + (mHomeSP != null ? mHomeSP.hashCode() : 0);
235         return result;
236     }
237 
238     @Override
toString()239     public String toString() {
240         return "PasspointMatchInfo{" +
241                 ", mPasspointMatch=" + mPasspointMatch +
242                 ", mNetworkInfo=" + getNetworkDetail().getSSID() +
243                 ", mHomeSP=" + mHomeSP.getFQDN() +
244                 '}';
245     }
246 }
247