diff options
5 files changed, 60 insertions, 44 deletions
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index b576a20db53a..47666b57e8fd 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -62,6 +62,8 @@ public class NetworkStatsFactory {      /** Path to {@code /proc/net/xt_qtaguid/stats}. */      private final File mStatsXtUid; +    private boolean mUseBpfStats; +      // TODO: to improve testability and avoid global state, do not use a static variable.      @GuardedBy("sStackedIfaces")      private static final ArrayMap<String, String> sStackedIfaces = new ArrayMap<>(); @@ -77,14 +79,15 @@ public class NetworkStatsFactory {      }      public NetworkStatsFactory() { -        this(new File("/proc/")); +        this(new File("/proc/"), new File("/sys/fs/bpf/traffic_uid_stats_map").exists());      }      @VisibleForTesting -    public NetworkStatsFactory(File procRoot) { +    public NetworkStatsFactory(File procRoot, boolean useBpfStats) {          mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");          mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");          mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); +        mUseBpfStats = useBpfStats;      }      /** @@ -252,7 +255,7 @@ public class NetworkStatsFactory {                  stats = new NetworkStats(SystemClock.elapsedRealtime(), -1);              }              if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid, -                    limitIfaces, limitTag) != 0) { +                    limitIfaces, limitTag, mUseBpfStats) != 0) {                  throw new IOException("Failed to parse network stats");              }              if (SANITY_CHECK_NATIVE) { @@ -346,6 +349,6 @@ public class NetworkStatsFactory {       * are expected to monotonically increase since device boot.       */      @VisibleForTesting -    public static native int nativeReadNetworkStatsDetail( -            NetworkStats stats, String path, int limitUid, String[] limitIfaces, int limitTag); +    public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path, +        int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats);  } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index bc98716ebc9c..b3fb43d58656 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -215,6 +215,8 @@ cc_library_shared {      ],      shared_libs: [ +        "libbpf", +        "libnetdutils",          "libmemtrack",          "libandroidfw",          "libappfuse", diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index d254de65f765..99d983957075 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -30,7 +30,14 @@  #include <utils/Log.h>  #include <utils/misc.h> -#include <utils/Vector.h> + +#include "android-base/unique_fd.h" +#include "bpf/BpfNetworkStats.h" +#include "bpf/BpfUtils.h" + +using android::bpf::hasBpfSupport; +using android::bpf::parseBpfNetworkStatsDetail; +using android::bpf::stats_line;  namespace android { @@ -53,17 +60,6 @@ static struct {      jfieldID operations;  } gNetworkStatsClassInfo; -struct stats_line { -    char iface[32]; -    int32_t uid; -    int32_t set; -    int32_t tag; -    int64_t rxBytes; -    int64_t rxPackets; -    int64_t txBytes; -    int64_t txPackets; -}; -  static jobjectArray get_string_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)  {      if (!grow) { @@ -97,33 +93,14 @@ static jlongArray get_long_array(JNIEnv* env, jobject obj, jfieldID field, int s      return env->NewLongArray(size);  } -static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, -        jstring path, jint limitUid, jobjectArray limitIfacesObj, jint limitTag) { -    ScopedUtfChars path8(env, path); -    if (path8.c_str() == NULL) { -        return -1; -    } - -    FILE *fp = fopen(path8.c_str(), "r"); +static int legacyReadNetworkStatsDetail(std::vector<stats_line>* lines, +                                        const std::vector<std::string>& limitIfaces, +                                        int limitTag, int limitUid, const char* path) { +    FILE* fp = fopen(path, "r");      if (fp == NULL) {          return -1;      } -    Vector<String8> limitIfaces; -    if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) { -        int num = env->GetArrayLength(limitIfacesObj); -        limitIfaces.setCapacity(num); -        for (int i=0; i<num; i++) { -            jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i); -            ScopedUtfChars string8(env, string); -            if (string8.c_str() != NULL) { -                limitIfaces.add(String8(string8.c_str())); -            } -        } -    } - -    Vector<stats_line> lines; -      int lastIdx = 1;      int idx;      char buffer[384]; @@ -215,7 +192,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,                  //ALOGI("skipping due to uid: %s", buffer);                  continue;              } -            lines.push_back(s); +            lines->push_back(s);          } else {              //ALOGI("skipping due to bad remaining fields: %s", pos);          } @@ -225,8 +202,42 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,          ALOGE("Failed to close netstats file");          return -1;      } +    return 0; +} + +static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path, +                                  jint limitUid, jobjectArray limitIfacesObj, jint limitTag, +                                  jboolean useBpfStats) { +    ScopedUtfChars path8(env, path); +    if (path8.c_str() == NULL) { +        return -1; +    } + +    std::vector<std::string> limitIfaces; +    if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) { +        int num = env->GetArrayLength(limitIfacesObj); +        for (int i = 0; i < num; i++) { +            jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i); +            ScopedUtfChars string8(env, string); +            if (string8.c_str() != NULL) { +                limitIfaces.push_back(std::string(string8.c_str())); +            } +        } +    } +    std::vector<stats_line> lines; + + +    if (useBpfStats) { +        if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0) +            return -1; +    } else { +        if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag, +                                         limitUid, path8.c_str()) < 0) +            return -1; +    }      int size = lines.size(); +      bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity);      ScopedLocalRef<jobjectArray> iface(env, get_string_array(env, stats, @@ -303,7 +314,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,  static const JNINativeMethod gMethods[] = {          { "nativeReadNetworkStatsDetail", -                "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;I)I", +                "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I",                  (void*) readNetworkStatsDetail }  }; diff --git a/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java b/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java index e62fbd6568f7..c2134649655a 100644 --- a/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java +++ b/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java @@ -53,7 +53,7 @@ public class NetworkStatsFactoryBenchmark {                      stats, mStats.getAbsolutePath(), NetworkStats.UID_ALL,                      // Looks like this was broken by change d0c5b9abed60b7bc056d026bf0f2b2235410fb70                      // Fixed compilation problem but needs addressing properly. -                    new String[0], 999); +                    new String[0], 999, false);          }      }  } diff --git a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java index 56b8e608dad1..b267cb53d3ca 100644 --- a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java +++ b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java @@ -67,7 +67,7 @@ public class NetworkStatsFactoryTest {              IoUtils.deleteContents(mTestProc);          } -        mFactory = new NetworkStatsFactory(mTestProc); +        mFactory = new NetworkStatsFactory(mTestProc, false);      }      @After  |