Ask netd to swap stats map before reading
To avoid protentail race problem between netd and system_server when
reading the network stats map. Always inform netd before reading the
stats and let netd to do a swap between active stats map and inactive
stats map. So the system_server can safely remove the stats after
reading.
Bug: 126620214
Test: android.app.usage.cts.NetworkUsageStatsTest
android.net.cts.TrafficStatsTest
Change-Id: I8fa37c26bec23ffca0b29b679e72ba1189f557f1
Merged-In: I8fa37c26bec23ffca0b29b679e72ba1189f557f1
(cherry picked from commit f729cb5fd654a0f099128734f849800fde9ba525)
This commit is contained in:
committed by
Lorenzo Colitti
parent
aeb31b53c6
commit
10fac71887
@@ -24,7 +24,10 @@ import static android.net.NetworkStats.UID_ALL;
|
||||
import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.net.INetd;
|
||||
import android.net.NetworkStats;
|
||||
import android.net.util.NetdService;
|
||||
import android.os.RemoteException;
|
||||
import android.os.StrictMode;
|
||||
import android.os.SystemClock;
|
||||
|
||||
@@ -65,6 +68,8 @@ public class NetworkStatsFactory {
|
||||
|
||||
private boolean mUseBpfStats;
|
||||
|
||||
private INetd mNetdService;
|
||||
|
||||
// A persistent Snapshot since device start for eBPF stats
|
||||
@GuardedBy("mPersistSnapshot")
|
||||
private final NetworkStats mPersistSnapshot;
|
||||
@@ -274,6 +279,19 @@ public class NetworkStatsFactory {
|
||||
return stats;
|
||||
}
|
||||
|
||||
@GuardedBy("mPersistSnapshot")
|
||||
private void requestSwapActiveStatsMapLocked() throws RemoteException {
|
||||
// Ask netd to do a active map stats swap. When the binder call successfully returns,
|
||||
// the system server should be able to safely read and clean the inactive map
|
||||
// without race problem.
|
||||
if (mUseBpfStats) {
|
||||
if (mNetdService == null) {
|
||||
mNetdService = NetdService.getInstance();
|
||||
}
|
||||
mNetdService.trafficSwapActiveStatsMap();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: delete the lastStats parameter
|
||||
private NetworkStats readNetworkStatsDetailInternal(int limitUid, String[] limitIfaces,
|
||||
int limitTag, NetworkStats lastStats) throws IOException {
|
||||
@@ -287,6 +305,13 @@ public class NetworkStatsFactory {
|
||||
}
|
||||
if (mUseBpfStats) {
|
||||
synchronized (mPersistSnapshot) {
|
||||
try {
|
||||
requestSwapActiveStatsMapLocked();
|
||||
} catch (RemoteException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
// Stats are always read from the inactive map, so they must be read after the
|
||||
// swap
|
||||
if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL,
|
||||
null, TAG_ALL, mUseBpfStats) != 0) {
|
||||
throw new IOException("Failed to parse network stats");
|
||||
|
||||
Reference in New Issue
Block a user