OSDN Git Service

Add a lock to protect persistent stats snapshot
authorChenbo Feng <fengc@google.com>
Wed, 10 Apr 2019 19:55:07 +0000 (12:55 -0700)
committerChenbo Feng <fengc@google.com>
Wed, 10 Apr 2019 19:59:18 +0000 (12:59 -0700)
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

services/core/java/com/android/server/net/NetworkStatsFactory.java

index bf34d8f..bd11d46 100644 (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) {