Add a lock to protect persistent stats snapshot

Since the network stats could be polled from multiple services at
runtime, it is not thread safe for networkStatsFactory to hold a
persistent stats snapshot without any protection. Use a internal lock to
prevent concurrent modification on mPersistentSnapshot to fix the
problem.

Bug: 124764595
Test: android.app.usage.cts.NetworkUsageStatsTest
      android.net.cts.TrafficStatsTest

Change-Id: I22afb46f17697e8b6359d4f593802e0f4b95db8b
This commit is contained in:
Chenbo Feng
2019-04-10 12:55:07 -07:00
parent c452cbf496
commit 0c419ca9eb

View File

@@ -28,6 +28,7 @@ import android.net.NetworkStats;
import android.os.StrictMode;
import android.os.SystemClock;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ProcFileReader;
@@ -65,6 +66,7 @@ public class NetworkStatsFactory {
private boolean mUseBpfStats;
// A persistent Snapshot since device start for eBPF stats
@GuardedBy("mPersistSnapshot")
private final NetworkStats mPersistSnapshot;
// TODO: only do adjustments in NetworkStatsService and remove this.
@@ -289,15 +291,17 @@ public class NetworkStatsFactory {
stats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
}
if (mUseBpfStats) {
if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL,
null, TAG_ALL, mUseBpfStats) != 0) {
throw new IOException("Failed to parse network stats");
synchronized (mPersistSnapshot) {
if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL,
null, TAG_ALL, mUseBpfStats) != 0) {
throw new IOException("Failed to parse network stats");
}
mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime());
mPersistSnapshot.combineAllValues(stats);
NetworkStats result = mPersistSnapshot.clone();
result.filter(limitUid, limitIfaces, limitTag);
return result;
}
mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime());
mPersistSnapshot.combineAllValues(stats);
NetworkStats result = mPersistSnapshot.clone();
result.filter(limitUid, limitIfaces, limitTag);
return result;
} else {
if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid,
limitIfaces, limitTag, mUseBpfStats) != 0) {