Check network slicing declaration for network request
When the application wants to request network with
NET_CAPABILITY_PRIORITIZE_BANDWIDTH or
NET_CAPABILITY_PRIORITIZE_LATENCY, it has to declare
PackageManager.PROPERTY_NETWORK_SLICE_DECLARATIONS property and also
adds the declaration in a separate XML files. Otherwise, the request
will fail with a SecurityException being thrown.
Test: atest FrameworksNetTests CtsNetTestCases
Bug: 266524688
Change-Id: I6affc857b803211517368da288e1b2fdc06a955b
diff --git a/tests/cts/hostside/Android.bp b/tests/cts/hostside/Android.bp
index ff9bd31..891c2dd 100644
--- a/tests/cts/hostside/Android.bp
+++ b/tests/cts/hostside/Android.bp
@@ -47,6 +47,9 @@
data: [
":CtsHostsideNetworkTestsApp",
":CtsHostsideNetworkTestsApp2",
+ ":CtsHostsideNetworkCapTestsAppWithoutProperty",
+ ":CtsHostsideNetworkCapTestsAppWithProperty",
+ ":CtsHostsideNetworkCapTestsAppSdk33",
] + next_app_data,
per_testcase_directory: true,
}
diff --git a/tests/cts/hostside/networkslicingtestapp/Android.bp b/tests/cts/hostside/networkslicingtestapp/Android.bp
new file mode 100644
index 0000000..2aa3f69
--- /dev/null
+++ b/tests/cts/hostside/networkslicingtestapp/Android.bp
@@ -0,0 +1,65 @@
+//
+// Copyright (C) 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_defaults {
+ name: "CtsHostsideNetworkCapTestsAppDefaults",
+ platform_apis: true,
+ static_libs: [
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "modules-utils-build",
+ "cts-net-utils",
+ ],
+ srcs: ["src/**/*.java"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "sts",
+ ],
+}
+
+android_test_helper_app {
+ name: "CtsHostsideNetworkCapTestsAppWithoutProperty",
+ defaults: [
+ "cts_support_defaults",
+ "CtsHostsideNetworkCapTestsAppDefaults"
+ ],
+ manifest: "AndroidManifestWithoutProperty.xml",
+}
+
+android_test_helper_app {
+ name: "CtsHostsideNetworkCapTestsAppWithProperty",
+ defaults: [
+ "cts_support_defaults",
+ "CtsHostsideNetworkCapTestsAppDefaults"
+ ],
+ manifest: "AndroidManifestWithProperty.xml",
+}
+
+android_test_helper_app {
+ name: "CtsHostsideNetworkCapTestsAppSdk33",
+ defaults: [
+ "cts_support_defaults",
+ "CtsHostsideNetworkCapTestsAppDefaults"
+ ],
+ target_sdk_version: "33",
+ manifest: "AndroidManifestWithoutProperty.xml",
+}
diff --git a/tests/cts/hostside/networkslicingtestapp/AndroidManifestWithProperty.xml b/tests/cts/hostside/networkslicingtestapp/AndroidManifestWithProperty.xml
new file mode 100644
index 0000000..3ef0376
--- /dev/null
+++ b/tests/cts/hostside/networkslicingtestapp/AndroidManifestWithProperty.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2023 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.net.hostside.networkslicingtestapp">
+
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+
+ <application>
+ <uses-library android:name="android.test.runner"/>
+ <property android:name="android.net.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES"
+ android:resource="@xml/self_certified_network_capabilities_both" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.net.hostside.networkslicingtestapp"/>
+
+</manifest>
diff --git a/tests/cts/hostside/networkslicingtestapp/AndroidManifestWithoutProperty.xml b/tests/cts/hostside/networkslicingtestapp/AndroidManifestWithoutProperty.xml
new file mode 100644
index 0000000..fe66684
--- /dev/null
+++ b/tests/cts/hostside/networkslicingtestapp/AndroidManifestWithoutProperty.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2023 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.cts.net.hostside.networkslicingtestapp">
+
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+
+ <application>
+ <uses-library android:name="android.test.runner"/>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.net.hostside.networkslicingtestapp"/>
+
+</manifest>
diff --git a/tests/cts/hostside/networkslicingtestapp/res/xml/self_certified_network_capabilities_both.xml b/tests/cts/hostside/networkslicingtestapp/res/xml/self_certified_network_capabilities_both.xml
new file mode 100644
index 0000000..4066be2
--- /dev/null
+++ b/tests/cts/hostside/networkslicingtestapp/res/xml/self_certified_network_capabilities_both.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_BANDWIDTH"/>
+</network-capabilities-declaration>
diff --git a/tests/cts/hostside/networkslicingtestapp/src/com.android.cts.net.hostside.networkslicingtestapp/NetworkSelfDeclaredCapabilitiesTest.java b/tests/cts/hostside/networkslicingtestapp/src/com.android.cts.net.hostside.networkslicingtestapp/NetworkSelfDeclaredCapabilitiesTest.java
new file mode 100644
index 0000000..39792fc
--- /dev/null
+++ b/tests/cts/hostside/networkslicingtestapp/src/com.android.cts.net.hostside.networkslicingtestapp/NetworkSelfDeclaredCapabilitiesTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 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 com.android.cts.net.hostside.networkslicingtestapp;
+
+import static org.junit.Assert.assertThrows;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.os.Build;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class NetworkSelfDeclaredCapabilitiesTest {
+
+ @Rule
+ public final DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule();
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ public void requestNetwork_withoutRequestCapabilities() {
+ final ConnectivityManager cm =
+ (ConnectivityManager)
+ InstrumentationRegistry.getInstrumentation()
+ .getContext()
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ final NetworkRequest request =
+ new NetworkRequest.Builder().build();
+ final ConnectivityManager.NetworkCallback callback =
+ new ConnectivityManager.NetworkCallback();
+ cm.requestNetwork(request, callback);
+ cm.unregisterNetworkCallback(callback);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ public void requestNetwork_withSelfDeclaredCapabilities() {
+ final ConnectivityManager cm =
+ (ConnectivityManager)
+ InstrumentationRegistry.getInstrumentation()
+ .getContext()
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ final NetworkRequest request =
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .build();
+ final ConnectivityManager.NetworkCallback callback =
+ new ConnectivityManager.NetworkCallback();
+ cm.requestNetwork(request, callback);
+ cm.unregisterNetworkCallback(callback);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ public void requestNetwork_lackingRequiredSelfDeclaredCapabilities() {
+ final ConnectivityManager cm =
+ (ConnectivityManager)
+ InstrumentationRegistry.getInstrumentation()
+ .getContext()
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ final NetworkRequest request =
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .build();
+ final ConnectivityManager.NetworkCallback callback =
+ new ConnectivityManager.NetworkCallback();
+ assertThrows(
+ SecurityException.class,
+ () -> cm.requestNetwork(request, callback));
+ }
+
+}
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideSelfDeclaredNetworkCapabilitiesCheckTest.java b/tests/cts/hostside/src/com/android/cts/net/HostsideSelfDeclaredNetworkCapabilitiesCheckTest.java
new file mode 100644
index 0000000..4c2985d
--- /dev/null
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideSelfDeclaredNetworkCapabilitiesCheckTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 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 com.android.cts.net;
+
+public class HostsideSelfDeclaredNetworkCapabilitiesCheckTest extends HostsideNetworkTestCase {
+
+ private static final String TEST_WITH_PROPERTY_IN_CURRENT_SDK_APK =
+ "CtsHostsideNetworkCapTestsAppWithProperty.apk";
+ private static final String TEST_WITHOUT_PROPERTY_IN_CURRENT_SDK_APK =
+ "CtsHostsideNetworkCapTestsAppWithoutProperty.apk";
+ private static final String TEST_IN_SDK_33_APK =
+ "CtsHostsideNetworkCapTestsAppSdk33.apk";
+ private static final String TEST_APP_PKG =
+ "com.android.cts.net.hostside.networkslicingtestapp";
+ private static final String TEST_CLASS_NAME = ".NetworkSelfDeclaredCapabilitiesTest";
+ private static final String WITH_SELF_DECLARED_CAPABILITIES_METHOD =
+ "requestNetwork_withSelfDeclaredCapabilities";
+ private static final String LACKING_SELF_DECLARED_CAPABILITIES_METHOD =
+ "requestNetwork_lackingRequiredSelfDeclaredCapabilities";
+ private static final String WITHOUT_REQUEST_CAPABILITIES_METHOD =
+ "requestNetwork_withoutRequestCapabilities";
+
+
+ public void testRequestNetworkInCurrentSdkWithProperty() throws Exception {
+ uninstallPackage(TEST_APP_PKG, false);
+ installPackage(TEST_WITH_PROPERTY_IN_CURRENT_SDK_APK);
+ // If the self-declared capabilities are defined,
+ // the ConnectivityManager.requestNetwork() call should always pass.
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ WITH_SELF_DECLARED_CAPABILITIES_METHOD);
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ WITHOUT_REQUEST_CAPABILITIES_METHOD);
+ uninstallPackage(TEST_APP_PKG, true);
+ }
+
+ public void testRequestNetworkInCurrentSdkWithoutProperty() throws Exception {
+ uninstallPackage(TEST_APP_PKG, false);
+ installPackage(TEST_WITHOUT_PROPERTY_IN_CURRENT_SDK_APK);
+ // If the self-declared capabilities are not defined,
+ // the ConnectivityManager.requestNetwork() call will fail if the properly is not declared.
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ LACKING_SELF_DECLARED_CAPABILITIES_METHOD);
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ WITHOUT_REQUEST_CAPABILITIES_METHOD);
+ uninstallPackage(TEST_APP_PKG, true);
+ }
+
+ public void testRequestNetworkInSdk33() throws Exception {
+ uninstallPackage(TEST_APP_PKG, false);
+ installPackage(TEST_IN_SDK_33_APK);
+ // In Sdk33, the ConnectivityManager.requestNetwork() call should always pass.
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ WITH_SELF_DECLARED_CAPABILITIES_METHOD);
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ WITHOUT_REQUEST_CAPABILITIES_METHOD);
+ uninstallPackage(TEST_APP_PKG, true);
+ }
+
+ public void testReinstallPackageWillUpdateProperty() throws Exception {
+ uninstallPackage(TEST_APP_PKG, false);
+ installPackage(TEST_WITHOUT_PROPERTY_IN_CURRENT_SDK_APK);
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ LACKING_SELF_DECLARED_CAPABILITIES_METHOD);
+ uninstallPackage(TEST_APP_PKG, true);
+
+
+ // Updates package.
+ installPackage(TEST_WITH_PROPERTY_IN_CURRENT_SDK_APK);
+ runDeviceTests(TEST_APP_PKG,
+ TEST_APP_PKG + TEST_CLASS_NAME,
+ WITH_SELF_DECLARED_CAPABILITIES_METHOD);
+ uninstallPackage(TEST_APP_PKG, true);
+
+ }
+}
+
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 5b98237..1a358b2 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -183,6 +183,8 @@
import static com.android.testutils.RecorderCallback.CallbackEntry.UNAVAILABLE;
import static com.android.testutils.TestPermissionUtil.runAsShell;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -228,6 +230,7 @@
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.app.usage.NetworkStatsManager;
+import android.compat.testing.PlatformCompatChangeRule;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProvider;
@@ -312,6 +315,7 @@
import android.net.Uri;
import android.net.VpnManager;
import android.net.VpnTransportInfo;
+import android.net.connectivity.ConnectivityCompatChanges;
import android.net.metrics.IpConnectivityLog;
import android.net.netd.aidl.NativeUidRangeConfig;
import android.net.networkstack.NetworkStackClientBase;
@@ -379,6 +383,7 @@
import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
import com.android.server.ConnectivityService.NetworkRequestInfo;
import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.ReportedInterfaces;
+import com.android.server.connectivity.ApplicationSelfCertifiedNetworkCapabilities;
import com.android.server.connectivity.AutomaticOnOffKeepaliveTracker;
import com.android.server.connectivity.CarrierPrivilegeAuthenticator;
import com.android.server.connectivity.ClatCoordinator;
@@ -406,6 +411,9 @@
import com.android.testutils.TestableNetworkCallback;
import com.android.testutils.TestableNetworkOfferCallback;
+import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -475,6 +483,9 @@
@Rule
public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+ @Rule
+ public final PlatformCompatChangeRule compatChangeRule = new PlatformCompatChangeRule();
+
private static final int TIMEOUT_MS = 2_000;
// Broadcasts can take a long time to be delivered. The test will not wait for that long unless
// there is a failure, so use a long timeout.
@@ -2105,6 +2116,37 @@
reset(mBroadcastOptionsShim);
return mBroadcastOptionsShim;
}
+
+ @GuardedBy("this")
+ private boolean mForceDisableCompatChangeCheck = true;
+
+ /**
+ * By default, the {@link #isChangeEnabled(long, String, UserHandle)} will always return
+ * true as the mForceDisableCompatChangeCheck is true and compat change check logic is
+ * never executed. The compat change check logic can be turned on by calling this method.
+ * If this method is called, the
+ * {@link libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges} or
+ * {@link libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges} must be
+ * used to turn on/off the compat change flag.
+ */
+ private void enableCompatChangeCheck() {
+ synchronized (this) {
+ mForceDisableCompatChangeCheck = false;
+ }
+ }
+
+ @Override
+ public boolean isChangeEnabled(long changeId,
+ @NonNull final String packageName,
+ @NonNull final UserHandle user) {
+ synchronized (this) {
+ if (mForceDisableCompatChangeCheck) {
+ return false;
+ } else {
+ return super.isChangeEnabled(changeId, packageName, user);
+ }
+ }
+ }
}
private class AutomaticOnOffKeepaliveTrackerDependencies
@@ -6310,6 +6352,142 @@
}
}
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @DisableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
+ public void testSelfCertifiedCapabilitiesDisabled()
+ throws Exception {
+ mDeps.enableCompatChangeCheck();
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .build();
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ mCm.requestNetwork(networkRequest, cb);
+ mCm.unregisterNetworkCallback(cb);
+ }
+
+ /** Set the networkSliceResourceId to 0 will result in NameNotFoundException be thrown. */
+ private void setupMockForNetworkCapabilitiesResources(int networkSliceResourceId)
+ throws PackageManager.NameNotFoundException {
+ if (networkSliceResourceId == 0) {
+ doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getProperty(
+ ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
+ mContext.getPackageName());
+ } else {
+ final PackageManager.Property property = new PackageManager.Property(
+ ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
+ networkSliceResourceId,
+ true /* isResource */,
+ mContext.getPackageName(),
+ "dummyClass"
+ );
+ doReturn(property).when(mPackageManager).getProperty(
+ ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
+ mContext.getPackageName());
+ doReturn(mContext.getResources()).when(mPackageManager).getResourcesForApplication(
+ mContext.getPackageName());
+ }
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
+ public void requestNetwork_withoutPrioritizeBandwidthDeclaration_shouldThrowException()
+ throws Exception {
+ mDeps.enableCompatChangeCheck();
+ setupMockForNetworkCapabilitiesResources(
+ com.android.frameworks.tests.net.R.xml.self_certified_capabilities_latency);
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .build();
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ final Exception e = assertThrows(SecurityException.class,
+ () -> mCm.requestNetwork(networkRequest, cb));
+ assertThat(e.getMessage(),
+ containsString(ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_BANDWIDTH));
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
+ public void requestNetwork_withoutPrioritizeLatencyDeclaration_shouldThrowException()
+ throws Exception {
+ mDeps.enableCompatChangeCheck();
+ setupMockForNetworkCapabilitiesResources(
+ com.android.frameworks.tests.net.R.xml.self_certified_capabilities_bandwidth);
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .build();
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ final Exception e = assertThrows(SecurityException.class,
+ () -> mCm.requestNetwork(networkRequest, cb));
+ assertThat(e.getMessage(),
+ containsString(ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_LATENCY));
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
+ public void requestNetwork_withoutNetworkSliceProperty_shouldThrowException() throws Exception {
+ mDeps.enableCompatChangeCheck();
+ setupMockForNetworkCapabilitiesResources(0 /* networkSliceResourceId */);
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .build();
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ final Exception e = assertThrows(SecurityException.class,
+ () -> mCm.requestNetwork(networkRequest, cb));
+ assertThat(e.getMessage(),
+ containsString(ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES));
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
+ public void requestNetwork_withNetworkSliceDeclaration_shouldSucceed() throws Exception {
+ mDeps.enableCompatChangeCheck();
+ setupMockForNetworkCapabilitiesResources(
+ com.android.frameworks.tests.net.R.xml.self_certified_capabilities_both);
+
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .build();
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ mCm.requestNetwork(networkRequest, cb);
+ mCm.unregisterNetworkCallback(cb);
+ }
+
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ @EnableCompatChanges(ConnectivityCompatChanges.ENABLE_SELF_CERTIFIED_CAPABILITIES_DECLARATION)
+ public void requestNetwork_withNetworkSliceDeclaration_shouldUseCache() throws Exception {
+ mDeps.enableCompatChangeCheck();
+ setupMockForNetworkCapabilitiesResources(
+ com.android.frameworks.tests.net.R.xml.self_certified_capabilities_both);
+
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ .build();
+ final TestNetworkCallback cb = new TestNetworkCallback();
+ mCm.requestNetwork(networkRequest, cb);
+ mCm.unregisterNetworkCallback(cb);
+
+ // Second call should use caches
+ mCm.requestNetwork(networkRequest, cb);
+ mCm.unregisterNetworkCallback(cb);
+
+ // PackageManager's API only called once because the second call is using cache.
+ verify(mPackageManager, times(1)).getProperty(
+ ConstantsShim.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES,
+ mContext.getPackageName());
+ verify(mPackageManager, times(1)).getResourcesForApplication(
+ mContext.getPackageName());
+ }
+
/**
* Validate the service throws if request with CBS but without carrier privilege.
*/
diff --git a/tests/unit/java/com/android/server/connectivity/ApplicationSelfCertifiedNetworkCapabilitiesTest.kt b/tests/unit/java/com/android/server/connectivity/ApplicationSelfCertifiedNetworkCapabilitiesTest.kt
new file mode 100644
index 0000000..f2d7aaa
--- /dev/null
+++ b/tests/unit/java/com/android/server/connectivity/ApplicationSelfCertifiedNetworkCapabilitiesTest.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 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 com.android.server.connectivity
+
+import android.net.NetworkCapabilities
+import android.os.Build
+import androidx.test.InstrumentationRegistry
+import androidx.test.filters.SmallTest
+import com.android.frameworks.tests.net.R
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertFailsWith
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(DevSdkIgnoreRunner::class)
+@SmallTest
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+class ApplicationSelfCertifiedNetworkCapabilitiesTest {
+ private val mResource = InstrumentationRegistry.getContext().getResources()
+ private val bandwidthCapability = NetworkCapabilities.Builder().apply {
+ addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ }.build()
+ private val latencyCapability = NetworkCapabilities.Builder().apply {
+ addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ }.build()
+ private val emptyCapability = NetworkCapabilities.Builder().build()
+ private val bothCapabilities = NetworkCapabilities.Builder().apply {
+ addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
+ addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
+ }.build()
+
+ @Test
+ fun parseXmlWithWrongTag_shouldIgnoreWrongTag() {
+ val parser = mResource.getXml(
+ R.xml.self_certified_capabilities_wrong_tag
+ )
+ val selfDeclaredCaps = ApplicationSelfCertifiedNetworkCapabilities.createFromXml(parser)
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(latencyCapability)
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(bandwidthCapability)
+ }
+
+ @Test
+ fun parseXmlWithWrongDeclaration_shouldThrowException() {
+ val parser = mResource.getXml(
+ R.xml.self_certified_capabilities_wrong_declaration
+ )
+ val exception = assertFailsWith<InvalidTagException> {
+ ApplicationSelfCertifiedNetworkCapabilities.createFromXml(parser)
+ }
+ assertThat(exception.message).contains("network-capabilities-declaration1")
+ }
+
+ @Test
+ fun checkIfSelfCertifiedNetworkCapabilitiesDeclared_shouldThrowExceptionWhenNoDeclaration() {
+ val parser = mResource.getXml(R.xml.self_certified_capabilities_other)
+ val selfDeclaredCaps = ApplicationSelfCertifiedNetworkCapabilities.createFromXml(parser)
+ val exception1 = assertFailsWith<SecurityException> {
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(latencyCapability)
+ }
+ assertThat(exception1.message).contains(
+ ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_LATENCY
+ )
+ val exception2 = assertFailsWith<SecurityException> {
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(bandwidthCapability)
+ }
+ assertThat(exception2.message).contains(
+ ApplicationSelfCertifiedNetworkCapabilities.PRIORITIZE_BANDWIDTH
+ )
+ }
+
+ @Test
+ fun checkIfSelfCertifiedNetworkCapabilitiesDeclared_shouldPassIfDeclarationExist() {
+ val parser = mResource.getXml(R.xml.self_certified_capabilities_both)
+ val selfDeclaredCaps = ApplicationSelfCertifiedNetworkCapabilities.createFromXml(parser)
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(latencyCapability)
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(bandwidthCapability)
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(bothCapabilities)
+ selfDeclaredCaps.enforceSelfCertifiedNetworkCapabilitiesDeclared(emptyCapability)
+ }
+}
diff --git a/tests/unit/res/xml/self_certified_capabilities_bandwidth.xml b/tests/unit/res/xml/self_certified_capabilities_bandwidth.xml
new file mode 100644
index 0000000..01fdca1
--- /dev/null
+++ b/tests/unit/res/xml/self_certified_capabilities_bandwidth.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_BANDWIDTH"/>
+</network-capabilities-declaration>
diff --git a/tests/unit/res/xml/self_certified_capabilities_both.xml b/tests/unit/res/xml/self_certified_capabilities_both.xml
new file mode 100644
index 0000000..4066be2
--- /dev/null
+++ b/tests/unit/res/xml/self_certified_capabilities_both.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_BANDWIDTH"/>
+</network-capabilities-declaration>
diff --git a/tests/unit/res/xml/self_certified_capabilities_latency.xml b/tests/unit/res/xml/self_certified_capabilities_latency.xml
new file mode 100644
index 0000000..1c4a0e0
--- /dev/null
+++ b/tests/unit/res/xml/self_certified_capabilities_latency.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+</network-capabilities-declaration>
diff --git a/tests/unit/res/xml/self_certified_capabilities_other.xml b/tests/unit/res/xml/self_certified_capabilities_other.xml
new file mode 100644
index 0000000..5b6649c
--- /dev/null
+++ b/tests/unit/res/xml/self_certified_capabilities_other.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability android:name="other"/>
+</network-capabilities-declaration>
diff --git a/tests/unit/res/xml/self_certified_capabilities_wrong_declaration.xml b/tests/unit/res/xml/self_certified_capabilities_wrong_declaration.xml
new file mode 100644
index 0000000..6082356
--- /dev/null
+++ b/tests/unit/res/xml/self_certified_capabilities_wrong_declaration.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration1 xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+</network-capabilities-declaration1>
diff --git a/tests/unit/res/xml/self_certified_capabilities_wrong_tag.xml b/tests/unit/res/xml/self_certified_capabilities_wrong_tag.xml
new file mode 100644
index 0000000..c9ecc0b
--- /dev/null
+++ b/tests/unit/res/xml/self_certified_capabilities_wrong_tag.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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.
+-->
+
+<network-capabilities-declaration xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-network-capability1 android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_LATENCY"/>
+ <uses-network-capability android:name="NET_CAPABILITY_PRIORITIZE_BANDWIDTH"/>
+</network-capabilities-declaration>