Delete the LinkAddress in cache when RTM_DELADDR is received

The addOrUpdateInterfaceAddress() should be called when RTM_NEWADDR
message is received and the address isPreferred. The
deleteInterfaceAddress() should be called when RTM_DELADDR is called.

Bug: 282592527
Test: atest MdnsSocketProviderTest
Change-Id: I06a5940f53d01552f117309b1cc09256a2a9fae7
diff --git a/service-t/src/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitor.java b/service-t/src/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitor.java
index 40191cf..451909c 100644
--- a/service-t/src/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitor.java
+++ b/service-t/src/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitor.java
@@ -61,13 +61,11 @@
         final StructIfaddrMsg ifaddrMsg = msg.getIfaddrHeader();
         final LinkAddress la = new LinkAddress(msg.getIpAddress(), ifaddrMsg.prefixLen,
                 msg.getFlags(), ifaddrMsg.scope);
-        if (!la.isPreferred()) {
-            // Skip the unusable ip address.
-            return;
-        }
         switch (msg.getHeader().nlmsg_type) {
             case NetlinkConstants.RTM_NEWADDR:
-                mCb.addOrUpdateInterfaceAddress(ifaddrMsg.index, la);
+                if (la.isPreferred()) {
+                    mCb.addOrUpdateInterfaceAddress(ifaddrMsg.index, la);
+                }
                 break;
             case NetlinkConstants.RTM_DELADDR:
                 mCb.deleteInterfaceAddress(ifaddrMsg.index, la);
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitorTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitorTest.kt
new file mode 100644
index 0000000..c62a081
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/mdns/internal/SocketNetlinkMonitorTest.kt
@@ -0,0 +1,90 @@
+package com.android.server.connectivity.mdns.internal
+
+import android.net.LinkAddress
+import android.os.Build
+import android.os.Handler
+import android.os.HandlerThread
+import android.system.OsConstants
+import com.android.net.module.util.SharedLog
+import com.android.net.module.util.netlink.NetlinkConstants
+import com.android.net.module.util.netlink.RtNetlinkAddressMessage
+import com.android.net.module.util.netlink.StructIfaddrMsg
+import com.android.net.module.util.netlink.StructNlMsgHdr
+import com.android.server.connectivity.mdns.MdnsAdvertiserTest
+import com.android.server.connectivity.mdns.MdnsSocketProvider
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mockito
+import org.mockito.Mockito.argThat
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+
+private val LINKADDRV4 = LinkAddress("192.0.2.0/24")
+private val IFACE_IDX = 32
+
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
+internal class SocketNetlinkMonitorTest {
+    private val thread = HandlerThread(MdnsAdvertiserTest::class.simpleName)
+    private val sharedlog = Mockito.mock(SharedLog::class.java)
+    private val netlinkMonitorCallBack =
+            Mockito.mock(MdnsSocketProvider.NetLinkMonitorCallBack::class.java)
+
+    @Before
+    fun setUp() {
+        thread.start()
+    }
+
+    @After
+    fun tearDown() {
+        thread.quitSafely()
+    }
+
+    @Test
+    fun testHandleDeprecatedNetlinkMessage() {
+        val socketNetlinkMonitor = SocketNetlinkMonitor(Handler(thread.looper), sharedlog,
+                netlinkMonitorCallBack)
+        val nlmsghdr = StructNlMsgHdr().apply {
+            nlmsg_type = NetlinkConstants.RTM_NEWADDR
+            nlmsg_flags = (StructNlMsgHdr.NLM_F_REQUEST.toInt()
+                    or StructNlMsgHdr.NLM_F_ACK.toInt()).toShort()
+            nlmsg_seq = 1
+        }
+        val structIfaddrMsg = StructIfaddrMsg(OsConstants.AF_INET.toShort(),
+                LINKADDRV4.prefixLength.toShort(),
+                LINKADDRV4.flags.toShort(),
+                LINKADDRV4.scope.toShort(), IFACE_IDX)
+        // If the LinkAddress is not preferred, RTM_NEWADDR will not trigger
+        // addOrUpdateInterfaceAddress() callback.
+        val deprecatedAddNetLinkMessage = RtNetlinkAddressMessage(nlmsghdr, structIfaddrMsg,
+            LINKADDRV4.address, null /* structIfacacheInfo */,
+            LINKADDRV4.flags or OsConstants.IFA_F_DEPRECATED)
+        socketNetlinkMonitor.processNetlinkMessage(deprecatedAddNetLinkMessage, 0L /* whenMs */)
+        verify(netlinkMonitorCallBack, never()).addOrUpdateInterfaceAddress(eq(IFACE_IDX),
+                 argThat { it.address == LINKADDRV4.address })
+
+        // If the LinkAddress is preferred, RTM_NEWADDR will trigger addOrUpdateInterfaceAddress()
+        // callback.
+        val preferredAddNetLinkMessage = RtNetlinkAddressMessage(nlmsghdr, structIfaddrMsg,
+            LINKADDRV4.address, null /* structIfacacheInfo */,
+            LINKADDRV4.flags or OsConstants.IFA_F_OPTIMISTIC)
+        socketNetlinkMonitor.processNetlinkMessage(preferredAddNetLinkMessage, 0L /* whenMs */)
+        verify(netlinkMonitorCallBack).addOrUpdateInterfaceAddress(eq(IFACE_IDX),
+            argThat { it.address == LINKADDRV4.address })
+
+        // Even if the LinkAddress is not preferred, RTM_DELADDR will trigger
+        // deleteInterfaceAddress() callback.
+        nlmsghdr.nlmsg_type = NetlinkConstants.RTM_DELADDR
+        val deprecatedDelNetLinkMessage = RtNetlinkAddressMessage(nlmsghdr, structIfaddrMsg,
+            LINKADDRV4.address, null /* structIfacacheInfo */,
+            LINKADDRV4.flags or OsConstants.IFA_F_DEPRECATED)
+        socketNetlinkMonitor.processNetlinkMessage(deprecatedDelNetLinkMessage, 0L /* whenMs */)
+        verify(netlinkMonitorCallBack).deleteInterfaceAddress(eq(IFACE_IDX),
+                argThat { it.address == LINKADDRV4.address })
+    }
+}