fix getIfaceStats and getTotalStats bug

root cause: getIfaceStats and getTotalStats is directly reading
iface_stat_fmt or eBPF, not include tether stats.
solution: add tether stats to getIfaceStats and getTotalStats.

Clean cherry-pick of aosp/848934

Bug: 120039819
Test case1:
1. tether offload is enabled on phone, enable MHS on phone.
2. Use test app to check getMobileRxBytes->getIfaceStats
3. Download 10M file on MHS client
4. Use test app to check getMobileRxBytes->getIfaceStats again
result: getMobileRxBytes increased around 10M

Test case2:
1. tether offload is disabled on phone, enable MHS on phone.
repeat above step 2~4
result: getMobileRxBytes increased around 10M

Following CTS cases passed
run cts -m CtsNetTestCases --test android.net.cts.TrafficStatsTest
run cts -m CtsUsageStatsTestCases --test android.app.usage.cts.NetworkUsageStatsTest

Change-Id: I3d94acb71c142ec38b750e58822881ff383341cc
This commit is contained in:
Mike SU
2018-11-26 15:05:13 +08:00
committed by junyulai
parent 14c16b87a9
commit 77c8591f9d

View File

@@ -962,12 +962,64 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override
public long getIfaceStats(String iface, int type) {
return nativeGetIfaceStat(iface, type, checkBpfStatsEnable());
long nativeIfaceStats = nativeGetIfaceStat(iface, type, checkBpfStatsEnable());
if (nativeIfaceStats == -1) {
return nativeIfaceStats;
} else {
// When tethering offload is in use, nativeIfaceStats does not contain usage from
// offload, add it back here.
// When tethering offload is not in use, nativeIfaceStats contains tethering usage.
// this does not cause double-counting of tethering traffic, because
// NetdTetheringStatsProvider returns zero NetworkStats
// when called with STATS_PER_IFACE.
return nativeIfaceStats + getTetherStats(iface, type);
}
}
@Override
public long getTotalStats(int type) {
return nativeGetTotalStat(type, checkBpfStatsEnable());
long nativeTotalStats = nativeGetTotalStat(type, checkBpfStatsEnable());
if (nativeTotalStats == -1) {
return nativeTotalStats;
} else {
// Refer to comment in getIfaceStats
return nativeTotalStats + getTetherStats(IFACE_ALL, type);
}
}
private long getTetherStats(String iface, int type) {
final NetworkStats tetherSnapshot;
final long token = Binder.clearCallingIdentity();
try {
tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE);
} catch (RemoteException e) {
Slog.w(TAG, "Error get TetherStats: " + e);
return 0;
} finally {
Binder.restoreCallingIdentity(token);
}
HashSet<String> limitIfaces;
if (iface == IFACE_ALL) {
limitIfaces = null;
} else {
limitIfaces = new HashSet<String>();
limitIfaces.add(iface);
}
NetworkStats.Entry entry = tetherSnapshot.getTotal(null, limitIfaces);
if (LOGD) Slog.d(TAG, "TetherStats: iface=" + iface + " type=" + type +
" entry=" + entry);
switch (type) {
case 0: // TYPE_RX_BYTES
return entry.rxBytes;
case 1: // TYPE_RX_PACKETS
return entry.rxPackets;
case 2: // TYPE_TX_BYTES
return entry.txBytes;
case 3: // TYPE_TX_PACKETS
return entry.txPackets;
default:
return 0;
}
}
private boolean checkBpfStatsEnable() {