diff options
author | Roshan Pius <rpius@google.com> | 2016-02-12 09:26:12 -0800 |
---|---|---|
committer | Roshan Pius <rpius@google.com> | 2016-02-19 12:48:37 -0800 |
commit | 5c3c06082b24f9ff0d479e82a63b52220c86598b (patch) | |
tree | e9d11198c236b773a2c15eb2e5c24b77e4601065 /service | |
parent | 5aecec3422a573e09b5792edd587153c00748da1 (diff) |
WifiConfigStore: API for fetching PNO network list
Modify the existing API for retrieving PNO network list to
differentiate the list for disconnected vs connected PNO scenarios.
The network sorting orders are different for each of these PNO
scenarios. Use different comparator objects to sort the network list for
the 2 scenarios.
Also, merging the existing ePNO network class (WifiPnoNetwork) with the
supplicant based PNO network class (PnoNetworkPriority). This allows the
Connectivity manager to use a single class for all types of PNO.
While there,
Remove dead code in WifiConfigStore (buildPnoList) which was written for
ePNO.
While there,
Add back the numAssociation counter increment because we're now using
it to sort PNO list.
BUG: 27151228
Change-Id: I6d48dab367a2106eef4f1d3f396f391c57a22339
TEST: Ran unit tests
Diffstat (limited to 'service')
3 files changed, 152 insertions, 119 deletions
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java index 834de6fd7..2a0a14a25 100644 --- a/service/java/com/android/server/wifi/WifiConfigStore.java +++ b/service/java/com/android/server/wifi/WifiConfigStore.java @@ -511,12 +511,6 @@ public class WifiConfigStore extends IpConfigStore { private long mLastSelectedTimeStamp = WifiConfiguration.NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; - /** - * Cached PNO list, it is updated when WifiConfiguration changes due to user input. - */ - ArrayList<WifiNative.WifiPnoNetwork> mCachedPnoList - = new ArrayList<WifiNative.WifiPnoNetwork>(); - /* * BSSID blacklist, i.e. list of BSSID we want to avoid */ @@ -1043,7 +1037,6 @@ public class WifiConfigStore extends IpConfigStore { if (updatePriorities) { config.priority = ++mLastPriority; setNetworkPriorityNative(config.networkId, config.priority); - buildPnoList(); } if (config.isPasspoint()) { @@ -1382,78 +1375,85 @@ public class WifiConfigStore extends IpConfigStore { } /** - * Get the Wifi PNO list - * - * @return list of WifiNative.WifiPnoNetwork + * General PnoNetwork list sorting algorithm: + * 1, Place the fully enabled networks first. Among the fully enabled networks, + * sort them in the oder determined by the return of |compareConfigurations| method + * implementation. + * 2. Next place all the temporarily disabled networks. Among the temporarily disabled + * networks, sort them in the order determined by the return of |compareConfigurations| method + * implementation. + * 3. Place the permanently disabled networks last. The order among permanently disabled + * networks doesn't matter. */ - private void buildPnoList() { - mCachedPnoList = new ArrayList<WifiNative.WifiPnoNetwork>(); - - ArrayList<WifiConfiguration> sortedWifiConfigurations - = new ArrayList<WifiConfiguration>(getConfiguredNetworks()); - Log.e(TAG, "buildPnoList sortedWifiConfigurations size " + sortedWifiConfigurations.size()); - if (sortedWifiConfigurations.size() != 0) { - // Sort by descending priority - Collections.sort(sortedWifiConfigurations, new Comparator<WifiConfiguration>() { - public int compare(WifiConfiguration a, WifiConfiguration b) { - return a.priority - b.priority; - } - }); + private static class PnoListComparator implements Comparator<WifiConfiguration> { + + public final int ENABLED_NETWORK_SCORE = 3; + public final int TEMPORARY_DISABLED_NETWORK_SCORE = 2; + public final int PERMANENTLY_DISABLED_NETWORK_SCORE = 1; + + @Override + public int compare(WifiConfiguration a, WifiConfiguration b) { + int configAScore = getPnoNetworkSortScore(a); + int configBScore = getPnoNetworkSortScore(b); + if (configAScore == configBScore) { + return compareConfigurations(a, b); + } else { + return Integer.compare(configBScore, configAScore); + } } - for (WifiConfiguration config : sortedWifiConfigurations) { - // Initialize the RSSI threshold with sane value: - // Use the 2.4GHz threshold since most WifiConfigurations are dual bands - // There is very little penalty with triggering too soon, i.e. if PNO finds a network - // that has an RSSI too low for us to attempt joining it. - int threshold = thresholdMinimumRssi24.get(); - Log.e(TAG, "found sortedWifiConfigurations : " + config.configKey()); - WifiNative.WifiPnoNetwork network = new WifiNative.WifiPnoNetwork(config, threshold); - mCachedPnoList.add(network); + // This needs to be implemented by the connected/disconnected PNO list comparator. + public int compareConfigurations(WifiConfiguration a, WifiConfiguration b) { + return 0; } - } + /** + * Returns an integer representing a score for each configuration. The scores are assigned + * based on the status of the configuration. The scores are assigned according to the order: + * Fully enabled network > Temporarily disabled network > Permanently disabled network. + */ + private int getPnoNetworkSortScore(WifiConfiguration config) { + if (config.getNetworkSelectionStatus().isNetworkEnabled()) { + return ENABLED_NETWORK_SCORE; + } else if (config.getNetworkSelectionStatus().isNetworkTemporaryDisabled()) { + return TEMPORARY_DISABLED_NETWORK_SCORE; + } else { + return PERMANENTLY_DISABLED_NETWORK_SCORE; + } + } + } /** - * PnoNetwork list sorting algorithm: - * 1, Place the fully enabled networks first. Among the fully enabled networks, - * sort them in descending order of their |numAssociation| values. If networks have - * the same |numAssociation|, then sort them in descending order of their |priority| + * Disconnected PnoNetwork list sorting algorithm: + * Place the configurations in descending order of their |numAssociation| values. If networks + * have the same |numAssociation|, then sort them in descending order of their |priority| * values. - * 2. Next place all the temporarily disabled networks. Among the temporarily disabled - * networks, sort them in the same order as the fully enabled networks. - * 3. Place the permanently disabled networks last. The order among permanently disabled - * networks doesn't matter. */ - private static final Comparator<WifiConfiguration> sPnoListSortComparator = - new Comparator<WifiConfiguration>() { - public int compare(WifiConfiguration a, WifiConfiguration b) { - boolean isConfigAEnabled = a.getNetworkSelectionStatus().isNetworkEnabled(); - boolean isConfigBEnabled = b.getNetworkSelectionStatus().isNetworkEnabled(); - boolean isConfigATempDisabled = - a.getNetworkSelectionStatus().isNetworkTemporaryDisabled(); - boolean isConfigBTempDisabled = - b.getNetworkSelectionStatus().isNetworkTemporaryDisabled(); - if ((isConfigAEnabled && isConfigBEnabled) - || (isConfigATempDisabled && isConfigBTempDisabled)) { - // If 2 networks have the same saved |numAssociation| value, sort them - // according to their priority. - if (a.numAssociation != b.numAssociation) { - return Long.compare(b.numAssociation, a.numAssociation); - } else { - return Integer.compare(b.priority, a.priority); - } - } else if (isConfigAEnabled != isConfigBEnabled) { - return Boolean.compare(isConfigBEnabled, isConfigAEnabled); + private static final PnoListComparator sDisconnectedPnoListComparator = + new PnoListComparator() { + @Override + public int compareConfigurations(WifiConfiguration a, WifiConfiguration b) { + if (a.numAssociation != b.numAssociation) { + return Long.compare(b.numAssociation, a.numAssociation); } else { - return Boolean.compare(isConfigBTempDisabled, isConfigATempDisabled); + return Integer.compare(b.priority, a.priority); } } }; /** * Retrieves an updated list of priorities for all the saved networks before - * enabling/disabling PNO. + * enabling disconnected PNO (wpa_supplicant based PNO). + * + * @return list of networks with updated priorities. + */ + public ArrayList<WifiNative.WifiPnoNetwork> retrieveDisconnectedWifiPnoNetworkList() { + return retrieveWifiPnoNetworkList(true, sDisconnectedPnoListComparator); + } + + /** + * Retrieves an updated list of priorities for all the saved networks before + * enabling/disabling disconnected PNO (wpa_supplicant based PNO). * * wpa_supplicant uses the priority of networks to build the list of SSID's to monitor * during PNO. If there are a lot of saved networks, this list will be truncated and we @@ -1463,34 +1463,83 @@ public class WifiConfigStore extends IpConfigStore { * @param enablePno boolean indicating whether PNO is being enabled or disabled. * @return list of networks with updated priorities. */ - ArrayList<WifiNative.PnoNetworkPriority> retrievePnoNetworkPriorityList(boolean enablePno) { - ArrayList<WifiNative.PnoNetworkPriority> pnoList = - new ArrayList<WifiNative.PnoNetworkPriority>(); + public ArrayList<WifiNative.WifiPnoNetwork> retrieveDisconnectedWifiPnoNetworkList( + boolean enablePno) { + return retrieveWifiPnoNetworkList(enablePno, sDisconnectedPnoListComparator); + } + + /** + * Connected PnoNetwork list sorting algorithm: + * Place the configurations with |lastSeenInQualifiedNetworkSelection| set first. If networks + * have the same value, then sort them in descending order of their |numAssociation| + * values. + */ + private static final PnoListComparator sConnectedPnoListComparator = + new PnoListComparator() { + @Override + public int compareConfigurations(WifiConfiguration a, WifiConfiguration b) { + boolean isConfigALastSeen = + a.getNetworkSelectionStatus().getSeenInLastQualifiedNetworkSelection(); + boolean isConfigBLastSeen = + b.getNetworkSelectionStatus().getSeenInLastQualifiedNetworkSelection(); + if (isConfigALastSeen != isConfigBLastSeen) { + return Boolean.compare(isConfigBLastSeen, isConfigALastSeen); + } else { + return Long.compare(b.numAssociation, a.numAssociation); + } + } + }; + + /** + * Retrieves an updated list of priorities for all the saved networks before + * enabling connected PNO (HAL based ePno). + * + * @return list of networks with updated priorities. + */ + public ArrayList<WifiNative.WifiPnoNetwork> retrieveConnectedWifiPnoNetworkList() { + return retrieveWifiPnoNetworkList(true, sConnectedPnoListComparator); + } + + /** + * Retrieves an updated list of priorities for all the saved networks before + * enabling/disabling PNO. + * + * @param enablePno boolean indicating whether PNO is being enabled or disabled. + * @return list of networks with updated priorities. + */ + private ArrayList<WifiNative.WifiPnoNetwork> retrieveWifiPnoNetworkList( + boolean enablePno, PnoListComparator pnoListComparator) { + ArrayList<WifiNative.WifiPnoNetwork> pnoList = + new ArrayList<WifiNative.WifiPnoNetwork>(); ArrayList<WifiConfiguration> wifiConfigurations = new ArrayList<WifiConfiguration>(mConfiguredNetworks.valuesForCurrentUser()); if (enablePno) { - Collections.sort(wifiConfigurations, sPnoListSortComparator); + Collections.sort(wifiConfigurations, pnoListComparator); // Let's use the network list size as the highest priority and then go down from there. // So, the most frequently connected network has the highest priority now. int priority = wifiConfigurations.size(); if (DBG) { Log.d(TAG, "Retrieve network priorities before PNO. Max priority: " + priority); } + // Initialize the RSSI threshold with sane value: + // Use the 2.4GHz threshold since most WifiConfigurations are dual bands + // There is very little penalty with triggering too soon, i.e. if PNO finds a network + // that has an RSSI too low for us to attempt joining it. + int threshold = thresholdMinimumRssi24.get(); for (WifiConfiguration config : wifiConfigurations) { - pnoList.add(new WifiNative.PnoNetworkPriority(config.networkId, priority)); + pnoList.add(new WifiNative.WifiPnoNetwork(config, threshold, priority)); priority--; } } else { // Revert the priorities back to the saved config values after PNO. if (DBG) Log.d(TAG, "Retrieve network priorities after PNO."); for (WifiConfiguration config : wifiConfigurations) { - pnoList.add(new WifiNative.PnoNetworkPriority(config.networkId, config.priority)); + pnoList.add(new WifiNative.WifiPnoNetwork(config, 0, config.priority)); } } return pnoList; } - String[] getWhiteListedSsids(WifiConfiguration config) { int num_ssids = 0; String nonQuoteSSID; @@ -2272,8 +2321,6 @@ public class WifiConfigStore extends IpConfigStore { readIpAndProxyConfigurations(); readAutoJoinConfig(); - buildPnoList(); - sendConfiguredNetworksChangedBroadcast(); if (showNetworks) { diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index e281b7b5d..cc1eefdc2 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -880,28 +880,6 @@ public class WifiNative { } - /** - * Object holding the network ID and the corresponding priority to be set before enabling/ - * disabling PNO. - */ - public static class PnoNetworkPriority { - public int networkId; - public int priority; - - PnoNetworkPriority(int networkId, int priority) { - this.networkId = networkId; - this.priority = priority; - } - - @Override - public String toString() { - StringBuilder sbuf = new StringBuilder(); - sbuf.append(" Network ID=").append(this.networkId); - sbuf.append(" Priority=").append(this.priority); - return sbuf.toString(); - } - } - //PNO Monitor private class PnoMonitor { private static final int MINIMUM_PNO_GAP = 5 * 1000; @@ -909,7 +887,7 @@ public class WifiNative { "com.android.server.Wifi.action.TOGGLE_PNO"; long mLastPnoChangeTimeStamp = -1L; boolean mExpectedPnoState = false; - List<PnoNetworkPriority> mExpectedPnoNetworkPriorityList = null; + List<WifiPnoNetwork> mExpectedWifiPnoNetworkList = null; boolean mCurrentPnoState = false;; boolean mWaitForTimer = false; final Object mPnoLock = new Object(); @@ -933,7 +911,7 @@ public class WifiNative { if (DBG) Log.d(mTAG, "change PNO from " + mCurrentPnoState + " to " + mExpectedPnoState); boolean ret = setPno( - mExpectedPnoState, mExpectedPnoNetworkPriorityList); + mExpectedPnoState, mExpectedWifiPnoNetworkList); if (!ret) { Log.e(mTAG, "set PNO failure"); } @@ -952,18 +930,18 @@ public class WifiNative { * @param enable boolean indicating whether PNO is being enabled or disabled. * @param pnoNetworkList list of networks with priorities to be set before PNO setting. */ - private boolean setPno(boolean enable, List<PnoNetworkPriority> pnoNetworkList) { + private boolean setPno(boolean enable, List<WifiPnoNetwork> pnoNetworkList) { // TODO: Couple of cases yet to be handled: // 1. What if the network priority update fails, should we bail out of PNO setting? // 2. If PNO setting fails below, should we go back and revert this priority change? if (pnoNetworkList != null) { if (DBG) Log.i(mTAG, "Update priorities for PNO. Enable: " + enable); - for (PnoNetworkPriority pnoNetwork : pnoNetworkList) { + for (WifiPnoNetwork pnoNetwork : pnoNetworkList) { // What if this fails? Should we bail out? boolean isSuccess = setNetworkVariable(pnoNetwork.networkId, WifiConfiguration.priorityVarName, Integer.toString(pnoNetwork.priority)); - if (DBG && !isSuccess) { + if (!isSuccess) { Log.e(mTAG, "Update priority failed for :" + pnoNetwork.networkId); } } @@ -979,12 +957,12 @@ public class WifiNative { public boolean enableBackgroundScan( boolean enable, - List<PnoNetworkPriority> pnoNetworkList) { + List<WifiPnoNetwork> pnoNetworkList) { synchronized(mPnoLock) { if (mWaitForTimer) { //already has a timer mExpectedPnoState = enable; - mExpectedPnoNetworkPriorityList = pnoNetworkList; + mExpectedWifiPnoNetworkList = pnoNetworkList; if (DBG) Log.d(mTAG, "update expected PNO to " + mExpectedPnoState); } else { if (mCurrentPnoState == enable) { @@ -995,7 +973,7 @@ public class WifiNative { return setPno(enable, pnoNetworkList); } else { mExpectedPnoState = enable; - mExpectedPnoNetworkPriorityList = pnoNetworkList; + mExpectedWifiPnoNetworkList = pnoNetworkList; mWaitForTimer = true; if (DBG) Log.d(mTAG, "start PNO timer with delay:" + timeDifference); mAlarmManager.set(AlarmManager.RTC_WAKEUP, @@ -1009,7 +987,7 @@ public class WifiNative { public boolean enableBackgroundScan( boolean enable, - List<PnoNetworkPriority> pnoNetworkList) { + List<WifiPnoNetwork> pnoNetworkList) { if (mPnoMonitor != null) { return mPnoMonitor.enableBackgroundScan(enable, pnoNetworkList); } else { @@ -2630,7 +2608,7 @@ public class WifiNative { } //--------------------------------------------------------------------------------- - /* Configure ePNO */ + /* Configure ePNO/PNO */ /* pno flags, keep these values in sync with gscan.h */ private static int WIFI_PNO_AUTH_CODE_OPEN = 1; // open @@ -2646,34 +2624,39 @@ public class WifiNative { // Whether strict matching is required (i.e. firmware shall not match on the entire SSID) private static int WIFI_PNO_FLAG_STRICT_MATCH = 8; + /** + * Object holding the network ID and the corresponding priority to be set before enabling/ + * disabling PNO. + */ public static class WifiPnoNetwork { - String SSID; - int rssi_threshold; // TODO remove - int flags; - int auth; - String configKey; // kept for reference + public String SSID; + public int rssi_threshold; // TODO remove + public int flags; + public int auth; + public String configKey; // kept for reference + public int networkId; + public int priority; - WifiPnoNetwork(WifiConfiguration config, int threshold) { + WifiPnoNetwork(WifiConfiguration config, int threshold, int newPriority) { if (config.SSID == null) { - this.SSID = ""; - this.flags = WIFI_PNO_FLAG_DIRECTED_SCAN; + SSID = ""; + flags = WIFI_PNO_FLAG_DIRECTED_SCAN; } else { - this.SSID = config.SSID; + SSID = config.SSID; } - this.rssi_threshold = threshold; + rssi_threshold = threshold; if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { auth |= WIFI_PNO_AUTH_CODE_PSK; } else if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_EAP) || config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.IEEE8021X)) { auth |= WIFI_PNO_AUTH_CODE_EAPOL; - } else if (config.wepKeys[0] != null) { - auth |= WIFI_PNO_AUTH_CODE_OPEN; } else { auth |= WIFI_PNO_AUTH_CODE_OPEN; } - flags |= WIFI_PNO_FLAG_A_BAND | WIFI_PNO_FLAG_G_BAND; configKey = config.configKey(); + networkId = config.networkId; + priority = newPriority; } @Override @@ -2683,6 +2666,8 @@ public class WifiNative { sbuf.append(" flags=").append(this.flags); sbuf.append(" rssi=").append(this.rssi_threshold); sbuf.append(" auth=").append(this.auth); + sbuf.append(" Network ID=").append(this.networkId); + sbuf.append(" Priority=").append(this.priority); return sbuf.toString(); } } diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 2866b3423..df47cab3e 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -2517,8 +2517,8 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno if (enable) { mWifiConfigStore.enableAllNetworks(); } - List<WifiNative.PnoNetworkPriority> pnoList = - mWifiConfigStore.retrievePnoNetworkPriorityList(enable); + List<WifiNative.WifiPnoNetwork> pnoList = + mWifiConfigStore.retrieveDisconnectedWifiPnoNetworkList(enable); boolean ret = mWifiNative.enableBackgroundScan(enable, pnoList); if (ret) { mLegacyPnoEnabled = enable; @@ -6600,6 +6600,7 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno //records how long this network is connected in future config.lastConnected = System.currentTimeMillis(); config.getNetworkSelectionStatus().clearDisableReasonCounter(); + config.numAssociation++; } mBadLinkspeedcount = 0; } |