diff --git a/core/java/android/net/QosFilter.java b/core/java/android/net/QosFilter.java index 0705468781..ab55002e02 100644 --- a/core/java/android/net/QosFilter.java +++ b/core/java/android/net/QosFilter.java @@ -19,6 +19,8 @@ package android.net; import android.annotation.NonNull; import android.annotation.SystemApi; +import java.net.InetAddress; + /** * Provides the related filtering logic to the {@link NetworkAgent} to match {@link QosSession}s * to their related {@link QosCallback}. @@ -58,5 +60,16 @@ public abstract class QosFilter { */ @QosCallbackException.ExceptionType public abstract int validate(); + + /** + * Determines whether or not the parameters is a match for the filter. + * + * @param address the local address + * @param startPort the start of the port range + * @param endPort the end of the port range + * @return whether the parameters match the local address of the filter + */ + public abstract boolean matchesLocalAddress(@NonNull InetAddress address, + int startPort, int endPort); } diff --git a/core/java/android/net/QosSocketFilter.java b/core/java/android/net/QosSocketFilter.java index f51a0881e6..2080e68f5f 100644 --- a/core/java/android/net/QosSocketFilter.java +++ b/core/java/android/net/QosSocketFilter.java @@ -26,7 +26,10 @@ import android.system.ErrnoException; import android.system.Os; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + import java.io.FileDescriptor; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; @@ -125,4 +128,39 @@ public class QosSocketFilter extends QosFilter { public Network getNetwork() { return mQosSocketInfo.getNetwork(); } + + /** + * @inheritDoc + */ + @Override + public boolean matchesLocalAddress(@NonNull final InetAddress address, final int startPort, + final int endPort) { + if (mQosSocketInfo.getLocalSocketAddress() == null) { + return false; + } + + return matchesLocalAddress(mQosSocketInfo.getLocalSocketAddress(), address, startPort, + endPort); + } + + /** + * Called from {@link QosSocketFilter#matchesLocalAddress(InetAddress, int, int)} with the + * filterSocketAddress coming from {@link QosSocketInfo#getLocalSocketAddress()}. + *

+ * This method exists for testing purposes since {@link QosSocketInfo} couldn't be mocked + * due to being final. + * + * @param filterSocketAddress the socket address of the filter + * @param address the address to compare the filterSocketAddressWith + * @param startPort the start of the port range to check + * @param endPort the end of the port range to check + */ + @VisibleForTesting + public static boolean matchesLocalAddress(@NonNull final InetSocketAddress filterSocketAddress, + @NonNull final InetAddress address, + final int startPort, final int endPort) { + return startPort <= filterSocketAddress.getPort() + && endPort >= filterSocketAddress.getPort() + && filterSocketAddress.getAddress().equals(address); + } } diff --git a/tests/net/java/android/net/QosSocketFilterTest.java b/tests/net/java/android/net/QosSocketFilterTest.java new file mode 100644 index 0000000000..ad58960eaa --- /dev/null +++ b/tests/net/java/android/net/QosSocketFilterTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2020 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 static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.net.InetAddress; +import java.net.InetSocketAddress; + +@RunWith(AndroidJUnit4.class) +@androidx.test.filters.SmallTest +public class QosSocketFilterTest { + + @Test + public void testPortExactMatch() { + final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); + final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4"); + assertTrue(QosSocketFilter.matchesLocalAddress( + new InetSocketAddress(addressA, 10), addressB, 10, 10)); + + } + + @Test + public void testPortLessThanStart() { + final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); + final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4"); + assertFalse(QosSocketFilter.matchesLocalAddress( + new InetSocketAddress(addressA, 8), addressB, 10, 10)); + } + + @Test + public void testPortGreaterThanEnd() { + final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); + final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4"); + assertFalse(QosSocketFilter.matchesLocalAddress( + new InetSocketAddress(addressA, 18), addressB, 10, 10)); + } + + @Test + public void testPortBetweenStartAndEnd() { + final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); + final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4"); + assertTrue(QosSocketFilter.matchesLocalAddress( + new InetSocketAddress(addressA, 10), addressB, 8, 18)); + } + + @Test + public void testAddressesDontMatch() { + final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4"); + final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.5"); + assertFalse(QosSocketFilter.matchesLocalAddress( + new InetSocketAddress(addressA, 10), addressB, 10, 10)); + } +} +