From 7b906dea29aa2922856009c8452957b4136dd85a Mon Sep 17 00:00:00 2001 From: Motomu Utsumi Date: Fri, 30 Aug 2024 19:44:54 +0900 Subject: [PATCH] Fix threading issue for mDefaultNetworkRequests Handler thread updates mDefaultNetworkRequests and Multiple threads read/iterate mDefaultNetworkRequests without locking. This caused NPE when there is concurrent updates and iterations. This CL fixed this issue by using CopyOnWriteArraySet. CopyOnWriteArraySet is suitable since number of default network request is small (system default network request + per-app default network requests) and updated infrequently but read frequently. Bug: 293978451 Test: TH Change-Id: Iaefe8e6e31c2b5257ebc51b4f848c3a7197781cb --- service/src/com/android/server/ConnectivityService.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index 53b1eb24bb..97a57f9e6c 100755 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -407,6 +407,7 @@ import java.util.Set; import java.util.SortedSet; import java.util.StringJoiner; import java.util.TreeSet; +import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; @@ -8933,9 +8934,15 @@ public class ConnectivityService extends IConnectivityManager.Stub @NonNull final NetworkRequestInfo mDefaultRequest; // Collection of NetworkRequestInfo's used for default networks. + // This set is read and iterated on multiple threads. + // Using CopyOnWriteArraySet since number of default network request is small (system default + // network request + per-app default network requests) and updated infrequently but read + // frequently. @VisibleForTesting @NonNull - final ArraySet mDefaultNetworkRequests = new ArraySet<>(); + final CopyOnWriteArraySet mDefaultNetworkRequests = + new CopyOnWriteArraySet<>(); + private boolean isPerAppDefaultRequest(@NonNull final NetworkRequestInfo nri) { return (mDefaultNetworkRequests.contains(nri) && mDefaultRequest != nri);