Support NetworkCallbacks based on signal strength.
Bug: 21405941
Change-Id: I2ed8a5aeb8dac464a4305671ed22abcacb485bc9
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 08754c2..49d35b8 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -150,6 +150,8 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.SortedSet;
+import java.util.TreeSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -1934,7 +1936,7 @@
(NetworkCapabilities)msg.obj;
if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) ||
networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
- Slog.wtf(TAG, "BUG: " + nai + " has stateful capability.");
+ Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
}
if (nai.created && !nai.networkCapabilities.equalImmutableCapabilities(
networkCapabilities)) {
@@ -2250,6 +2252,13 @@
private void handleRegisterNetworkRequest(NetworkRequestInfo nri) {
mNetworkRequests.put(nri.request, nri);
mNetworkRequestInfoLogs.log("REGISTER " + nri);
+ if (!nri.isRequest) {
+ for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
+ if (network.satisfiesImmutableCapabilitiesOf(nri.request)) {
+ updateSignalStrengthThresholds(network);
+ }
+ }
+ }
rematchAllNetworksAndRequests(null, 0);
if (nri.isRequest && mNetworkForRequestId.get(nri.request.requestId) == null) {
sendUpdatedScoreToFactories(nri.request, 0);
@@ -2363,6 +2372,9 @@
// if this listen request applies and remove it.
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
nai.networkRequests.remove(nri.request.requestId);
+ if (nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
+ updateSignalStrengthThresholds(nai);
+ }
}
}
callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED);
@@ -3599,6 +3611,34 @@
}
}
+ private int[] getSignalStrengthThresholds(NetworkAgentInfo nai) {
+ final SortedSet<Integer> thresholds = new TreeSet();
+ synchronized (nai) {
+ for (NetworkRequestInfo nri : mNetworkRequests.values()) {
+ if (nri.request.networkCapabilities.hasSignalStrength() &&
+ nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
+ thresholds.add(nri.request.networkCapabilities.getSignalStrength());
+ }
+ }
+ }
+ // We can't just do something like:
+ // return thresholds.toArray(new int[thresholds.size()]);
+ // because autoboxing does not work for primitive arrays.
+ final int[] out = new int[thresholds.size()];
+ int pos = 0;
+ for (Integer threshold : thresholds) {
+ out[pos] = threshold;
+ pos++;
+ }
+ return out;
+ }
+
+ private void updateSignalStrengthThresholds(NetworkAgentInfo nai) {
+ nai.asyncChannel.sendMessage(
+ android.net.NetworkAgent.CMD_SET_SIGNAL_STRENGTH_THRESHOLDS,
+ 0, 0, getSignalStrengthThresholds(nai));
+ }
+
@Override
public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
@@ -4523,6 +4563,15 @@
// TODO: support proxy per network.
}
+ // Whether a particular NetworkRequest listen should cause signal strength thresholds to
+ // be communicated to a particular NetworkAgent depends only on the network's immutable,
+ // capabilities, so it only needs to be done once on initial connect, not every time the
+ // network's capabilities change. Note that we do this before rematching the network,
+ // so we could decide to tear it down immediately afterwards. That's fine though - on
+ // disconnection NetworkAgents should stop any signal strength monitoring they have been
+ // doing.
+ updateSignalStrengthThresholds(networkAgent);
+
// Consider network even though it is not yet validated.
rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP);