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;
private boolean mUseBpfStats;
+ private INetd mNetdService;
+
// A persistent Snapshot since device start for eBPF stats
@GuardedBy("mPersistSnapshot")
private final NetworkStats mPersistSnapshot;
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 {
}
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");