Merge "netd.c - cleanup AID_CLAT handling"
diff --git a/framework/src/android/net/LinkProperties.java b/framework/src/android/net/LinkProperties.java
index 4f7ac30..9fb9bc6 100644
--- a/framework/src/android/net/LinkProperties.java
+++ b/framework/src/android/net/LinkProperties.java
@@ -1456,8 +1456,13 @@
      * @hide
      */
     public boolean isIdenticalPcscfs(@NonNull LinkProperties target) {
-        // list order is important, compare one by one
-        return target.getPcscfServers().equals(mPcscfs);
+        // Per 3GPP TS 24.229, B.2.2.1 PDP context activation and P-CSCF discovery
+        // list order is important, so on U+ compare one by one
+        if (SdkLevel.isAtLeastU()) return target.getPcscfServers().equals(mPcscfs);
+        // but for safety old behaviour on pre-U:
+        Collection<InetAddress> targetPcscfs = target.getPcscfServers();
+        return (mPcscfs.size() == targetPcscfs.size()) ?
+                    mPcscfs.containsAll(targetPcscfs) : false;
     }
 
     /**
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/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
index e2ef981..f8285ed 100644
--- a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
@@ -210,8 +210,12 @@
             this.mKi = Objects.requireNonNull(ki);
             mCallback = ki.mCallback;
             mUnderpinnedNetwork = underpinnedNetwork;
-            if (autoOnOff && mDependencies.isFeatureEnabled(AUTOMATIC_ON_OFF_KEEPALIVE_VERSION,
-                    true /* defaultEnabled */)) {
+            // Reading DeviceConfig will check if the calling uid and calling package name are the
+            // same. Clear calling identity to align the calling uid and package
+            final boolean enabled = BinderUtils.withCleanCallingIdentity(
+                    () -> mDependencies.isFeatureEnabled(AUTOMATIC_ON_OFF_KEEPALIVE_VERSION,
+                            true /* defaultEnabled */));
+            if (autoOnOff && enabled) {
                 mAutomaticOnOffState = STATE_ENABLED;
                 if (null == ki.mFd) {
                     throw new IllegalArgumentException("fd can't be null with automatic "
@@ -583,8 +587,12 @@
      */
     public void dump(IndentingPrintWriter pw) {
         mKeepaliveTracker.dump(pw);
-        final boolean featureEnabled = mDependencies.isFeatureEnabled(
-                AUTOMATIC_ON_OFF_KEEPALIVE_VERSION, true /* defaultEnabled */);
+        // Reading DeviceConfig will check if the calling uid and calling package name are the same.
+        // Clear calling identity to align the calling uid and package so that it won't fail if cts
+        // would like to call dump()
+        final boolean featureEnabled = BinderUtils.withCleanCallingIdentity(
+                () -> mDependencies.isFeatureEnabled(AUTOMATIC_ON_OFF_KEEPALIVE_VERSION,
+                        true /* defaultEnabled */));
         pw.println("AutomaticOnOff enabled: " + featureEnabled);
         pw.increaseIndent();
         for (AutomaticOnOffKeepalive autoKi : mAutomaticOnOffKeepalives) {
@@ -837,12 +845,8 @@
          * @return whether the feature is enabled
          */
         public boolean isFeatureEnabled(@NonNull final String name, final boolean defaultEnabled) {
-            // Reading DeviceConfig will check if the calling uid and calling package name are the
-            // same. Clear calling identity to align the calling uid and package so that it won't
-            // fail if cts would like to do the dump()
-            return BinderUtils.withCleanCallingIdentity(() ->
-                    DeviceConfigUtils.isFeatureEnabled(mContext, NAMESPACE_TETHERING, name,
-                    DeviceConfigUtils.TETHERING_MODULE_NAME, defaultEnabled));
+            return DeviceConfigUtils.isFeatureEnabled(mContext, NAMESPACE_TETHERING, name,
+                    DeviceConfigUtils.TETHERING_MODULE_NAME, defaultEnabled);
         }
 
         /**
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 })
+    }
+}