Connectivity metrics: serialize networkId, transports, ifname
This patch adds translation from ConnectivityMetricsEvent to
IpConnectivityEvent of recently added fields:
- top-level network id
- top-level ifname
- transports
Also adds inference of link layer from transports or ifname.
At the moment these new fields are not populated in
ConnectivityMetricsEvent. Follow-up patches will fill this gap for
the events of the android.net.metrics package.
Test: new unit tests, $ runtest frameworks-net passes
Bug: 34901696
Change-Id: I563a6a3183470bdfaabb7c781a1beaf6b1058bf0
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
index 81e891a..4991b2b 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityEventBuilder.java
@@ -16,6 +16,17 @@
package com.android.server.connectivity;
+import static android.net.NetworkCapabilities.MAX_TRANSPORT;
+import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
+import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
+import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
+import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.NetworkId;
+
import android.net.ConnectivityMetricsEvent;
import android.net.metrics.ApfProgramEvent;
import android.net.metrics.ApfStats;
@@ -29,14 +40,12 @@
import android.net.metrics.RaEvent;
import android.net.metrics.ValidationProbeEvent;
import android.os.Parcelable;
+import android.util.SparseArray;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityLog;
-import static com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.NetworkId;
/** {@hide} */
final public class IpConnectivityEventBuilder {
@@ -73,6 +82,12 @@
return null;
}
out.timeMs = ev.timestamp;
+ out.networkId = ev.netId;
+ out.transports = ev.transports;
+ if (ev.ifname != null) {
+ out.ifName = ev.ifname;
+ }
+ inferLinkLayer(out);
return out;
}
@@ -280,4 +295,70 @@
private static boolean isBitSet(int flags, int bit) {
return (flags & (1 << bit)) != 0;
}
+
+ private static void inferLinkLayer(IpConnectivityEvent ev) {
+ int linkLayer = IpConnectivityLogClass.UNKNOWN;
+ if (ev.transports != 0) {
+ linkLayer = transportsToLinkLayer(ev.transports);
+ } else if (ev.ifName != null) {
+ linkLayer = ifnameToLinkLayer(ev.ifName);
+ }
+ if (linkLayer == IpConnectivityLogClass.UNKNOWN) {
+ return;
+ }
+ ev.linkLayer = linkLayer;
+ ev.ifName = "";
+ }
+
+ private static int transportsToLinkLayer(long transports) {
+ switch (Long.bitCount(transports)) {
+ case 0:
+ return IpConnectivityLogClass.UNKNOWN;
+ case 1:
+ int t = Long.numberOfTrailingZeros(transports);
+ return transportToLinkLayer(t);
+ default:
+ return IpConnectivityLogClass.MULTIPLE;
+ }
+ }
+
+ private static int transportToLinkLayer(int transport) {
+ if (0 <= transport && transport < TRANSPORT_LINKLAYER_MAP.length) {
+ return TRANSPORT_LINKLAYER_MAP[transport];
+ }
+ return IpConnectivityLogClass.UNKNOWN;
+ }
+
+ private static final int[] TRANSPORT_LINKLAYER_MAP = new int[MAX_TRANSPORT + 1];
+ static {
+ TRANSPORT_LINKLAYER_MAP[TRANSPORT_CELLULAR] = IpConnectivityLogClass.CELLULAR;
+ TRANSPORT_LINKLAYER_MAP[TRANSPORT_WIFI] = IpConnectivityLogClass.WIFI;
+ TRANSPORT_LINKLAYER_MAP[TRANSPORT_BLUETOOTH] = IpConnectivityLogClass.BLUETOOTH;
+ TRANSPORT_LINKLAYER_MAP[TRANSPORT_ETHERNET] = IpConnectivityLogClass.ETHERNET;
+ TRANSPORT_LINKLAYER_MAP[TRANSPORT_VPN] = IpConnectivityLogClass.UNKNOWN;
+ // TODO: change mapping TRANSPORT_WIFI_AWARE -> WIFI_AWARE
+ TRANSPORT_LINKLAYER_MAP[TRANSPORT_WIFI_AWARE] = IpConnectivityLogClass.UNKNOWN;
+ };
+
+ private static int ifnameToLinkLayer(String ifname) {
+ // Do not try to catch all interface names with regexes, instead only catch patterns that
+ // are cheap to check, and otherwise fallback on postprocessing in aggregation layer.
+ for (int i = 0; i < IFNAME_LINKLAYER_MAP.size(); i++) {
+ String pattern = IFNAME_LINKLAYER_MAP.valueAt(i);
+ if (ifname.startsWith(pattern)) {
+ return IFNAME_LINKLAYER_MAP.keyAt(i);
+ }
+ }
+ return IpConnectivityLogClass.UNKNOWN;
+ }
+
+ private static final SparseArray<String> IFNAME_LINKLAYER_MAP = new SparseArray<String>();
+ static {
+ IFNAME_LINKLAYER_MAP.put(IpConnectivityLogClass.CELLULAR, "rmnet");
+ IFNAME_LINKLAYER_MAP.put(IpConnectivityLogClass.WIFI, "wlan");
+ IFNAME_LINKLAYER_MAP.put(IpConnectivityLogClass.BLUETOOTH, "bt-pan");
+ // TODO: rekey to USB
+ IFNAME_LINKLAYER_MAP.put(IpConnectivityLogClass.ETHERNET, "usb");
+ // TODO: add mappings for nan -> WIFI_AWARE and p2p -> WIFI_P2P
+ }
}