Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db910397 authored by Chenbo Feng's avatar Chenbo Feng Committed by Lorenzo Colitti
Browse files

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 f729cb5f)
parent bce7364a
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -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");