diff options
author | Michael Plass <mplass@google.com> | 2017-07-15 00:31:33 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-07-15 00:31:33 +0000 |
commit | 0eb389dd4a9bf3d8a5c72ffb2aa893aa91f981a6 (patch) | |
tree | 0a28b1df6d52746e947d45d25e667988a5b559d6 | |
parent | 56d74cae34989196fbdcba21cbb9fe55298293a0 (diff) | |
parent | 3359479d092caebc1e5c27cfbb7d378d6b6007ee (diff) |
Merge changes Ia5c42c7c,Ie8362f6d into oc-dr1-dev am: 1ab69dfa7c
am: 3359479d09
Change-Id: I77d4be85fda2c07f85cfec09ec7b8df8c58dd212
4 files changed, 438 insertions, 221 deletions
diff --git a/service/java/com/android/server/wifi/AggressiveConnectedScore.java b/service/java/com/android/server/wifi/AggressiveConnectedScore.java new file mode 100644 index 000000000..a0de7731e --- /dev/null +++ b/service/java/com/android/server/wifi/AggressiveConnectedScore.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wifi; + +import android.content.Context; +import android.net.wifi.WifiInfo; + +import com.android.internal.R; + +/** + * Experimental scorer, used when aggressive handover preference is set. + */ +public class AggressiveConnectedScore extends ConnectedScore { + + // Device configs. The values are examples. + private final int mThresholdQualifiedRssi5; // -70 + private final int mThresholdQualifiedRssi24; // -73 + + private int mFrequencyMHz = 5000; + private int mRssi = 0; + + public AggressiveConnectedScore(Context context, Clock clock) { + super(clock); + mThresholdQualifiedRssi5 = context.getResources().getInteger( + R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz); + mThresholdQualifiedRssi24 = context.getResources().getInteger( + R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz); + } + + @Override + public void updateUsingRssi(int rssi, long millis, double standardDeviation) { + mRssi = rssi; + } + + @Override + public void updateUsingWifiInfo(WifiInfo wifiInfo, long millis) { + mFrequencyMHz = wifiInfo.getFrequency(); + mRssi = wifiInfo.getRssi(); + } + + @Override + public void reset() { + mFrequencyMHz = 5000; + } + + @Override + public int generateScore() { + int badRssi = mFrequencyMHz >= 5000 ? mThresholdQualifiedRssi5 : mThresholdQualifiedRssi24; + int score = (mRssi - badRssi) + WIFI_TRANSITION_SCORE; + return score; + } +} diff --git a/service/java/com/android/server/wifi/ConnectedScore.java b/service/java/com/android/server/wifi/ConnectedScore.java new file mode 100644 index 000000000..5c7ffa8e4 --- /dev/null +++ b/service/java/com/android/server/wifi/ConnectedScore.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wifi; + +import android.net.NetworkAgent; +import android.net.wifi.WifiInfo; + +/** + * Base class for connection scoring + */ +public abstract class ConnectedScore { + + /** Maximum NetworkAgent score that should be generated by wifi */ + public static final int WIFI_MAX_SCORE = NetworkAgent.WIFI_BASE_SCORE; + + /** Score at which wifi is considered poor enough to give up ant try something else */ + public static final int WIFI_TRANSITION_SCORE = NetworkAgent.WIFI_BASE_SCORE - 10; + + public static final int WIFI_MIN_SCORE = 0; + + final Clock mClock; + + /** This is a typical STD for the connected RSSI for a phone sitting still */ + public double mDefaultRssiStandardDeviation = 2.0; + + /** + * + * @param clock is the time source for getMillis() + */ + public ConnectedScore(Clock clock) { + mClock = clock; + } + + /** + * Returns the current time in milliseconds + * + * This time is to be passed into the update methods. + * The scoring methods generally don't need a particular epoch, depending + * only on deltas. So a different time source may be used, as long as it is consistent. + * + * Note that when there are long intervals between updates, it is unlikely to matter much + * how large the interval is, so a time source that does not update while the processor is + * asleep could be just fine. + * + * @return millisecond-resolution time. + */ + public long getMillis() { + return mClock.getWallClockMillis(); + } + + /** + * Updates scoring state using RSSI alone + * + * @param rssi signal strength (dB). + * @param millis millisecond-resolution time. + */ + public void updateUsingRssi(int rssi, long millis) { + updateUsingRssi(rssi, millis, mDefaultRssiStandardDeviation); + } + + /** + * Updates scoring state using RSSI and noise estimate + * + * This is useful if an RSSI comes from another source (e.g. scan results) and the + * expected noise varies by source. + * + * @param rssi signal strength (dB). + * @param millis millisecond-resolution time. + * @param standardDeviation of the RSSI. + */ + public abstract void updateUsingRssi(int rssi, long millis, double standardDeviation); + + /** + * Updates the score using relevant parts of WifiInfo + * + * @param wifiInfo object holding relevant values. + * @param millis millisecond-resolution time. + */ + public void updateUsingWifiInfo(WifiInfo wifiInfo, long millis) { + updateUsingRssi(wifiInfo.getRssi(), millis); + } + + /** + * Generates a score based on the current state + * + * @return network score - on NetworkAgent scale. + */ + public abstract int generateScore(); + + /** + * Clears out state associated with the connection + */ + public abstract void reset(); +} diff --git a/service/java/com/android/server/wifi/LegacyConnectedScore.java b/service/java/com/android/server/wifi/LegacyConnectedScore.java new file mode 100644 index 000000000..facab0a54 --- /dev/null +++ b/service/java/com/android/server/wifi/LegacyConnectedScore.java @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wifi; + +import android.content.Context; +import android.net.NetworkAgent; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiInfo; + +import com.android.internal.R; + +/** + * Class used to calculate scores for connected wifi networks and report it to the associated + * network agent. + */ +public class LegacyConnectedScore extends ConnectedScore { + + private static final int STARTING_SCORE = 56; + + private static final int SCAN_CACHE_VISIBILITY_MS = 12000; + private static final int HOME_VISIBLE_NETWORK_MAX_COUNT = 6; + private static final int SCAN_CACHE_COUNT_PENALTY = 2; + private static final int MAX_SUCCESS_RATE_OF_STUCK_LINK = 3; // proportional to packets per sec + private static final int MAX_STUCK_LINK_COUNT = 5; + private static final int MAX_BAD_RSSI_COUNT = 7; + private static final int BAD_RSSI_COUNT_PENALTY = 2; + private static final int MAX_LOW_RSSI_COUNT = 1; + private static final double MIN_TX_FAILURE_RATE_FOR_WORKING_LINK = 0.3; + private static final int MIN_SUSTAINED_LINK_STUCK_COUNT = 1; + private static final int LINK_STUCK_PENALTY = 2; + private static final int BAD_LINKSPEED_PENALTY = 4; + private static final int GOOD_LINKSPEED_BONUS = 4; + + // Device configs. The values are examples. + private final int mThresholdMinimumRssi5; // -82 + private final int mThresholdQualifiedRssi5; // -70 + private final int mThresholdSaturatedRssi5; // -57 + private final int mThresholdMinimumRssi24; // -85 + private final int mThresholdQualifiedRssi24; // -73 + private final int mThresholdSaturatedRssi24; // -60 + private final int mBadLinkSpeed24; // 6 Mbps + private final int mBadLinkSpeed5; // 12 Mbps + private final int mGoodLinkSpeed24; // 24 Mbps + private final int mGoodLinkSpeed5; // 36 Mbps + + private final WifiConfigManager mWifiConfigManager; + private boolean mVerboseLoggingEnabled = false; + + private boolean mMultiBandScanResults; + private boolean mIsHomeNetwork; + private int mScore = 0; + + LegacyConnectedScore(Context context, WifiConfigManager wifiConfigManager, Clock clock) { + super(clock); + // Fetch all the device configs. + mThresholdMinimumRssi5 = context.getResources().getInteger( + R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz); + mThresholdQualifiedRssi5 = context.getResources().getInteger( + R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz); + mThresholdSaturatedRssi5 = context.getResources().getInteger( + R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz); + mThresholdMinimumRssi24 = context.getResources().getInteger( + R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz); + mThresholdQualifiedRssi24 = context.getResources().getInteger( + R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz); + mThresholdSaturatedRssi24 = context.getResources().getInteger( + R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz); + mBadLinkSpeed24 = context.getResources().getInteger( + R.integer.config_wifi_framework_wifi_score_bad_link_speed_24); + mBadLinkSpeed5 = context.getResources().getInteger( + R.integer.config_wifi_framework_wifi_score_bad_link_speed_5); + mGoodLinkSpeed24 = context.getResources().getInteger( + R.integer.config_wifi_framework_wifi_score_good_link_speed_24); + mGoodLinkSpeed5 = context.getResources().getInteger( + R.integer.config_wifi_framework_wifi_score_good_link_speed_5); + + mWifiConfigManager = wifiConfigManager; + } + + @Override + public void updateUsingWifiInfo(WifiInfo wifiInfo, long millis) { + mMultiBandScanResults = multiBandScanResults(wifiInfo); + mIsHomeNetwork = isHomeNetwork(wifiInfo); + + int rssiThreshBad = mThresholdMinimumRssi24; + int rssiThreshLow = mThresholdQualifiedRssi24; + + if (wifiInfo.is5GHz() && !mMultiBandScanResults) { + rssiThreshBad = mThresholdMinimumRssi5; + rssiThreshLow = mThresholdQualifiedRssi5; + } + + int rssi = wifiInfo.getRssi(); + if (mIsHomeNetwork) { + rssi += WifiConfiguration.HOME_NETWORK_RSSI_BOOST; + } + + if ((wifiInfo.txBadRate >= 1) + && (wifiInfo.txSuccessRate < MAX_SUCCESS_RATE_OF_STUCK_LINK) + && rssi < rssiThreshLow) { + // Link is stuck + if (wifiInfo.linkStuckCount < MAX_STUCK_LINK_COUNT) { + wifiInfo.linkStuckCount += 1; + } + } else if (wifiInfo.txBadRate < MIN_TX_FAILURE_RATE_FOR_WORKING_LINK) { + if (wifiInfo.linkStuckCount > 0) { + wifiInfo.linkStuckCount -= 1; + } + } + + if (rssi < rssiThreshBad) { + if (wifiInfo.badRssiCount < MAX_BAD_RSSI_COUNT) { + wifiInfo.badRssiCount += 1; + } + } else if (rssi < rssiThreshLow) { + wifiInfo.lowRssiCount = MAX_LOW_RSSI_COUNT; // Dont increment the lowRssi count above 1 + if (wifiInfo.badRssiCount > 0) { + // Decrement bad Rssi count + wifiInfo.badRssiCount -= 1; + } + } else { + wifiInfo.badRssiCount = 0; + wifiInfo.lowRssiCount = 0; + } + + // Ugh, we need to finish the score calculation while we have wifiInfo + mScore = calculateScore(wifiInfo); + + } + + @Override + public void updateUsingRssi(int rssi, long millis, double standardDeviation) { + // This scorer needs more than just the RSSI. Just ignore. + } + + @Override + public int generateScore() { + return mScore; + } + + @Override + public void reset() { + mScore = 0; + } + + /** + * Calculates a score based on the current state and wifiInfo + */ + private int calculateScore(WifiInfo wifiInfo) { + int score = STARTING_SCORE; + + int rssiThreshSaturated = mThresholdSaturatedRssi24; + int linkspeedThreshBad = mBadLinkSpeed24; + int linkspeedThreshGood = mGoodLinkSpeed24; + + if (wifiInfo.is5GHz()) { + if (!mMultiBandScanResults) { + rssiThreshSaturated = mThresholdSaturatedRssi5; + } + linkspeedThreshBad = mBadLinkSpeed5; + linkspeedThreshGood = mGoodLinkSpeed5; + } + + int rssi = wifiInfo.getRssi(); + if (mIsHomeNetwork) { + rssi += WifiConfiguration.HOME_NETWORK_RSSI_BOOST; + } + + int linkSpeed = wifiInfo.getLinkSpeed(); + + if (wifiInfo.linkStuckCount > MIN_SUSTAINED_LINK_STUCK_COUNT) { + // Once link gets stuck for more than 3 seconds, start reducing the score + score = score - LINK_STUCK_PENALTY * (wifiInfo.linkStuckCount - 1); + } + + if (linkSpeed < linkspeedThreshBad) { + score -= BAD_LINKSPEED_PENALTY; + } else if ((linkSpeed >= linkspeedThreshGood) && (wifiInfo.txSuccessRate > 5)) { + score += GOOD_LINKSPEED_BONUS; // So as bad rssi alone doesn't kill us + } + + score -= wifiInfo.badRssiCount * BAD_RSSI_COUNT_PENALTY + wifiInfo.lowRssiCount; + + if (rssi >= rssiThreshSaturated) score += 5; + + if (score > NetworkAgent.WIFI_BASE_SCORE) score = NetworkAgent.WIFI_BASE_SCORE; + if (score < 0) score = 0; + + return score; + } + + /** + * Determines if we can see both 2.4GHz and 5GHz for current config + */ + private boolean multiBandScanResults(WifiInfo wifiInfo) { + WifiConfiguration currentConfiguration = + mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId()); + if (currentConfiguration == null) return false; + ScanDetailCache scanDetailCache = + mWifiConfigManager.getScanDetailCacheForNetwork(wifiInfo.getNetworkId()); + if (scanDetailCache == null) return false; + // Nasty that we change state here... + currentConfiguration.setVisibility(scanDetailCache.getVisibility(SCAN_CACHE_VISIBILITY_MS)); + if (currentConfiguration.visibility == null) return false; + if (currentConfiguration.visibility.rssi24 == WifiConfiguration.INVALID_RSSI) return false; + if (currentConfiguration.visibility.rssi5 == WifiConfiguration.INVALID_RSSI) return false; + // N.B. this does not do exactly what is claimed! + if (currentConfiguration.visibility.rssi24 + >= currentConfiguration.visibility.rssi5 - SCAN_CACHE_COUNT_PENALTY) { + return true; + } + return false; + } + + /** + * Decides whether the current network is a "home" network + */ + private boolean isHomeNetwork(WifiInfo wifiInfo) { + WifiConfiguration currentConfiguration = + mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId()); + if (currentConfiguration == null) return false; + // This seems like it will only return true for really old routers! + if (currentConfiguration.allowedKeyManagement.cardinality() != 1) return false; + if (!currentConfiguration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { + return false; + } + ScanDetailCache scanDetailCache = + mWifiConfigManager.getScanDetailCacheForNetwork(wifiInfo.getNetworkId()); + if (scanDetailCache == null) return false; + if (scanDetailCache.size() <= HOME_VISIBLE_NETWORK_MAX_COUNT) { + return true; + } + return false; + } +} diff --git a/service/java/com/android/server/wifi/WifiScoreReport.java b/service/java/com/android/server/wifi/WifiScoreReport.java index 5aadc1e9b..98747a34e 100644 --- a/service/java/com/android/server/wifi/WifiScoreReport.java +++ b/service/java/com/android/server/wifi/WifiScoreReport.java @@ -18,12 +18,9 @@ package com.android.server.wifi; import android.content.Context; import android.net.NetworkAgent; -import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.util.Log; -import com.android.internal.R; - import java.io.FileDescriptor; import java.io.PrintWriter; import java.text.SimpleDateFormat; @@ -38,75 +35,24 @@ import java.util.Locale; public class WifiScoreReport { private static final String TAG = "WifiScoreReport"; - private static final int STARTING_SCORE = 56; - - private static final int SCAN_CACHE_VISIBILITY_MS = 12000; - private static final int HOME_VISIBLE_NETWORK_MAX_COUNT = 6; - private static final int SCAN_CACHE_COUNT_PENALTY = 2; - private static final int AGGRESSIVE_HANDOVER_PENALTY = 6; - private static final int MAX_SUCCESS_RATE_OF_STUCK_LINK = 3; // proportional to packets per sec - private static final int MAX_STUCK_LINK_COUNT = 5; - private static final int MAX_BAD_RSSI_COUNT = 7; - private static final int BAD_RSSI_COUNT_PENALTY = 2; - private static final int MAX_LOW_RSSI_COUNT = 1; - private static final double MIN_TX_FAILURE_RATE_FOR_WORKING_LINK = 0.3; - private static final int MIN_SUSTAINED_LINK_STUCK_COUNT = 1; - private static final int LINK_STUCK_PENALTY = 2; - private static final int BAD_LINKSPEED_PENALTY = 4; - private static final int GOOD_LINKSPEED_BONUS = 4; private static final int DUMPSYS_ENTRY_COUNT_LIMIT = 14400; // 12 hours on 3 second poll - // Device configs. The values are examples. - private final int mThresholdMinimumRssi5; // -82 - private final int mThresholdQualifiedRssi5; // -70 - private final int mThresholdSaturatedRssi5; // -57 - private final int mThresholdMinimumRssi24; // -85 - private final int mThresholdQualifiedRssi24; // -73 - private final int mThresholdSaturatedRssi24; // -60 - private final int mBadLinkSpeed24; // 6 Mbps - private final int mBadLinkSpeed5; // 12 Mbps - private final int mGoodLinkSpeed24; // 24 Mbps - private final int mGoodLinkSpeed5; // 36 Mbps - - private final WifiConfigManager mWifiConfigManager; private boolean mVerboseLoggingEnabled = false; // Cache of the last score report. private String mReport; private boolean mReportValid = false; - // State set by updateScoringState - private boolean mMultiBandScanResults; - private boolean mIsHomeNetwork; - private final Clock mClock; private int mSessionNumber = 0; - WifiScoreReport(Context context, WifiConfigManager wifiConfigManager, Clock clock) { - // Fetch all the device configs. - mThresholdMinimumRssi5 = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz); - mThresholdQualifiedRssi5 = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz); - mThresholdSaturatedRssi5 = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz); - mThresholdMinimumRssi24 = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz); - mThresholdQualifiedRssi24 = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz); - mThresholdSaturatedRssi24 = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz); - mBadLinkSpeed24 = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_bad_link_speed_24); - mBadLinkSpeed5 = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_bad_link_speed_5); - mGoodLinkSpeed24 = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_good_link_speed_24); - mGoodLinkSpeed5 = context.getResources().getInteger( - R.integer.config_wifi_framework_wifi_score_good_link_speed_5); + ConnectedScore mConnectedScore; + ConnectedScore mAggressiveConnectedScore; - mWifiConfigManager = wifiConfigManager; + WifiScoreReport(Context context, WifiConfigManager wifiConfigManager, Clock clock) { mClock = clock; + mConnectedScore = new LegacyConnectedScore(context, wifiConfigManager, clock); + mAggressiveConnectedScore = new AggressiveConnectedScore(context, clock); } /** @@ -125,6 +71,8 @@ public class WifiScoreReport { mReport = ""; mReportValid = false; mSessionNumber++; + mConnectedScore.reset(); + mAggressiveConnectedScore.reset(); if (mVerboseLoggingEnabled) Log.d(TAG, "reset"); } @@ -162,13 +110,17 @@ public class WifiScoreReport { int aggressiveHandover, WifiMetrics wifiMetrics) { int score; + long millis = mConnectedScore.getMillis(); + logLinkMetrics(wifiInfo); + + mConnectedScore.updateUsingWifiInfo(wifiInfo, millis); + mAggressiveConnectedScore.updateUsingWifiInfo(wifiInfo, millis); + if (aggressiveHandover == 0) { - // Use the old method - updateScoringState(wifiInfo, aggressiveHandover); - score = calculateScore(wifiInfo, aggressiveHandover); + score = mConnectedScore.generateScore(); } else { - score = calculateAlternativeScore(wifiInfo); + score = mAggressiveConnectedScore.generateScore(); } //sanitize boundaries @@ -196,164 +148,6 @@ public class WifiScoreReport { } /** - * Updates the state. - */ - private void updateScoringState(WifiInfo wifiInfo, int aggressiveHandover) { - mMultiBandScanResults = multiBandScanResults(wifiInfo); - mIsHomeNetwork = isHomeNetwork(wifiInfo); - - int rssiThreshBad = mThresholdMinimumRssi24; - int rssiThreshLow = mThresholdQualifiedRssi24; - - if (wifiInfo.is5GHz() && !mMultiBandScanResults) { - rssiThreshBad = mThresholdMinimumRssi5; - rssiThreshLow = mThresholdQualifiedRssi5; - } - - int rssi = wifiInfo.getRssi(); - if (aggressiveHandover != 0) { - rssi -= AGGRESSIVE_HANDOVER_PENALTY * aggressiveHandover; - } - if (mIsHomeNetwork) { - rssi += WifiConfiguration.HOME_NETWORK_RSSI_BOOST; - } - - if ((wifiInfo.txBadRate >= 1) - && (wifiInfo.txSuccessRate < MAX_SUCCESS_RATE_OF_STUCK_LINK) - && rssi < rssiThreshLow) { - // Link is stuck - if (wifiInfo.linkStuckCount < MAX_STUCK_LINK_COUNT) { - wifiInfo.linkStuckCount += 1; - } - } else if (wifiInfo.txBadRate < MIN_TX_FAILURE_RATE_FOR_WORKING_LINK) { - if (wifiInfo.linkStuckCount > 0) { - wifiInfo.linkStuckCount -= 1; - } - } - - if (rssi < rssiThreshBad) { - if (wifiInfo.badRssiCount < MAX_BAD_RSSI_COUNT) { - wifiInfo.badRssiCount += 1; - } - } else if (rssi < rssiThreshLow) { - wifiInfo.lowRssiCount = MAX_LOW_RSSI_COUNT; // Dont increment the lowRssi count above 1 - if (wifiInfo.badRssiCount > 0) { - // Decrement bad Rssi count - wifiInfo.badRssiCount -= 1; - } - } else { - wifiInfo.badRssiCount = 0; - wifiInfo.lowRssiCount = 0; - } - - } - - /** - * Calculates the score, without all the cruft. - */ - private int calculateScore(WifiInfo wifiInfo, int aggressiveHandover) { - int score = STARTING_SCORE; - - int rssiThreshSaturated = mThresholdSaturatedRssi24; - int linkspeedThreshBad = mBadLinkSpeed24; - int linkspeedThreshGood = mGoodLinkSpeed24; - - if (wifiInfo.is5GHz()) { - if (!mMultiBandScanResults) { - rssiThreshSaturated = mThresholdSaturatedRssi5; - } - linkspeedThreshBad = mBadLinkSpeed5; - linkspeedThreshGood = mGoodLinkSpeed5; - } - - int rssi = wifiInfo.getRssi(); - if (aggressiveHandover != 0) { - rssi -= AGGRESSIVE_HANDOVER_PENALTY * aggressiveHandover; - } - if (mIsHomeNetwork) { - rssi += WifiConfiguration.HOME_NETWORK_RSSI_BOOST; - } - - int linkSpeed = wifiInfo.getLinkSpeed(); - - if (wifiInfo.linkStuckCount > MIN_SUSTAINED_LINK_STUCK_COUNT) { - // Once link gets stuck for more than 3 seconds, start reducing the score - score = score - LINK_STUCK_PENALTY * (wifiInfo.linkStuckCount - 1); - } - - if (linkSpeed < linkspeedThreshBad) { - score -= BAD_LINKSPEED_PENALTY; - } else if ((linkSpeed >= linkspeedThreshGood) && (wifiInfo.txSuccessRate > 5)) { - score += GOOD_LINKSPEED_BONUS; // So as bad rssi alone doesn't kill us - } - - score -= wifiInfo.badRssiCount * BAD_RSSI_COUNT_PENALTY + wifiInfo.lowRssiCount; - - if (rssi >= rssiThreshSaturated) score += 5; - - if (score > NetworkAgent.WIFI_BASE_SCORE) score = NetworkAgent.WIFI_BASE_SCORE; - if (score < 0) score = 0; - - return score; - } - - /** - * Determines if we can see both 2.4GHz and 5GHz for current config - */ - private boolean multiBandScanResults(WifiInfo wifiInfo) { - WifiConfiguration currentConfiguration = - mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId()); - if (currentConfiguration == null) return false; - ScanDetailCache scanDetailCache = - mWifiConfigManager.getScanDetailCacheForNetwork(wifiInfo.getNetworkId()); - if (scanDetailCache == null) return false; - // Nasty that we change state here... - currentConfiguration.setVisibility(scanDetailCache.getVisibility(SCAN_CACHE_VISIBILITY_MS)); - if (currentConfiguration.visibility == null) return false; - if (currentConfiguration.visibility.rssi24 == WifiConfiguration.INVALID_RSSI) return false; - if (currentConfiguration.visibility.rssi5 == WifiConfiguration.INVALID_RSSI) return false; - // N.B. this does not do exactly what is claimed! - if (currentConfiguration.visibility.rssi24 - >= currentConfiguration.visibility.rssi5 - SCAN_CACHE_COUNT_PENALTY) { - return true; - } - return false; - } - - /** - * Decides whether the current network is a "home" network - */ - private boolean isHomeNetwork(WifiInfo wifiInfo) { - WifiConfiguration currentConfiguration = - mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId()); - if (currentConfiguration == null) return false; - // This seems like it will only return true for really old routers! - if (currentConfiguration.allowedKeyManagement.cardinality() != 1) return false; - if (!currentConfiguration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { - return false; - } - ScanDetailCache scanDetailCache = - mWifiConfigManager.getScanDetailCacheForNetwork(wifiInfo.getNetworkId()); - if (scanDetailCache == null) return false; - if (scanDetailCache.size() <= HOME_VISIBLE_NETWORK_MAX_COUNT) { - return true; - } - return false; - } - - /** - * Experimental scorer, used when aggressive handover preference is set - */ - private int calculateAlternativeScore(WifiInfo wifiInfo) { - double rssi = wifiInfo.getRssi(); - double badRssi = wifiInfo.is5GHz() ? mThresholdQualifiedRssi5 : mThresholdQualifiedRssi24; - - double baseScore = 50.0; // The score to beat to be chosen over mobile data - double score = (rssi - badRssi) + baseScore; - return (int) Math.round(score); - } - - /** * Data for dumpsys * * These are stored as csv formatted lines |