com_android_internal_net_NetworkStatsFactory.cpp revision f5fabdf83d2a1b30fcbd2a25882f98e282e4f762
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "NetworkStats" 18 19#include <errno.h> 20#include <sys/stat.h> 21#include <sys/types.h> 22 23#include <android_runtime/AndroidRuntime.h> 24#include <jni.h> 25 26#include <ScopedUtfChars.h> 27#include <ScopedLocalRef.h> 28#include <ScopedPrimitiveArray.h> 29 30#include <utils/Log.h> 31#include <utils/misc.h> 32#include <utils/Vector.h> 33 34namespace android { 35 36static jclass gStringClass; 37 38static struct { 39 jfieldID size; 40 jfieldID iface; 41 jfieldID uid; 42 jfieldID set; 43 jfieldID tag; 44 jfieldID rxBytes; 45 jfieldID rxPackets; 46 jfieldID txBytes; 47 jfieldID txPackets; 48 jfieldID operations; 49} gNetworkStatsClassInfo; 50 51struct stats_line { 52 int32_t idx; 53 char iface[32]; 54 int32_t uid; 55 int32_t set; 56 int32_t tag; 57 int64_t rxBytes; 58 int64_t rxPackets; 59 int64_t txBytes; 60 int64_t txPackets; 61}; 62 63static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, 64 jstring path, jint limitUid) { 65 ScopedUtfChars path8(env, path); 66 if (path8.c_str() == NULL) { 67 return -1; 68 } 69 70 FILE *fp = fopen(path8.c_str(), "r"); 71 if (fp == NULL) { 72 return -1; 73 } 74 75 Vector<stats_line> lines; 76 77 int lastIdx = 1; 78 char buffer[384]; 79 while (fgets(buffer, sizeof(buffer), fp) != NULL) { 80 stats_line s; 81 int64_t rawTag; 82 if (sscanf(buffer, "%d %31s 0x%llx %u %u %llu %llu %llu %llu", &s.idx, 83 s.iface, &rawTag, &s.uid, &s.set, &s.rxBytes, &s.rxPackets, 84 &s.txBytes, &s.txPackets) == 9) { 85 if (s.idx != lastIdx + 1) { 86 ALOGE("inconsistent idx=%d after lastIdx=%d", s.idx, lastIdx); 87 return -1; 88 } 89 lastIdx = s.idx; 90 91 s.tag = rawTag >> 32; 92 lines.push_back(s); 93 } 94 } 95 96 if (fclose(fp) != 0) { 97 return -1; 98 } 99 100 int size = lines.size(); 101 102 ScopedLocalRef<jobjectArray> iface(env, env->NewObjectArray(size, gStringClass, NULL)); 103 if (iface.get() == NULL) return -1; 104 ScopedIntArrayRW uid(env, env->NewIntArray(size)); 105 if (uid.get() == NULL) return -1; 106 ScopedIntArrayRW set(env, env->NewIntArray(size)); 107 if (set.get() == NULL) return -1; 108 ScopedIntArrayRW tag(env, env->NewIntArray(size)); 109 if (tag.get() == NULL) return -1; 110 ScopedLongArrayRW rxBytes(env, env->NewLongArray(size)); 111 if (rxBytes.get() == NULL) return -1; 112 ScopedLongArrayRW rxPackets(env, env->NewLongArray(size)); 113 if (rxPackets.get() == NULL) return -1; 114 ScopedLongArrayRW txBytes(env, env->NewLongArray(size)); 115 if (txBytes.get() == NULL) return -1; 116 ScopedLongArrayRW txPackets(env, env->NewLongArray(size)); 117 if (txPackets.get() == NULL) return -1; 118 ScopedLongArrayRW operations(env, env->NewLongArray(size)); 119 if (operations.get() == NULL) return -1; 120 121 for (int i = 0; i < size; i++) { 122 ScopedLocalRef<jstring> ifaceString(env, env->NewStringUTF(lines[i].iface)); 123 env->SetObjectArrayElement(iface.get(), i, ifaceString.get()); 124 125 uid[i] = lines[i].uid; 126 set[i] = lines[i].set; 127 tag[i] = lines[i].tag; 128 rxBytes[i] = lines[i].rxBytes; 129 rxPackets[i] = lines[i].rxPackets; 130 txBytes[i] = lines[i].txBytes; 131 txPackets[i] = lines[i].txPackets; 132 } 133 134 env->SetIntField(stats, gNetworkStatsClassInfo.size, size); 135 env->SetObjectField(stats, gNetworkStatsClassInfo.iface, iface.get()); 136 env->SetObjectField(stats, gNetworkStatsClassInfo.uid, uid.getJavaArray()); 137 env->SetObjectField(stats, gNetworkStatsClassInfo.set, set.getJavaArray()); 138 env->SetObjectField(stats, gNetworkStatsClassInfo.tag, tag.getJavaArray()); 139 env->SetObjectField(stats, gNetworkStatsClassInfo.rxBytes, rxBytes.getJavaArray()); 140 env->SetObjectField(stats, gNetworkStatsClassInfo.rxPackets, rxPackets.getJavaArray()); 141 env->SetObjectField(stats, gNetworkStatsClassInfo.txBytes, txBytes.getJavaArray()); 142 env->SetObjectField(stats, gNetworkStatsClassInfo.txPackets, txPackets.getJavaArray()); 143 env->SetObjectField(stats, gNetworkStatsClassInfo.operations, operations.getJavaArray()); 144 145 return 0; 146} 147 148static jclass findClass(JNIEnv* env, const char* name) { 149 ScopedLocalRef<jclass> localClass(env, env->FindClass(name)); 150 jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get())); 151 if (result == NULL) { 152 ALOGE("failed to find class '%s'", name); 153 abort(); 154 } 155 return result; 156} 157 158static JNINativeMethod gMethods[] = { 159 { "nativeReadNetworkStatsDetail", 160 "(Landroid/net/NetworkStats;Ljava/lang/String;I)I", 161 (void*) readNetworkStatsDetail } 162}; 163 164int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) { 165 int err = AndroidRuntime::registerNativeMethods(env, 166 "com/android/internal/net/NetworkStatsFactory", gMethods, 167 NELEM(gMethods)); 168 169 gStringClass = findClass(env, "java/lang/String"); 170 171 jclass clazz = env->FindClass("android/net/NetworkStats"); 172 gNetworkStatsClassInfo.size = env->GetFieldID(clazz, "size", "I"); 173 gNetworkStatsClassInfo.iface = env->GetFieldID(clazz, "iface", "[Ljava/lang/String;"); 174 gNetworkStatsClassInfo.uid = env->GetFieldID(clazz, "uid", "[I"); 175 gNetworkStatsClassInfo.set = env->GetFieldID(clazz, "set", "[I"); 176 gNetworkStatsClassInfo.tag = env->GetFieldID(clazz, "tag", "[I"); 177 gNetworkStatsClassInfo.rxBytes = env->GetFieldID(clazz, "rxBytes", "[J"); 178 gNetworkStatsClassInfo.rxPackets = env->GetFieldID(clazz, "rxPackets", "[J"); 179 gNetworkStatsClassInfo.txBytes = env->GetFieldID(clazz, "txBytes", "[J"); 180 gNetworkStatsClassInfo.txPackets = env->GetFieldID(clazz, "txPackets", "[J"); 181 gNetworkStatsClassInfo.operations = env->GetFieldID(clazz, "operations", "[J"); 182 183 return err; 184} 185 186} 187