Merge "LinkProperties: use ordered comparison for P-CSCFs - only on U+"
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index c15b85e..bd8b325 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -2988,9 +2988,9 @@
         final MacAddress testMac1 = MacAddress.fromString("11:11:11:11:11:11");
         final DhcpLeaseParcelable p2pLease = createDhcpLeaseParcelable("clientId1", testMac1,
                 "192.168.50.24", 24, Long.MAX_VALUE, "test1");
-        final List<TetheredClient> p2pClients = notifyDhcpLeasesChanged(TETHERING_WIFI_P2P,
+        final List<TetheredClient> connectedClients = notifyDhcpLeasesChanged(TETHERING_WIFI_P2P,
                 eventCallbacks, p2pLease);
-        callback.expectTetheredClientChanged(p2pClients);
+        callback.expectTetheredClientChanged(connectedClients);
         reset(mDhcpServer);
 
         // Run wifi tethering.
@@ -2999,21 +2999,11 @@
         verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS)).startWithCallbacks(
                 any(), dhcpEventCbsCaptor.capture());
         eventCallbacks = dhcpEventCbsCaptor.getValue();
-        // Update mac address from softAp callback before getting dhcp lease.
         final MacAddress testMac2 = MacAddress.fromString("22:22:22:22:22:22");
-        final TetheredClient noAddrClient = notifyConnectedWifiClientsChanged(testMac2,
-                false /* isLocalOnly */);
-        final List<TetheredClient> p2pAndNoAddrClients = new ArrayList<>(p2pClients);
-        p2pAndNoAddrClients.add(noAddrClient);
-        callback.expectTetheredClientChanged(p2pAndNoAddrClients);
-
-        // Update dhcp lease for wifi tethering.
         final DhcpLeaseParcelable wifiLease = createDhcpLeaseParcelable("clientId2", testMac2,
                 "192.168.43.24", 24, Long.MAX_VALUE, "test2");
-        final List<TetheredClient> p2pAndWifiClients = new ArrayList<>(p2pClients);
-        p2pAndWifiClients.addAll(notifyDhcpLeasesChanged(TETHERING_WIFI,
-                eventCallbacks, wifiLease));
-        callback.expectTetheredClientChanged(p2pAndWifiClients);
+        verifyHotspotClientUpdate(false /* isLocalOnly */, testMac2, wifiLease, connectedClients,
+                eventCallbacks, callback);
 
         // Test onStarted callback that register second callback when tethering is running.
         TestTetheringEventCallback callback2 = new TestTetheringEventCallback();
@@ -3021,7 +3011,7 @@
             mTethering.registerTetheringEventCallback(callback2);
             mLooper.dispatchAll();
         });
-        callback2.expectTetheredClientChanged(p2pAndWifiClients);
+        callback2.expectTetheredClientChanged(connectedClients);
     }
 
     @Test
@@ -3043,26 +3033,34 @@
         verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS)).startWithCallbacks(
                 any(), dhcpEventCbsCaptor.capture());
         final IDhcpEventCallbacks eventCallbacks = dhcpEventCbsCaptor.getValue();
-        // Update mac address from softAp callback before getting dhcp lease.
-        final MacAddress testMac = MacAddress.fromString("22:22:22:22:22:22");
-        final TetheredClient noAddrClient = notifyConnectedWifiClientsChanged(testMac,
-                true /* isLocalOnly */);
-        final List<TetheredClient> noAddrLocalOnlyClients = new ArrayList<>();
-        noAddrLocalOnlyClients.add(noAddrClient);
-        callback.expectTetheredClientChanged(noAddrLocalOnlyClients);
 
-        // Update dhcp lease for local only hotspot.
+        final List<TetheredClient> connectedClients = new ArrayList<>();
+        final MacAddress testMac = MacAddress.fromString("22:22:22:22:22:22");
         final DhcpLeaseParcelable wifiLease = createDhcpLeaseParcelable("clientId", testMac,
                 "192.168.43.24", 24, Long.MAX_VALUE, "test");
