1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi.hotspot2; 18 19import android.net.RssiCurve; 20 21import com.android.internal.annotations.VisibleForTesting; 22import com.android.server.wifi.ScanDetail; 23import com.android.server.wifi.hotspot2.anqp.ANQPElement; 24import com.android.server.wifi.hotspot2.anqp.Constants.ANQPElementType; 25import com.android.server.wifi.hotspot2.anqp.HSWanMetricsElement; 26import com.android.server.wifi.hotspot2.anqp.IPAddressTypeAvailabilityElement; 27 28import java.util.HashMap; 29import java.util.Map; 30 31/** 32 * This is an utility class for calculating score for Passpoint networks. 33 */ 34public class PasspointNetworkScore { 35 /** 36 * Award points for network that's a Passpoint home provider. 37 */ 38 @VisibleForTesting 39 public static final int HOME_PROVIDER_AWARD = 100; 40 41 /** 42 * Award points for network that provides Internet access. 43 */ 44 @VisibleForTesting 45 public static final int INTERNET_ACCESS_AWARD = 50; 46 47 /** 48 * Award points for public or private network. 49 */ 50 @VisibleForTesting 51 public static final int PUBLIC_OR_PRIVATE_NETWORK_AWARDS = 4; 52 53 /** 54 * Award points for personal or emergency network. 55 */ 56 @VisibleForTesting 57 public static final int PERSONAL_OR_EMERGENCY_NETWORK_AWARDS = 2; 58 59 /** 60 * Award points for network providing restricted or unknown IP address. 61 */ 62 @VisibleForTesting 63 public static final int RESTRICTED_OR_UNKNOWN_IP_AWARDS = 1; 64 65 /** 66 * Award points for network providing unrestricted IP address. 67 */ 68 @VisibleForTesting 69 public static final int UNRESTRICTED_IP_AWARDS = 2; 70 71 /** 72 * Penalty points for network with WAN port that's down or the load already reached the max. 73 */ 74 @VisibleForTesting 75 public static final int WAN_PORT_DOWN_OR_CAPPED_PENALTY = 50; 76 77 // Award points for availability of IPv4 and IPv6 addresses. 78 private static final Map<Integer, Integer> IPV4_SCORES = new HashMap<>(); 79 private static final Map<Integer, Integer> IPV6_SCORES = new HashMap<>(); 80 81 // Award points based on access network type. 82 private static final Map<NetworkDetail.Ant, Integer> NETWORK_TYPE_SCORES = new HashMap<>(); 83 84 /** 85 * Curve for calculating score for RSSI level. 86 */ 87 @VisibleForTesting 88 public static final RssiCurve RSSI_SCORE = new RssiCurve(-80 /* start */, 20 /* bucketWidth */, 89 new byte[] {-10, 0, 10, 20, 30, 40} /* rssiBuckets */, 90 20 /* activeNetworkRssiBoost */); 91 92 static { 93 // These are all arbitrarily chosen scores, subject to tuning. 94 95 NETWORK_TYPE_SCORES.put(NetworkDetail.Ant.FreePublic, PUBLIC_OR_PRIVATE_NETWORK_AWARDS); 96 NETWORK_TYPE_SCORES.put(NetworkDetail.Ant.ChargeablePublic, 97 PUBLIC_OR_PRIVATE_NETWORK_AWARDS); 98 NETWORK_TYPE_SCORES.put(NetworkDetail.Ant.PrivateWithGuest, 99 PUBLIC_OR_PRIVATE_NETWORK_AWARDS); 100 NETWORK_TYPE_SCORES.put(NetworkDetail.Ant.Private, 101 PUBLIC_OR_PRIVATE_NETWORK_AWARDS); 102 NETWORK_TYPE_SCORES.put(NetworkDetail.Ant.Personal, PERSONAL_OR_EMERGENCY_NETWORK_AWARDS); 103 NETWORK_TYPE_SCORES.put(NetworkDetail.Ant.EmergencyOnly, 104 PERSONAL_OR_EMERGENCY_NETWORK_AWARDS); 105 NETWORK_TYPE_SCORES.put(NetworkDetail.Ant.Wildcard, 0); 106 NETWORK_TYPE_SCORES.put(NetworkDetail.Ant.TestOrExperimental, 0); 107 108 IPV4_SCORES.put(IPAddressTypeAvailabilityElement.IPV4_NOT_AVAILABLE, 0); 109 IPV4_SCORES.put(IPAddressTypeAvailabilityElement.IPV4_PORT_RESTRICTED, 110 RESTRICTED_OR_UNKNOWN_IP_AWARDS); 111 IPV4_SCORES.put(IPAddressTypeAvailabilityElement.IPV4_PORT_RESTRICTED_AND_SINGLE_NAT, 112 RESTRICTED_OR_UNKNOWN_IP_AWARDS); 113 IPV4_SCORES.put(IPAddressTypeAvailabilityElement.IPV4_PORT_RESTRICTED_AND_DOUBLE_NAT, 114 RESTRICTED_OR_UNKNOWN_IP_AWARDS); 115 IPV4_SCORES.put(IPAddressTypeAvailabilityElement.IPV4_UNKNOWN, 116 RESTRICTED_OR_UNKNOWN_IP_AWARDS); 117 IPV4_SCORES.put(IPAddressTypeAvailabilityElement.IPV4_PUBLIC, UNRESTRICTED_IP_AWARDS); 118 IPV4_SCORES.put(IPAddressTypeAvailabilityElement.IPV4_SINGLE_NAT, UNRESTRICTED_IP_AWARDS); 119 IPV4_SCORES.put(IPAddressTypeAvailabilityElement.IPV4_DOUBLE_NAT, UNRESTRICTED_IP_AWARDS); 120 121 IPV6_SCORES.put(IPAddressTypeAvailabilityElement.IPV6_NOT_AVAILABLE, 0); 122 IPV6_SCORES.put(IPAddressTypeAvailabilityElement.IPV6_UNKNOWN, 123 RESTRICTED_OR_UNKNOWN_IP_AWARDS); 124 IPV6_SCORES.put(IPAddressTypeAvailabilityElement.IPV6_AVAILABLE, 125 UNRESTRICTED_IP_AWARDS); 126 } 127 128 129 /** 130 * Calculate and return a score associated with the given Passpoint network. 131 * The score is calculated with the following preferences: 132 * - Prefer home provider 133 * - Prefer network that provides Internet access 134 * - Prefer network with active WAN port with available load 135 * - Prefer network that provides unrestricted IP address 136 * - Prefer currently active network 137 * - Prefer AP with higher RSSI 138 * 139 * This can be expanded for additional preference in the future (e.g. AP station count, link 140 * speed, and etc). 141 * 142 * @param isHomeProvider Flag indicating home provider 143 * @param scanDetail The ScanDetail associated with the AP 144 * @param isActiveNetwork Flag indicating current active network 145 * @return integer score 146 */ 147 public static int calculateScore(boolean isHomeProvider, ScanDetail scanDetail, 148 Map<ANQPElementType, ANQPElement> anqpElements, boolean isActiveNetwork) { 149 NetworkDetail networkDetail = scanDetail.getNetworkDetail(); 150 int score = 0; 151 if (isHomeProvider) { 152 score += HOME_PROVIDER_AWARD; 153 } 154 155 // Adjust score based on Internet accessibility. 156 score += (networkDetail.isInternet() ? 1 : -1) * INTERNET_ACCESS_AWARD; 157 158 // Adjust score based on the network type. 159 score += NETWORK_TYPE_SCORES.get(networkDetail.getAnt()); 160 161 if (anqpElements != null) { 162 HSWanMetricsElement wm = 163 (HSWanMetricsElement) anqpElements.get(ANQPElementType.HSWANMetrics); 164 if (wm != null) { 165 if (wm.getStatus() != HSWanMetricsElement.LINK_STATUS_UP || wm.isCapped()) { 166 score -= WAN_PORT_DOWN_OR_CAPPED_PENALTY; 167 } 168 } 169 170 IPAddressTypeAvailabilityElement ipa = (IPAddressTypeAvailabilityElement) 171 anqpElements.get(ANQPElementType.ANQPIPAddrAvailability); 172 173 if (ipa != null) { 174 Integer v4Score = IPV4_SCORES.get(ipa.getV4Availability()); 175 Integer v6Score = IPV6_SCORES.get(ipa.getV6Availability()); 176 v4Score = v4Score != null ? v4Score : 0; 177 v6Score = v6Score != null ? v6Score : 0; 178 score += (v4Score + v6Score); 179 } 180 } 181 182 score += RSSI_SCORE.lookupScore(scanDetail.getScanResult().level, isActiveNetwork); 183 return score; 184 } 185} 186