diff options
author | Roshan Pius <rpius@google.com> | 2016-02-11 06:48:44 +0000 |
---|---|---|
committer | Android Partner Code Review <android-gerrit-partner@google.com> | 2016-02-11 06:48:45 +0000 |
commit | bfcea7de75875c900de19a8504416492ed96ae21 (patch) | |
tree | f79a09f583a46b153f90fe3f8a993aadcd92b844 /service | |
parent | d150184a5b28f862b39ad383ab87ee0ac4ca6be8 (diff) | |
parent | ac9ad3283508db15b65b1cbb89b841278973276b (diff) |
Merge "Update network priorities before PNO is triggered" into mm-wireless-dev
Diffstat (limited to 'service')
3 files changed, 138 insertions, 7 deletions
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java index 77757a8b3..cc9e5068f 100644 --- a/service/java/com/android/server/wifi/WifiConfigStore.java +++ b/service/java/com/android/server/wifi/WifiConfigStore.java @@ -1363,6 +1363,84 @@ public class WifiConfigStore extends IpConfigStore { } } + + /** + * 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| + * 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); + } else { + return Boolean.compare(isConfigBTempDisabled, isConfigATempDisabled); + } + } + }; + + /** + * Retrieves an updated list of priorities for all the saved networks before + * enabling/disabling 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 + * might end up not connecting to the networks we use most frequently. So, We want the networks + * to be re-sorted based on the relative |numAssociation| values. + * + * @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>(); + ArrayList<WifiConfiguration> wifiConfigurations = + new ArrayList<WifiConfiguration>(mConfiguredNetworks.valuesForCurrentUser()); + if (enablePno) { + Collections.sort(wifiConfigurations, sPnoListSortComparator); + // 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); + } + for (WifiConfiguration config : wifiConfigurations) { + pnoList.add(new WifiNative.PnoNetworkPriority(config.networkId, 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)); + } + } + return pnoList; + } + + String[] getWhiteListedSsids(WifiConfiguration config) { int num_ssids = 0; String nonQuoteSSID; diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index 20f5ab3c7..9246c2ea9 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -880,6 +880,29 @@ public class WifiNative { return doBooleanCommand("DRIVER COUNTRY"); } + + /** + * 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; @@ -887,6 +910,7 @@ public class WifiNative { "com.android.server.Wifi.action.TOGGLE_PNO"; long mLastPnoChangeTimeStamp = -1L; boolean mExpectedPnoState = false; + List<PnoNetworkPriority> mExpectedPnoNetworkPriorityList = null; boolean mCurrentPnoState = false;; boolean mWaitForTimer = false; final Object mPnoLock = new Object(); @@ -909,7 +933,8 @@ public class WifiNative { if (mCurrentPnoState != mExpectedPnoState) { if (DBG) Log.d(mTAG, "change PNO from " + mCurrentPnoState + " to " + mExpectedPnoState); - boolean ret = setPno(mExpectedPnoState); + boolean ret = setPno( + mExpectedPnoState, mExpectedPnoNetworkPriorityList); if (!ret) { Log.e(mTAG, "set PNO failure"); } @@ -923,7 +948,27 @@ public class WifiNative { new IntentFilter(ACTION_TOGGLE_PNO)); } - private boolean setPno(boolean enable) { + /* Enable/Disable PNO with updated network priorities. + * + * @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) { + // 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) { + // What if this fails? Should we bail out? + boolean isSuccess = setNetworkVariable(pnoNetwork.networkId, + WifiConfiguration.priorityVarName, + Integer.toString(pnoNetwork.priority)); + if (DBG && !isSuccess) { + Log.e(mTAG, "Update priority failed for :" + pnoNetwork.networkId); + } + } + } String cmd = enable ? "SET pno 1" : "SET pno 0"; boolean ret = doBooleanCommand(cmd); mLastPnoChangeTimeStamp = System.currentTimeMillis(); @@ -933,11 +978,14 @@ public class WifiNative { return ret; } - public boolean enableBackgroundScan(boolean enable) { + public boolean enableBackgroundScan( + boolean enable, + List<PnoNetworkPriority> pnoNetworkList) { synchronized(mPnoLock) { if (mWaitForTimer) { //already has a timer mExpectedPnoState = enable; + mExpectedPnoNetworkPriorityList = pnoNetworkList; if (DBG) Log.d(mTAG, "update expected PNO to " + mExpectedPnoState); } else { if (mCurrentPnoState == enable) { @@ -945,9 +993,10 @@ public class WifiNative { } long timeDifference = System.currentTimeMillis() - mLastPnoChangeTimeStamp; if (timeDifference >= MINIMUM_PNO_GAP) { - return setPno(enable); + return setPno(enable, pnoNetworkList); } else { mExpectedPnoState = enable; + mExpectedPnoNetworkPriorityList = pnoNetworkList; mWaitForTimer = true; if (DBG) Log.d(mTAG, "start PNO timer with delay:" + timeDifference); mAlarmManager.set(AlarmManager.RTC_WAKEUP, @@ -959,9 +1008,11 @@ public class WifiNative { } } - public boolean enableBackgroundScan(boolean enable) { + public boolean enableBackgroundScan( + boolean enable, + List<PnoNetworkPriority> pnoNetworkList) { if (mPnoMonitor != null) { - return mPnoMonitor.enableBackgroundScan(enable); + return mPnoMonitor.enableBackgroundScan(enable, pnoNetworkList); } else { return false; } diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 8aaa163bd..1bf89a683 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -2507,7 +2507,9 @@ public class WifiStateMachine extends StateMachine implements WifiNative.WifiPno if (enable) { mWifiConfigStore.enableAllNetworks(); } - boolean ret = mWifiNative.enableBackgroundScan(enable); + List<WifiNative.PnoNetworkPriority> pnoList = + mWifiConfigStore.retrievePnoNetworkPriorityList(enable); + boolean ret = mWifiNative.enableBackgroundScan(enable, pnoList); if (ret) { mLegacyPnoEnabled = enable; } else { |