-        final List<TetheredClient> localOnlyClients = notifyDhcpLeasesChanged(TETHERING_WIFI,
-                eventCallbacks, wifiLease);
-        callback.expectTetheredClientChanged(localOnlyClients);
+        verifyHotspotClientUpdate(true /* isLocalOnly */, testMac, wifiLease, connectedClients,
+                eventCallbacks, callback);
 
         // Client disconnect from local only hotspot.
         mLocalOnlyHotspotCallback.onConnectedClientsChanged(Collections.emptyList());
         callback.expectTetheredClientChanged(Collections.emptyList());
     }
 
+    private void verifyHotspotClientUpdate(final boolean isLocalOnly, final MacAddress testMac,
+            final DhcpLeaseParcelable dhcpLease, final List<TetheredClient> currentClients,
+            final IDhcpEventCallbacks dhcpCallback, final TestTetheringEventCallback callback)
+            throws Exception {
+        // Update mac address from softAp callback before getting dhcp lease.
+        final TetheredClient noAddrClient = notifyConnectedWifiClientsChanged(testMac, isLocalOnly);
+        final List<TetheredClient> withNoAddrClients = new ArrayList<>(currentClients);
+        withNoAddrClients.add(noAddrClient);
+        callback.expectTetheredClientChanged(withNoAddrClients);
+
+        // Update dhcp lease for hotspot.
+        currentClients.addAll(notifyDhcpLeasesChanged(TETHERING_WIFI, dhcpCallback, dhcpLease));
+        callback.expectTetheredClientChanged(currentClients);
+    }
+
     private TetheredClient notifyConnectedWifiClientsChanged(final MacAddress mac,
             boolean isLocalOnly) throws Exception {
         final ArrayList<WifiClient> wifiClients = new ArrayList<>();
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index e6ffecd..f05cebe 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -387,6 +387,7 @@
 import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
 import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
 import com.android.server.ConnectivityService.NetworkRequestInfo;
+import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.DestroySocketsWrapper;
 import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.ReportedInterfaces;
 import com.android.server.connectivity.ApplicationSelfCertifiedNetworkCapabilities;
 import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker;
@@ -615,6 +616,7 @@
     @Mock TetheringManager mTetheringManager;
     @Mock BroadcastOptionsShim mBroadcastOptionsShim;
     @Mock ActivityManager mActivityManager;
+    @Mock DestroySocketsWrapper mDestroySocketsWrapper;
 
     // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the
     // underlying binder calls.
@@ -1865,7 +1867,7 @@
         final Context mockResContext = mock(Context.class);
         doReturn(mResources).when(mockResContext).getResources();
         ConnectivityResources.setResourcesContextForTest(mockResContext);
-        mDeps = spy(new ConnectivityServiceDependencies(mockResContext));
+        mDeps = new ConnectivityServiceDependencies(mockResContext);
         mAutoOnOffKeepaliveDependencies =
                 new AutomaticOnOffKeepaliveTrackerDependencies(mServiceContext);
         mService = new ConnectivityService(mServiceContext,
@@ -1928,8 +1930,7 @@
                 R.integer.config_networkWakeupPacketMark);
     }
 
