From c3a43b406326bc6d736ef710a136e5a74f143f0a Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 1 Apr 2022 16:34:22 +0800 Subject: [PATCH] Fix NullPointerException happens in dumpCheckin Currently dumpCheckin passes a null object to create the contructor of NetworkStatsCollection.Key but the constructor requires non-null object. Thus, it caused the NPE in dumpCheckin. To fix this exception, create an NetworkIdentitySet() object instead of using an null object. Bug: 225131008 Bug: 226539404 Test: dumpsys netstats --checkin is fine FrameworksNetTests Change-Id: I7f2dadf0647b3f42e0f667d96291d2ae37e23faf --- .../src/android/net/NetworkIdentitySet.java | 1 + .../android/net/NetworkStatsCollection.java | 2 +- tests/unit/Android.bp | 1 + .../android/net/NetworkIdentitySetTest.kt | 66 +++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 tests/unit/java/android/net/NetworkIdentitySetTest.kt diff --git a/framework-t/src/android/net/NetworkIdentitySet.java b/framework-t/src/android/net/NetworkIdentitySet.java index ad3a958a68..d88408eef0 100644 --- a/framework-t/src/android/net/NetworkIdentitySet.java +++ b/framework-t/src/android/net/NetworkIdentitySet.java @@ -206,6 +206,7 @@ public class NetworkIdentitySet extends HashSet { public static int compare(@NonNull NetworkIdentitySet left, @NonNull NetworkIdentitySet right) { Objects.requireNonNull(left); Objects.requireNonNull(right); + if (left.isEmpty() && right.isEmpty()) return 0; if (left.isEmpty()) return -1; if (right.isEmpty()) return 1; diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java index e385b33447..b59a890a2a 100644 --- a/framework-t/src/android/net/NetworkStatsCollection.java +++ b/framework-t/src/android/net/NetworkStatsCollection.java @@ -776,7 +776,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W if (!templateMatches(groupTemplate, key.ident)) continue; if (key.set >= NetworkStats.SET_DEBUG_START) continue; - final Key groupKey = new Key(null, key.uid, key.set, key.tag); + final Key groupKey = new Key(new NetworkIdentitySet(), key.uid, key.set, key.tag); NetworkStatsHistory groupHistory = grouped.get(groupKey); if (groupHistory == null) { groupHistory = new NetworkStatsHistory(value.getBucketDuration()); diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp index 545f7b92e7..5b926de36d 100644 --- a/tests/unit/Android.bp +++ b/tests/unit/Android.bp @@ -63,6 +63,7 @@ filegroup { "java/android/net/IpSecManagerTest.java", "java/android/net/IpSecTransformTest.java", "java/android/net/KeepalivePacketDataUtilTest.java", + "java/android/net/NetworkIdentitySetTest.kt", "java/android/net/NetworkIdentityTest.kt", "java/android/net/NetworkStats*.java", "java/android/net/NetworkTemplateTest.kt", diff --git a/tests/unit/java/android/net/NetworkIdentitySetTest.kt b/tests/unit/java/android/net/NetworkIdentitySetTest.kt new file mode 100644 index 0000000000..d61ebf97be --- /dev/null +++ b/tests/unit/java/android/net/NetworkIdentitySetTest.kt @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net + +import android.content.Context +import android.net.ConnectivityManager.TYPE_MOBILE +import android.os.Build +import android.telephony.TelephonyManager +import com.android.testutils.DevSdkIgnoreRule +import com.android.testutils.DevSdkIgnoreRunner +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.mock +import kotlin.test.assertEquals + +private const val TEST_IMSI1 = "testimsi1" + +@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2) +@RunWith(DevSdkIgnoreRunner::class) +class NetworkIdentitySetTest { + private val mockContext = mock(Context::class.java) + + private fun buildMobileNetworkStateSnapshot( + caps: NetworkCapabilities, + subscriberId: String + ): NetworkStateSnapshot { + return NetworkStateSnapshot(mock(Network::class.java), caps, + LinkProperties(), subscriberId, TYPE_MOBILE) + } + + @Test + fun testCompare() { + val ident1 = NetworkIdentity.buildNetworkIdentity(mockContext, + buildMobileNetworkStateSnapshot(NetworkCapabilities(), TEST_IMSI1), + false /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS) + val ident2 = NetworkIdentity.buildNetworkIdentity(mockContext, + buildMobileNetworkStateSnapshot(NetworkCapabilities(), TEST_IMSI1), + true /* defaultNetwork */, TelephonyManager.NETWORK_TYPE_UMTS) + + // Verify that the results of comparing two empty sets are equal + assertEquals(0, NetworkIdentitySet.compare(NetworkIdentitySet(), NetworkIdentitySet())) + + val identSet1 = NetworkIdentitySet() + val identSet2 = NetworkIdentitySet() + identSet1.add(ident1) + identSet2.add(ident2) + assertEquals(-1, NetworkIdentitySet.compare(NetworkIdentitySet(), identSet1)) + assertEquals(1, NetworkIdentitySet.compare(identSet1, NetworkIdentitySet())) + assertEquals(0, NetworkIdentitySet.compare(identSet1, identSet1)) + assertEquals(-1, NetworkIdentitySet.compare(identSet1, identSet2)) + } +}