-    // ConnectivityServiceDependencies is public to use Mockito.spy
-    public class ConnectivityServiceDependencies extends ConnectivityService.Dependencies {
+    class ConnectivityServiceDependencies extends ConnectivityService.Dependencies {
         final ConnectivityResources mConnRes;
 
         ConnectivityServiceDependencies(final Context mockResContext) {
@@ -2168,15 +2169,24 @@
             }
         }
 
-        @Override
-        public void destroyLiveTcpSockets(final Set<Range<Integer>> ranges,
-                final Set<Integer> exemptUids) {
-            // This function is empty since the invocation of this method is verified by mocks
+        // Class to be mocked and used to verify destroy sockets methods call
+        public class DestroySocketsWrapper {
+            public void destroyLiveTcpSockets(final Set<Range<Integer>> ranges,
+                    final Set<Integer> exemptUids){}
+            public void destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids){}
         }
 
-        @Override
+        @Override @SuppressWarnings("DirectInvocationOnMock")
+        public void destroyLiveTcpSockets(final Set<Range<Integer>> ranges,
+                final Set<Integer> exemptUids) {
+            // Call mocked destroyLiveTcpSockets so that test can verify this method call
+            mDestroySocketsWrapper.destroyLiveTcpSockets(ranges, exemptUids);
+        }
+
+        @Override @SuppressWarnings("DirectInvocationOnMock")
         public void destroyLiveTcpSocketsByOwnerUids(final Set<Integer> ownerUids) {
-            // This function is empty since the invocation of this method is verified by mocks
+            // Call mocked destroyLiveTcpSocketsByOwnerUids so that test can verify this method call
+            mDestroySocketsWrapper.destroyLiveTcpSocketsByOwnerUids(ownerUids);
         }
     }
 
@@ -10276,7 +10286,7 @@
 
     private void doTestSetFirewallChainEnabledCloseSocket(final int chain,
             final boolean isAllowList) throws Exception {
-        reset(mDeps);
+        reset(mDestroySocketsWrapper);
 
         mCm.setFirewallChainEnabled(chain, true /* enabled */);
         final Set<Integer> uids =
@@ -10284,13 +10294,13 @@
         if (isAllowList) {
             final Set<Range<Integer>> range = new ArraySet<>(
                     List.of(new Range<>(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE)));
-            verify(mDeps).destroyLiveTcpSockets(range, uids);
+            verify(mDestroySocketsWrapper).destroyLiveTcpSockets(range, uids);
         } else {
-            verify(mDeps).destroyLiveTcpSocketsByOwnerUids(uids);
+            verify(mDestroySocketsWrapper).destroyLiveTcpSocketsByOwnerUids(uids);
         }
 
         mCm.setFirewallChainEnabled(chain, false /* enabled */);
-        verifyNoMoreInteractions(mDeps);
+        verifyNoMoreInteractions(mDestroySocketsWrapper);
     }
 
     @Test @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
@@ -12627,11 +12637,11 @@
 
     private void assertVpnUidRangesUpdated(boolean add, Set<UidRange> vpnRanges, int exemptUid)
             throws Exception {
-        InOrder inOrder = inOrder(mMockNetd, mDeps);
+        InOrder inOrder = inOrder(mMockNetd, mDestroySocketsWrapper);
         final Set<Integer> exemptUidSet = new ArraySet<>(List.of(exemptUid, Process.VPN_UID));
 
-        inOrder.verify(mDeps).destroyLiveTcpSockets(UidRange.toIntRanges(vpnRanges),
-                exemptUidSet);
+        inOrder.verify(mDestroySocketsWrapper).destroyLiveTcpSockets(
+                UidRange.toIntRanges(vpnRanges), exemptUidSet);
 
         if (add) {
             inOrder.verify(mMockNetd, times(1)).networkAddUidRangesParcel(
@@ -12643,8 +12653,8 @@
                             toUidRangeStableParcels(vpnRanges), PREFERENCE_ORDER_VPN));
         }
 
-        inOrder.verify(mDeps).destroyLiveTcpSockets(UidRange.toIntRanges(vpnRanges),
-                exemptUidSet);
+        inOrder.verify(mDestroySocketsWrapper).destroyLiveTcpSockets(
+                UidRange.toIntRanges(vpnRanges), exemptUidSet);
     }
 
     @Test
@@ -17984,7 +17994,7 @@
         final UidRange frozenUidRange = new UidRange(TEST_FROZEN_UID, TEST_FROZEN_UID);
         final Set<UidRange> ranges = Collections.singleton(frozenUidRange);
 
-        verify(mDeps).destroyLiveTcpSockets(eq(UidRange.toIntRanges(ranges)),
+        verify(mDestroySocketsWrapper).destroyLiveTcpSockets(eq(UidRange.toIntRanges(ranges)),
                 eq(exemptUids));
     }