Merge "Disable PendingIntent background activity launch" into tm-dev am: 05494c71f8
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/18610590
Change-Id: I29e55026ae07fcadfda63619fe9f888b7f30871f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/TEST_MAPPING b/TEST_MAPPING
index c4c79c6..bb6d655 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -41,6 +41,9 @@
"name": "connectivity_native_test"
},
{
+ "name": "libclat_test"
+ },
+ {
"name": "netd_updatable_unit_test"
},
{
@@ -68,16 +71,10 @@
"keywords": ["netd-device-kernel-4.9", "netd-device-kernel-4.14"]
},
{
- "name": "libclat_test"
- },
- {
"name": "traffic_controller_unit_test",
"keywords": ["netd-device-kernel-4.9", "netd-device-kernel-4.14"]
},
{
- "name": "libnetworkstats_test"
- },
- {
"name": "FrameworksNetDeflakeTest"
}
],
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 1728665..8ab6507 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -33,6 +33,7 @@
":framework-connectivity-shared-srcs",
":tethering-module-utils-srcs",
":services-tethering-shared-srcs",
+ ":statslog-tethering-java-gen",
],
static_libs: [
"androidx.annotation_annotation",
@@ -223,3 +224,11 @@
apex_available: ["com.android.tethering"],
min_sdk_version: "30",
}
+
+genrule {
+ name: "statslog-tethering-java-gen",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --java $(out) --module network_tethering" +
+ " --javaPackage com.android.networkstack.tethering.metrics --javaClass TetheringStatsLog",
+ out: ["com/android/networkstack/tethering/metrics/TetheringStatsLog.java"],
+}
\ No newline at end of file
diff --git a/Tethering/src/android/net/ip/IpServer.java b/Tethering/src/android/net/ip/IpServer.java
index c718f4c..437ed71 100644
--- a/Tethering/src/android/net/ip/IpServer.java
+++ b/Tethering/src/android/net/ip/IpServer.java
@@ -69,6 +69,7 @@
import com.android.networkstack.tethering.BpfCoordinator.Ipv6ForwardingRule;
import com.android.networkstack.tethering.PrivateAddressCoordinator;
import com.android.networkstack.tethering.TetheringConfiguration;
+import com.android.networkstack.tethering.metrics.TetheringMetrics;
import com.android.networkstack.tethering.util.InterfaceSet;
import com.android.networkstack.tethering.util.PrefixUtils;
@@ -282,13 +283,15 @@
private LinkAddress mIpv4Address;
+ private final TetheringMetrics mTetheringMetrics;
+
// TODO: Add a dependency object to pass the data members or variables from the tethering
// object. It helps to reduce the arguments of the constructor.
public IpServer(
String ifaceName, Looper looper, int interfaceType, SharedLog log,
INetd netd, @NonNull BpfCoordinator coordinator, Callback callback,
TetheringConfiguration config, PrivateAddressCoordinator addressCoordinator,
- Dependencies deps) {
+ TetheringMetrics tetheringMetrics, Dependencies deps) {
super(ifaceName, looper);
mLog = log.forSubComponent(ifaceName);
mNetd = netd;
@@ -303,6 +306,7 @@
mP2pLeasesSubnetPrefixLength = config.getP2pLeasesSubnetPrefixLength();
mPrivateAddressCoordinator = addressCoordinator;
mDeps = deps;
+ mTetheringMetrics = tetheringMetrics;
resetLinkProperties();
mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
mServingMode = STATE_AVAILABLE;
@@ -1201,6 +1205,9 @@
stopConntrackMonitoring();
resetLinkProperties();
+
+ mTetheringMetrics.updateErrorCode(mInterfaceType, mLastError);
+ mTetheringMetrics.sendReport(mInterfaceType);
}
@Override
diff --git a/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
index cc2422f..41a10ae 100644
--- a/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
+++ b/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
@@ -172,6 +172,9 @@
return new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS);
}
+ // This ensures that tethering isn't started on 2 different interfaces with the same type.
+ // Once tethering could support multiple interface with the same type,
+ // TetheringSoftApCallback would need to handle it among others.
final LinkAddress cachedAddress = mCachedAddresses.get(ipServer.interfaceType());
if (useLastAddress && cachedAddress != null
&& !isConflictWithUpstream(asIpPrefix(cachedAddress))) {
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 35a394d..af017f3 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -140,6 +140,7 @@
import com.android.networkstack.apishim.common.BluetoothPanShim.TetheredInterfaceCallbackShim;
import com.android.networkstack.apishim.common.BluetoothPanShim.TetheredInterfaceRequestShim;
import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
+import com.android.networkstack.tethering.metrics.TetheringMetrics;
import com.android.networkstack.tethering.util.InterfaceSet;
import com.android.networkstack.tethering.util.PrefixUtils;
import com.android.networkstack.tethering.util.TetheringUtils;
@@ -254,6 +255,7 @@
private final UserManager mUserManager;
private final BpfCoordinator mBpfCoordinator;
private final PrivateAddressCoordinator mPrivateAddressCoordinator;
+ private final TetheringMetrics mTetheringMetrics;
private int mActiveDataSubId = INVALID_SUBSCRIPTION_ID;
private volatile TetheringConfiguration mConfig;
@@ -292,6 +294,7 @@
mNetd = mDeps.getINetd(mContext);
mLooper = mDeps.getTetheringLooper();
mNotificationUpdater = mDeps.getNotificationUpdater(mContext, mLooper);
+ mTetheringMetrics = mDeps.getTetheringMetrics();
// This is intended to ensrure that if something calls startTethering(bluetooth) just after
// bluetooth is enabled. Before onServiceConnected is called, store the calls into this
@@ -445,8 +448,22 @@
mStateReceiver, noUpstreamFilter, PERMISSION_MAINLINE_NETWORK_STACK, mHandler);
final WifiManager wifiManager = getWifiManager();
+ TetheringSoftApCallback softApCallback = new TetheringSoftApCallback();
if (wifiManager != null) {
- wifiManager.registerSoftApCallback(mExecutor, new TetheringSoftApCallback());
+ wifiManager.registerSoftApCallback(mExecutor, softApCallback);
+ }
+ if (SdkLevel.isAtLeastT() && wifiManager != null) {
+ try {
+ // Although WifiManager#registerLocalOnlyHotspotSoftApCallback document that it need
+ // NEARBY_WIFI_DEVICES permission, but actually a caller who have NETWORK_STACK
+ // or MAINLINE_NETWORK_STACK permission would also able to use this API.
+ wifiManager.registerLocalOnlyHotspotSoftApCallback(mExecutor, softApCallback);
+ } catch (UnsupportedOperationException e) {
+ // Since wifi module development in internal branch,
+ // #registerLocalOnlyHotspotSoftApCallback currently doesn't supported in AOSP
+ // before AOSP switch to Android T + 1.
+ Log.wtf(TAG, "registerLocalOnlyHotspotSoftApCallback API is not supported");
+ }
}
startTrackDefaultNetwork();
@@ -542,6 +559,13 @@
}
// Called by wifi when the number of soft AP clients changed.
+ // Currently multiple softAp would not behave well in PrivateAddressCoordinator
+ // (where it gets the address from cache), it ensure tethering only support one ipServer for
+ // TETHERING_WIFI. Once tethering support multiple softAp enabled simultaneously,
+ // onConnectedClientsChanged should also be updated to support tracking different softAp's
+ // clients individually.
+ // TODO: Add wtf log and have check to reject request duplicated type with different
+ // interface.
@Override
public void onConnectedClientsChanged(final List<WifiClient> clients) {
updateConnectedClients(clients);
@@ -616,7 +640,8 @@
processInterfaceStateChange(iface, false /* enabled */);
}
- void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) {
+ void startTethering(final TetheringRequestParcel request, final String callerPkg,
+ final IIntResultListener listener) {
mHandler.post(() -> {
final TetheringRequestParcel unfinishedRequest = mActiveTetheringRequests.get(
request.tetheringType);
@@ -636,6 +661,7 @@
request.showProvisioningUi);
}
enableTetheringInternal(request.tetheringType, true /* enabled */, listener);
+ mTetheringMetrics.createBuilder(request.tetheringType, callerPkg);
});
}
@@ -695,7 +721,11 @@
// If changing tethering fail, remove corresponding request
// no matter who trigger the start/stop.
- if (result != TETHER_ERROR_NO_ERROR) mActiveTetheringRequests.remove(type);
+ if (result != TETHER_ERROR_NO_ERROR) {
+ mActiveTetheringRequests.remove(type);
+ mTetheringMetrics.updateErrorCode(type, result);
+ mTetheringMetrics.sendReport(type);
+ }
}
private int setWifiTethering(final boolean enable) {
@@ -2779,7 +2809,7 @@
final TetherState tetherState = new TetherState(
new IpServer(iface, mLooper, interfaceType, mLog, mNetd, mBpfCoordinator,
makeControlCallback(), mConfig, mPrivateAddressCoordinator,
- mDeps.getIpServerDependencies()), isNcm);
+ mTetheringMetrics, mDeps.getIpServerDependencies()), isNcm);
mTetherStates.put(iface, tetherState);
tetherState.ipServer.start();
}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
index 9224213..8e0354d 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
@@ -34,6 +34,7 @@
import com.android.internal.util.StateMachine;
import com.android.networkstack.apishim.BluetoothPanShimImpl;
import com.android.networkstack.apishim.common.BluetoothPanShim;
+import com.android.networkstack.tethering.metrics.TetheringMetrics;
import java.util.ArrayList;
@@ -163,4 +164,11 @@
public BluetoothPanShim getBluetoothPanShim(BluetoothPan pan) {
return BluetoothPanShimImpl.newInstance(pan);
}
+
+ /**
+ * Get a reference to the TetheringMetrics to be used by tethering.
+ */
+ public TetheringMetrics getTetheringMetrics() {
+ return new TetheringMetrics();
+ }
}
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringService.java b/Tethering/src/com/android/networkstack/tethering/TetheringService.java
index 9fb61fe..f147e10 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringService.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringService.java
@@ -137,7 +137,7 @@
return;
}
- mTethering.startTethering(request, listener);
+ mTethering.startTethering(request, callerPkg, listener);
}
@Override
diff --git a/Tethering/src/com/android/networkstack/tethering/metrics/TetheringMetrics.java b/Tethering/src/com/android/networkstack/tethering/metrics/TetheringMetrics.java
new file mode 100644
index 0000000..e25f2ae
--- /dev/null
+++ b/Tethering/src/com/android/networkstack/tethering/metrics/TetheringMetrics.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2022 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.networkstack.tethering.metrics;
+
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_ETHERNET;
+import static android.net.TetheringManager.TETHERING_NCM;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHERING_WIFI_P2P;
+import static android.net.TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_DISABLE_FORWARDING_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
+import static android.net.TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
+import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
+import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
+import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
+import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
+import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
+import static android.net.TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
+
+import android.stats.connectivity.DownstreamType;
+import android.stats.connectivity.ErrorCode;
+import android.stats.connectivity.UpstreamType;
+import android.stats.connectivity.UserType;
+import android.util.Log;
+import android.util.SparseArray;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * Collection of utilities for tethering metrics.
+ *
+ * To see if the logs are properly sent to statsd, execute following commands
+ *
+ * $ adb shell cmd stats print-logs
+ * $ adb logcat | grep statsd OR $ adb logcat -b stats
+ *
+ * @hide
+ */
+public class TetheringMetrics {
+ private static final String TAG = TetheringMetrics.class.getSimpleName();
+ private static final boolean DBG = false;
+ private static final String SETTINGS_PKG_NAME = "com.android.settings";
+ private static final String SYSTEMUI_PKG_NAME = "com.android.systemui";
+ private static final String GMS_PKG_NAME = "com.google.android.gms";
+ private final SparseArray<NetworkTetheringReported.Builder> mBuilderMap = new SparseArray<>();
+
+ /** Update Tethering stats about caller's package name and downstream type. */
+ public void createBuilder(final int downstreamType, final String callerPkg) {
+ mBuilderMap.clear();
+ NetworkTetheringReported.Builder statsBuilder =
+ NetworkTetheringReported.newBuilder();
+ statsBuilder.setDownstreamType(downstreamTypeToEnum(downstreamType))
+ .setUserType(userTypeToEnum(callerPkg))
+ .setUpstreamType(UpstreamType.UT_UNKNOWN)
+ .setErrorCode(ErrorCode.EC_NO_ERROR)
+ .build();
+ mBuilderMap.put(downstreamType, statsBuilder);
+ }
+
+ /** Update error code of given downstreamType. */
+ public void updateErrorCode(final int downstreamType, final int errCode) {
+ NetworkTetheringReported.Builder statsBuilder = mBuilderMap.get(downstreamType);
+ if (statsBuilder == null) {
+ Log.e(TAG, "Given downstreamType does not exist, this is a bug!");
+ return;
+ }
+ statsBuilder.setErrorCode(errorCodeToEnum(errCode));
+ }
+
+ /** Remove Tethering stats.
+ * If Tethering stats is ready to write then write it before removing.
+ */
+ public void sendReport(final int downstreamType) {
+ final NetworkTetheringReported.Builder statsBuilder =
+ mBuilderMap.get(downstreamType);
+ if (statsBuilder == null) {
+ Log.e(TAG, "Given downstreamType does not exist, this is a bug!");
+ return;
+ }
+ write(statsBuilder.build());
+ mBuilderMap.remove(downstreamType);
+ }
+
+ /** Collect Tethering stats and write metrics data to statsd pipeline. */
+ @VisibleForTesting
+ public void write(@NonNull final NetworkTetheringReported reported) {
+ TetheringStatsLog.write(TetheringStatsLog.NETWORK_TETHERING_REPORTED,
+ reported.getErrorCode().getNumber(),
+ reported.getDownstreamType().getNumber(),
+ reported.getUpstreamType().getNumber(),
+ reported.getUserType().getNumber());
+ if (DBG) {
+ Log.d(TAG, "Write errorCode: " + reported.getErrorCode().getNumber()
+ + ", downstreamType: " + reported.getDownstreamType().getNumber()
+ + ", upstreamType: " + reported.getUpstreamType().getNumber()
+ + ", userType: " + reported.getUserType().getNumber());
+ }
+ }
+
+ /** Map {@link TetheringType} to {@link DownstreamType} */
+ private DownstreamType downstreamTypeToEnum(final int ifaceType) {
+ switch(ifaceType) {
+ case TETHERING_WIFI:
+ return DownstreamType.DS_TETHERING_WIFI;
+ case TETHERING_WIFI_P2P:
+ return DownstreamType.DS_TETHERING_WIFI_P2P;
+ case TETHERING_USB:
+ return DownstreamType.DS_TETHERING_USB;
+ case TETHERING_BLUETOOTH:
+ return DownstreamType.DS_TETHERING_BLUETOOTH;
+ case TETHERING_NCM:
+ return DownstreamType.DS_TETHERING_NCM;
+ case TETHERING_ETHERNET:
+ return DownstreamType.DS_TETHERING_ETHERNET;
+ default:
+ return DownstreamType.DS_UNSPECIFIED;
+ }
+ }
+
+ /** Map {@link StartTetheringError} to {@link ErrorCode} */
+ private ErrorCode errorCodeToEnum(final int lastError) {
+ switch(lastError) {
+ case TETHER_ERROR_NO_ERROR:
+ return ErrorCode.EC_NO_ERROR;
+ case TETHER_ERROR_UNKNOWN_IFACE:
+ return ErrorCode.EC_UNKNOWN_IFACE;
+ case TETHER_ERROR_SERVICE_UNAVAIL:
+ return ErrorCode.EC_SERVICE_UNAVAIL;
+ case TETHER_ERROR_UNSUPPORTED:
+ return ErrorCode.EC_UNSUPPORTED;
+ case TETHER_ERROR_UNAVAIL_IFACE:
+ return ErrorCode.EC_UNAVAIL_IFACE;
+ case TETHER_ERROR_INTERNAL_ERROR:
+ return ErrorCode.EC_INTERNAL_ERROR;
+ case TETHER_ERROR_TETHER_IFACE_ERROR:
+ return ErrorCode.EC_TETHER_IFACE_ERROR;
+ case TETHER_ERROR_UNTETHER_IFACE_ERROR:
+ return ErrorCode.EC_UNTETHER_IFACE_ERROR;
+ case TETHER_ERROR_ENABLE_FORWARDING_ERROR:
+ return ErrorCode.EC_ENABLE_FORWARDING_ERROR;
+ case TETHER_ERROR_DISABLE_FORWARDING_ERROR:
+ return ErrorCode.EC_DISABLE_FORWARDING_ERROR;
+ case TETHER_ERROR_IFACE_CFG_ERROR:
+ return ErrorCode.EC_IFACE_CFG_ERROR;
+ case TETHER_ERROR_PROVISIONING_FAILED:
+ return ErrorCode.EC_PROVISIONING_FAILED;
+ case TETHER_ERROR_DHCPSERVER_ERROR:
+ return ErrorCode.EC_DHCPSERVER_ERROR;
+ case TETHER_ERROR_ENTITLEMENT_UNKNOWN:
+ return ErrorCode.EC_ENTITLEMENT_UNKNOWN;
+ case TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION:
+ return ErrorCode.EC_NO_CHANGE_TETHERING_PERMISSION;
+ case TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION:
+ return ErrorCode.EC_NO_ACCESS_TETHERING_PERMISSION;
+ default:
+ return ErrorCode.EC_UNKNOWN_TYPE;
+ }
+ }
+
+ /** Map callerPkg to {@link UserType} */
+ private UserType userTypeToEnum(final String callerPkg) {
+ if (callerPkg.equals(SETTINGS_PKG_NAME)) {
+ return UserType.USER_SETTINGS;
+ } else if (callerPkg.equals(SYSTEMUI_PKG_NAME)) {
+ return UserType.USER_SYSTEMUI;
+ } else if (callerPkg.equals(GMS_PKG_NAME)) {
+ return UserType.USER_GMS;
+ } else {
+ return UserType.USER_UNKNOWN;
+ }
+ }
+}
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index 3699f7a..5869f2b 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -36,9 +36,11 @@
import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV4;
import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6;
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
+import static com.android.testutils.DeviceInfoUtils.KVersion;
import static com.android.testutils.TestNetworkTrackerKt.initTestNetwork;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -1067,23 +1069,43 @@
false /* usingBpf */);
}
- private static boolean isUdpOffloadSupportedByKernel() {
- final String kVersionString = VintfRuntimeInfo.getKernelVersion();
- // Kernel version which is older than 4.14 doesn't support UDP offload absolutely. Kernel
- // version which is between 4.14 and 5.8 support UDP offload probably. Simply apply kernel
- // 4.14 to be threshold first and monitor on what devices tests fail for improving the
- // offload support checking.
- return DeviceInfoUtils.compareMajorMinorVersion(kVersionString, "4.14") >= 0;
+ private static boolean isUdpOffloadSupportedByKernel(final String kernelVersion) {
+ final KVersion current = DeviceInfoUtils.getMajorMinorSubminorVersion(kernelVersion);
+ return current.isInRange(new KVersion(4, 14, 222), new KVersion(4, 19, 0))
+ || current.isInRange(new KVersion(4, 19, 176), new KVersion(5, 4, 0))
+ || current.isAtLeast(new KVersion(5, 4, 98));
}
@Test
+ public void testIsUdpOffloadSupportedByKernel() throws Exception {
+ assertFalse(isUdpOffloadSupportedByKernel("4.14.221"));
+ assertTrue(isUdpOffloadSupportedByKernel("4.14.222"));
+ assertTrue(isUdpOffloadSupportedByKernel("4.16.0"));
+ assertTrue(isUdpOffloadSupportedByKernel("4.18.0"));
+ assertFalse(isUdpOffloadSupportedByKernel("4.19.0"));
+
+ assertFalse(isUdpOffloadSupportedByKernel("4.19.175"));
+ assertTrue(isUdpOffloadSupportedByKernel("4.19.176"));
+ assertTrue(isUdpOffloadSupportedByKernel("5.2.0"));
+ assertTrue(isUdpOffloadSupportedByKernel("5.3.0"));
+ assertFalse(isUdpOffloadSupportedByKernel("5.4.0"));
+
+ assertFalse(isUdpOffloadSupportedByKernel("5.4.97"));
+ assertTrue(isUdpOffloadSupportedByKernel("5.4.98"));
+ assertTrue(isUdpOffloadSupportedByKernel("5.10.0"));
+ }
+
+ // TODO: refactor test testTetherUdpV4* into IPv4 UDP non-offload and offload tests.
+ // That can be easier to know which feature is verified from test results.
+ @Test
@IgnoreUpTo(Build.VERSION_CODES.R)
public void testTetherUdpV4AfterR() throws Exception {
initializeTethering();
- boolean usingBpf = isUdpOffloadSupportedByKernel();
+ final String kernelVersion = VintfRuntimeInfo.getKernelVersion();
+ boolean usingBpf = isUdpOffloadSupportedByKernel(kernelVersion);
if (!usingBpf) {
Log.i(TAG, "testTetherUdpV4AfterR will skip BPF offload test for kernel "
- + VintfRuntimeInfo.getKernelVersion());
+ + kernelVersion);
}
runUdp4Test(new TetheringTester(mDownstreamReader), new RemoteResponder(mUpstreamReader),
usingBpf);
diff --git a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index aac531a..bf7e887 100644
--- a/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -116,6 +116,7 @@
import com.android.networkstack.tethering.TetherLimitValue;
import com.android.networkstack.tethering.TetherUpstream6Key;
import com.android.networkstack.tethering.TetheringConfiguration;
+import com.android.networkstack.tethering.metrics.TetheringMetrics;
import com.android.networkstack.tethering.util.InterfaceSet;
import com.android.networkstack.tethering.util.PrefixUtils;
import com.android.testutils.DevSdkIgnoreRule;
@@ -186,6 +187,7 @@
@Mock private NetworkStatsManager mStatsManager;
@Mock private TetheringConfiguration mTetherConfig;
@Mock private ConntrackMonitor mConntrackMonitor;
+ @Mock private TetheringMetrics mTetheringMetrics;
@Mock private BpfMap<Tether4Key, Tether4Value> mBpfDownstream4Map;
@Mock private BpfMap<Tether4Key, Tether4Value> mBpfUpstream4Map;
@Mock private BpfMap<TetherDownstream6Key, Tether6Value> mBpfDownstream6Map;
@@ -235,7 +237,7 @@
when(mTetherConfig.getP2pLeasesSubnetPrefixLength()).thenReturn(P2P_SUBNET_PREFIX_LENGTH);
mIpServer = new IpServer(
IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd, mBpfCoordinator,
- mCallback, mTetherConfig, mAddressCoordinator, mDependencies);
+ mCallback, mTetherConfig, mAddressCoordinator, mTetheringMetrics, mDependencies);
mIpServer.start();
mNeighborEventConsumer = neighborCaptor.getValue();
@@ -367,7 +369,7 @@
.thenReturn(mIpNeighborMonitor);
mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog,
mNetd, mBpfCoordinator, mCallback, mTetherConfig, mAddressCoordinator,
- mDependencies);
+ mTetheringMetrics, mDependencies);
mIpServer.start();
mLooper.dispatchAll();
verify(mCallback).updateInterfaceState(
@@ -451,6 +453,9 @@
mIpServer, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
inOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), any(LinkProperties.class));
+ verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_BLUETOOTH),
+ eq(TETHER_ERROR_NO_ERROR));
+ verify(mTetheringMetrics).sendReport(eq(TETHERING_BLUETOOTH));
verifyNoMoreInteractions(mNetd, mCallback, mAddressCoordinator);
}
@@ -658,6 +663,9 @@
usbTeardownOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), mLinkPropertiesCaptor.capture());
assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
+ verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_USB),
+ eq(TETHER_ERROR_TETHER_IFACE_ERROR));
+ verify(mTetheringMetrics).sendReport(eq(TETHERING_USB));
}
@Test
@@ -676,6 +684,9 @@
usbTeardownOrder.verify(mCallback).updateLinkProperties(
eq(mIpServer), mLinkPropertiesCaptor.capture());
assertNoAddressesNorRoutes(mLinkPropertiesCaptor.getValue());
+ verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_USB),
+ eq(TETHER_ERROR_ENABLE_FORWARDING_ERROR));
+ verify(mTetheringMetrics).sendReport(eq(TETHERING_USB));
}
@Test
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
index e9716b3..8ef0c76 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java
@@ -26,6 +26,7 @@
import static android.net.RouteInfo.RTN_UNICAST;
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
+import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_IFACE;
import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_UID;
@@ -668,7 +669,7 @@
if (isAtLeastT()) {
mTetherStatsProviderCb.expectNotifyLimitReached();
- } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.S) {
+ } else if (isAtLeastS()) {
mTetherStatsProviderCb.expectNotifyWarningOrLimitReached();
} else {
mTetherStatsProviderCb.expectNotifyLimitReached();
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
index f664d5d..9db8f16 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
@@ -275,7 +275,7 @@
mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
result);
verify(mTethering).isTetheringSupported();
- verify(mTethering).startTethering(eq(request), eq(result));
+ verify(mTethering).startTethering(eq(request), eq(TEST_CALLER_PKG), eq(result));
}
@Test
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 6ef0e24..773cae3 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -45,6 +45,7 @@
import static android.net.TetheringManager.TETHERING_WIFI;
import static android.net.TetheringManager.TETHERING_WIFI_P2P;
import static android.net.TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
@@ -193,11 +194,15 @@
import com.android.networkstack.apishim.common.BluetoothPanShim.TetheredInterfaceRequestShim;
import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
import com.android.networkstack.tethering.TestConnectivityManager.TestNetworkAgent;
+import com.android.networkstack.tethering.metrics.TetheringMetrics;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.MiscAsserts;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -220,6 +225,8 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class TetheringTest {
+ @Rule public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+
private static final int IFINDEX_OFFSET = 100;
private static final String TEST_MOBILE_IFNAME = "test_rmnet_data0";
@@ -240,6 +247,7 @@
private static final String TEST_WIFI_REGEX = "test_wlan\\d";
private static final String TEST_P2P_REGEX = "test_p2p-p2p\\d-.*";
private static final String TEST_BT_REGEX = "test_pan\\d";
+ private static final String TEST_CALLER_PKG = "com.test.tethering";
private static final int CELLULAR_NETID = 100;
private static final int WIFI_NETID = 101;
@@ -274,6 +282,7 @@
@Mock private BluetoothPan mBluetoothPan;
@Mock private BluetoothPanShim mBluetoothPanShim;
@Mock private TetheredInterfaceRequestShim mTetheredInterfaceRequestShim;
+ @Mock private TetheringMetrics mTetheringMetrics;
private final MockIpServerDependencies mIpServerDependencies =
spy(new MockIpServerDependencies());
@@ -297,6 +306,7 @@
private OffloadController mOffloadCtrl;
private PrivateAddressCoordinator mPrivateAddressCoordinator;
private SoftApCallback mSoftApCallback;
+ private SoftApCallback mLocalOnlyHotspotCallback;
private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
private TetheredInterfaceCallbackShim mTetheredInterfaceCallbackShim;
@@ -498,6 +508,11 @@
}
@Override
+ public TetheringMetrics getTetheringMetrics() {
+ return mTetheringMetrics;
+ }
+
+ @Override
public PrivateAddressCoordinator getPrivateAddressCoordinator(Context ctx,
TetheringConfiguration cfg) {
mPrivateAddressCoordinator = super.getPrivateAddressCoordinator(ctx, cfg);
@@ -662,6 +677,14 @@
verify(mWifiManager).registerSoftApCallback(any(), softApCallbackCaptor.capture());
mSoftApCallback = softApCallbackCaptor.getValue();
+ if (isAtLeastT()) {
+ final ArgumentCaptor<SoftApCallback> localOnlyCallbackCaptor =
+ ArgumentCaptor.forClass(SoftApCallback.class);
+ verify(mWifiManager).registerLocalOnlyHotspotSoftApCallback(any(),
+ localOnlyCallbackCaptor.capture());
+ mLocalOnlyHotspotCallback = localOnlyCallbackCaptor.getValue();
+ }
+
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)).thenReturn(true);
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true);
}
@@ -856,7 +879,8 @@
private void prepareNcmTethering() {
// Emulate startTethering(TETHERING_NCM) called
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_NCM), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_NCM), TEST_CALLER_PKG,
+ null);
mLooper.dispatchAll();
verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NCM);
}
@@ -864,7 +888,7 @@
private void prepareUsbTethering() {
// Emulate pressing the USB tethering button in Settings UI.
final TetheringRequestParcel request = createTetheringRequestParcel(TETHERING_USB);
- mTethering.startTethering(request, null);
+ mTethering.startTethering(request, TEST_CALLER_PKG, null);
mLooper.dispatchAll();
assertEquals(1, mTethering.getActiveTetheringRequests().size());
@@ -1434,7 +1458,8 @@
when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
// Emulate pressing the WiFi tethering button.
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), TEST_CALLER_PKG,
+ null);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager);
@@ -1461,7 +1486,8 @@
when(mWifiManager.startTetheredHotspot(any(SoftApConfiguration.class))).thenReturn(true);
// Emulate pressing the WiFi tethering button.
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), TEST_CALLER_PKG,
+ null);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager);
@@ -1537,11 +1563,13 @@
doThrow(new RemoteException()).when(mNetd).ipfwdEnableForwarding(TETHERING_NAME);
// Emulate pressing the WiFi tethering button.
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), TEST_CALLER_PKG,
+ null);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startTetheredHotspot(null);
verifyNoMoreInteractions(mWifiManager);
verifyNoMoreInteractions(mNetd);
+ verify(mTetheringMetrics).createBuilder(eq(TETHERING_WIFI), anyString());
// Emulate externally-visible WifiManager effects, causing the
// per-interface state machine to start up, and telling us that
@@ -1580,6 +1608,10 @@
verify(mWifiManager).updateInterfaceIpState(
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
+ verify(mTetheringMetrics, times(2)).updateErrorCode(eq(TETHERING_WIFI),
+ eq(TETHER_ERROR_INTERNAL_ERROR));
+ verify(mTetheringMetrics, times(2)).sendReport(eq(TETHERING_WIFI));
+
verifyNoMoreInteractions(mWifiManager);
verifyNoMoreInteractions(mNetd);
}
@@ -1882,7 +1914,8 @@
tetherState = callback.pollTetherStatesChanged();
assertArrayEquals(tetherState.availableList, new TetheringInterface[] {wifiIface});
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), TEST_CALLER_PKG,
+ null);
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
tetherState = callback.pollTetherStatesChanged();
assertArrayEquals(tetherState.tetheredList, new TetheringInterface[] {wifiIface});
@@ -1985,10 +2018,12 @@
public void testNoDuplicatedEthernetRequest() throws Exception {
final TetheredInterfaceRequest mockRequest = mock(TetheredInterfaceRequest.class);
when(mEm.requestTetheredInterface(any(), any())).thenReturn(mockRequest);
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), TEST_CALLER_PKG,
+ null);
mLooper.dispatchAll();
verify(mEm, times(1)).requestTetheredInterface(any(), any());
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), TEST_CALLER_PKG,
+ null);
mLooper.dispatchAll();
verifyNoMoreInteractions(mEm);
mTethering.stopTethering(TETHERING_ETHERNET);
@@ -2192,14 +2227,16 @@
final ResultListener thirdResult = new ResultListener(TETHER_ERROR_NO_ERROR);
// Enable USB tethering and check that Tethering starts USB.
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB), firstResult);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB), TEST_CALLER_PKG,
+ firstResult);
mLooper.dispatchAll();
firstResult.assertHasResult();
verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
verifyNoMoreInteractions(mUsbManager);
// Enable USB tethering again with the same request and expect no change to USB.
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB), secondResult);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB), TEST_CALLER_PKG,
+ secondResult);
mLooper.dispatchAll();
secondResult.assertHasResult();
verify(mUsbManager, never()).setCurrentFunctions(UsbManager.FUNCTION_NONE);
@@ -2208,7 +2245,8 @@
// Enable USB tethering with a different request and expect that USB is stopped and
// started.
mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
- serverLinkAddr, clientLinkAddr, false, CONNECTIVITY_SCOPE_GLOBAL), thirdResult);
+ serverLinkAddr, clientLinkAddr, false, CONNECTIVITY_SCOPE_GLOBAL),
+ TEST_CALLER_PKG, thirdResult);
mLooper.dispatchAll();
thirdResult.assertHasResult();
verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NONE);
@@ -2237,7 +2275,8 @@
final ArgumentCaptor<DhcpServingParamsParcel> dhcpParamsCaptor =
ArgumentCaptor.forClass(DhcpServingParamsParcel.class);
mTethering.startTethering(createTetheringRequestParcel(TETHERING_USB,
- serverLinkAddr, clientLinkAddr, false, CONNECTIVITY_SCOPE_GLOBAL), null);
+ serverLinkAddr, clientLinkAddr, false, CONNECTIVITY_SCOPE_GLOBAL),
+ TEST_CALLER_PKG, null);
mLooper.dispatchAll();
verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NCM);
mTethering.interfaceStatusChanged(TEST_NCM_IFNAME, true);
@@ -2305,7 +2344,7 @@
final TetheringRequestParcel wifiNotExemptRequest =
createTetheringRequestParcel(TETHERING_WIFI, null, null, false,
CONNECTIVITY_SCOPE_GLOBAL);
- mTethering.startTethering(wifiNotExemptRequest, null);
+ mTethering.startTethering(wifiNotExemptRequest, TEST_CALLER_PKG, null);
mLooper.dispatchAll();
verify(mEntitleMgr).startProvisioningIfNeeded(TETHERING_WIFI, false);
verify(mEntitleMgr, never()).setExemptedDownstreamType(TETHERING_WIFI);
@@ -2319,7 +2358,7 @@
final TetheringRequestParcel wifiExemptRequest =
createTetheringRequestParcel(TETHERING_WIFI, null, null, true,
CONNECTIVITY_SCOPE_GLOBAL);
- mTethering.startTethering(wifiExemptRequest, null);
+ mTethering.startTethering(wifiExemptRequest, TEST_CALLER_PKG, null);
mLooper.dispatchAll();
verify(mEntitleMgr, never()).startProvisioningIfNeeded(TETHERING_WIFI, false);
verify(mEntitleMgr).setExemptedDownstreamType(TETHERING_WIFI);
@@ -2332,14 +2371,14 @@
// If one app enables tethering without provisioning check first, then another app enables
// tethering of the same type but does not disable the provisioning check.
setupForRequiredProvisioning();
- mTethering.startTethering(wifiExemptRequest, null);
+ mTethering.startTethering(wifiExemptRequest, TEST_CALLER_PKG, null);
mLooper.dispatchAll();
verify(mEntitleMgr, never()).startProvisioningIfNeeded(TETHERING_WIFI, false);
verify(mEntitleMgr).setExemptedDownstreamType(TETHERING_WIFI);
assertTrue(mEntitleMgr.isCellularUpstreamPermitted());
reset(mEntitleMgr);
setupForRequiredProvisioning();
- mTethering.startTethering(wifiNotExemptRequest, null);
+ mTethering.startTethering(wifiNotExemptRequest, TEST_CALLER_PKG, null);
mLooper.dispatchAll();
verify(mEntitleMgr).startProvisioningIfNeeded(TETHERING_WIFI, false);
verify(mEntitleMgr, never()).setExemptedDownstreamType(TETHERING_WIFI);
@@ -2429,7 +2468,8 @@
when(mEm.requestTetheredInterface(any(), any())).thenReturn(mockRequest);
final ArgumentCaptor<TetheredInterfaceCallback> callbackCaptor =
ArgumentCaptor.forClass(TetheredInterfaceCallback.class);
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET), null);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_ETHERNET),
+ TEST_CALLER_PKG, null);
mLooper.dispatchAll();
verify(mEm).requestTetheredInterface(any(), callbackCaptor.capture());
TetheredInterfaceCallback ethCallback = callbackCaptor.getValue();
@@ -2511,12 +2551,11 @@
eventCallbacks = dhcpEventCbsCaptor.getValue();
// Update lease for local only tethering.
final MacAddress testMac1 = MacAddress.fromString("11:11:11:11:11:11");
- final ArrayList<DhcpLeaseParcelable> p2pLeases = new ArrayList<>();
- p2pLeases.add(createDhcpLeaseParcelable("clientId1", testMac1, "192.168.50.24", 24,
- Long.MAX_VALUE, "test1"));
- notifyDhcpLeasesChanged(p2pLeases, eventCallbacks);
- final List<TetheredClient> clients = toTetheredClients(p2pLeases, TETHERING_WIFI_P2P);
- callback.expectTetheredClientChanged(clients);
+ final DhcpLeaseParcelable p2pLease = createDhcpLeaseParcelable("clientId1", testMac1,
+ "192.168.50.24", 24, Long.MAX_VALUE, "test1");
+ final List<TetheredClient> p2pClients = notifyDhcpLeasesChanged(TETHERING_WIFI_P2P,
+ eventCallbacks, p2pLease);
+ callback.expectTetheredClientChanged(p2pClients);
reset(mDhcpServer);
// Run wifi tethering.
@@ -2526,25 +2565,20 @@
any(), dhcpEventCbsCaptor.capture());
eventCallbacks = dhcpEventCbsCaptor.getValue();
// Update mac address from softAp callback before getting dhcp lease.
- final ArrayList<WifiClient> wifiClients = new ArrayList<>();
final MacAddress testMac2 = MacAddress.fromString("22:22:22:22:22:22");
- final WifiClient testClient = mock(WifiClient.class);
- when(testClient.getMacAddress()).thenReturn(testMac2);
- wifiClients.add(testClient);
- mSoftApCallback.onConnectedClientsChanged(wifiClients);
- final TetheredClient noAddrClient = new TetheredClient(testMac2,
- Collections.emptyList() /* addresses */, TETHERING_WIFI);
- clients.add(noAddrClient);
- callback.expectTetheredClientChanged(clients);
+ 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.
- clients.remove(noAddrClient);
- final ArrayList<DhcpLeaseParcelable> wifiLeases = new ArrayList<>();
- wifiLeases.add(createDhcpLeaseParcelable("clientId2", testMac2, "192.168.43.24", 24,
- Long.MAX_VALUE, "test2"));
- notifyDhcpLeasesChanged(wifiLeases, eventCallbacks);
- clients.addAll(toTetheredClients(wifiLeases, TETHERING_WIFI));
- callback.expectTetheredClientChanged(clients);
+ 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);
// Test onStarted callback that register second callback when tethering is running.
TestTetheringEventCallback callback2 = new TestTetheringEventCallback();
@@ -2552,18 +2586,74 @@
mTethering.registerTetheringEventCallback(callback2);
mLooper.dispatchAll();
});
- callback2.expectTetheredClientChanged(clients);
+ callback2.expectTetheredClientChanged(p2pAndWifiClients);
}
- private void notifyDhcpLeasesChanged(List<DhcpLeaseParcelable> leaseParcelables,
- IDhcpEventCallbacks callback) throws Exception {
- callback.onLeasesChanged(leaseParcelables);
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.S_V2)
+ public void testUpdateConnectedClientsForLocalOnlyHotspot() throws Exception {
+ TestTetheringEventCallback callback = new TestTetheringEventCallback();
+ runAsShell(NETWORK_SETTINGS, () -> {
+ mTethering.registerTetheringEventCallback(callback);
+ mLooper.dispatchAll();
+ });
+ callback.expectTetheredClientChanged(Collections.emptyList());
+
+ // Run local only hotspot.
+ mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
+ sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
+
+ final ArgumentCaptor<IDhcpEventCallbacks> dhcpEventCbsCaptor =
+ ArgumentCaptor.forClass(IDhcpEventCallbacks.class);
+ 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 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);
+
+ // Client disconnect from local only hotspot.
+ mLocalOnlyHotspotCallback.onConnectedClientsChanged(Collections.emptyList());
+ callback.expectTetheredClientChanged(Collections.emptyList());
+ }
+
+ private TetheredClient notifyConnectedWifiClientsChanged(final MacAddress mac,
+ boolean isLocalOnly) throws Exception {
+ final ArrayList<WifiClient> wifiClients = new ArrayList<>();
+ final WifiClient testClient = mock(WifiClient.class);
+ when(testClient.getMacAddress()).thenReturn(mac);
+ wifiClients.add(testClient);
+ if (isLocalOnly) {
+ mLocalOnlyHotspotCallback.onConnectedClientsChanged(wifiClients);
+ } else {
+ mSoftApCallback.onConnectedClientsChanged(wifiClients);
+ }
+ return new TetheredClient(mac, Collections.emptyList() /* addresses */, TETHERING_WIFI);
+ }
+
+ private List<TetheredClient> notifyDhcpLeasesChanged(int type, IDhcpEventCallbacks callback,
+ DhcpLeaseParcelable... leases) throws Exception {
+ final List<DhcpLeaseParcelable> dhcpLeases = Arrays.asList(leases);
+ callback.onLeasesChanged(dhcpLeases);
mLooper.dispatchAll();
+
+ return toTetheredClients(dhcpLeases, type);
}
private List<TetheredClient> toTetheredClients(List<DhcpLeaseParcelable> leaseParcelables,
int type) throws Exception {
- final ArrayList<TetheredClient> leases = new ArrayList<>();
+ final ArrayList<TetheredClient> clients = new ArrayList<>();
for (DhcpLeaseParcelable lease : leaseParcelables) {
final LinkAddress address = new LinkAddress(
intToInet4AddressHTH(lease.netAddr), lease.prefixLength,
@@ -2573,13 +2663,13 @@
final MacAddress macAddress = MacAddress.fromBytes(lease.hwAddr);
final AddressInfo addressInfo = new TetheredClient.AddressInfo(address, lease.hostname);
- leases.add(new TetheredClient(
+ clients.add(new TetheredClient(
macAddress,
Collections.singletonList(addressInfo),
type));
}
- return leases;
+ return clients;
}
private DhcpLeaseParcelable createDhcpLeaseParcelable(final String clientId,
@@ -2604,7 +2694,8 @@
final ResultListener result = new ResultListener(TETHER_ERROR_NO_ERROR);
mockBluetoothSettings(true /* bluetoothOn */, true /* tetheringOn */);
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_BLUETOOTH), result);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_BLUETOOTH),
+ TEST_CALLER_PKG, result);
mLooper.dispatchAll();
verifySetBluetoothTethering(true /* enable */, true /* bindToPanService */);
result.assertHasResult();
@@ -2639,7 +2730,8 @@
final ResultListener result = new ResultListener(TETHER_ERROR_NO_ERROR);
mockBluetoothSettings(true /* bluetoothOn */, true /* tetheringOn */);
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_BLUETOOTH), result);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_BLUETOOTH),
+ TEST_CALLER_PKG, result);
mLooper.dispatchAll();
verifySetBluetoothTethering(true /* enable */, true /* bindToPanService */);
result.assertHasResult();
@@ -2660,7 +2752,8 @@
// already bound.
mockBluetoothSettings(true /* bluetoothOn */, true /* tetheringOn */);
final ResultListener secondResult = new ResultListener(TETHER_ERROR_NO_ERROR);
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_BLUETOOTH), secondResult);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_BLUETOOTH),
+ TEST_CALLER_PKG, secondResult);
mLooper.dispatchAll();
verifySetBluetoothTethering(true /* enable */, false /* bindToPanService */);
secondResult.assertHasResult();
@@ -2681,7 +2774,8 @@
public void testBluetoothServiceDisconnects() throws Exception {
final ResultListener result = new ResultListener(TETHER_ERROR_NO_ERROR);
mockBluetoothSettings(true /* bluetoothOn */, true /* tetheringOn */);
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_BLUETOOTH), result);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_BLUETOOTH),
+ TEST_CALLER_PKG, result);
mLooper.dispatchAll();
ServiceListener panListener = verifySetBluetoothTethering(true /* enable */,
true /* bindToPanService */);
@@ -2832,18 +2926,26 @@
runNcmTethering();
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
any(), any());
+ verify(mTetheringMetrics).createBuilder(eq(TETHERING_NCM), anyString());
// Change the USB tethering function to NCM. Because the USB tethering function was set to
// RNDIS (the default), tethering is stopped.
forceUsbTetheringUse(TETHER_USB_NCM_FUNCTION);
verifyUsbTetheringStopDueToSettingChange(TEST_NCM_IFNAME);
+ verify(mTetheringMetrics).updateErrorCode(anyInt(), eq(TETHER_ERROR_NO_ERROR));
+ verify(mTetheringMetrics).sendReport(eq(TETHERING_NCM));
// If TETHERING_USB is forced to use ncm function, TETHERING_NCM would no longer be
// available.
final ResultListener ncmResult = new ResultListener(TETHER_ERROR_SERVICE_UNAVAIL);
- mTethering.startTethering(createTetheringRequestParcel(TETHERING_NCM), ncmResult);
+ mTethering.startTethering(createTetheringRequestParcel(TETHERING_NCM), TEST_CALLER_PKG,
+ ncmResult);
mLooper.dispatchAll();
ncmResult.assertHasResult();
+ verify(mTetheringMetrics, times(2)).createBuilder(eq(TETHERING_NCM), anyString());
+ verify(mTetheringMetrics).updateErrorCode(eq(TETHERING_NCM),
+ eq(TETHER_ERROR_SERVICE_UNAVAIL));
+ verify(mTetheringMetrics, times(2)).sendReport(eq(TETHERING_NCM));
// Run TETHERING_USB with ncm configuration.
runDualStackUsbTethering(TEST_NCM_IFNAME);
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/metrics/TetheringMetricsTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/metrics/TetheringMetricsTest.java
new file mode 100644
index 0000000..c34cf5f
--- /dev/null
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/metrics/TetheringMetricsTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2022 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.networkstack.tethering.metrics;
+
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_ETHERNET;
+import static android.net.TetheringManager.TETHERING_NCM;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHERING_WIFI_P2P;
+import static android.net.TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_DISABLE_FORWARDING_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
+import static android.net.TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_INTERNAL_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
+import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
+import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
+import static android.net.TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
+import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
+import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_TYPE;
+import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED;
+import static android.net.TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
+
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.stats.connectivity.DownstreamType;
+import android.stats.connectivity.ErrorCode;
+import android.stats.connectivity.UpstreamType;
+import android.stats.connectivity.UserType;
+import android.util.Pair;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public final class TetheringMetricsTest {
+ private static final String TEST_CALLER_PKG = "com.test.caller.pkg";
+ private static final String SETTINGS_PKG = "com.android.settings";
+ private static final String SYSTEMUI_PKG = "com.android.systemui";
+ private static final String GMS_PKG = "com.google.android.gms";
+ private TetheringMetrics mTetheringMetrics;
+
+ private final NetworkTetheringReported.Builder mStatsBuilder =
+ NetworkTetheringReported.newBuilder();
+
+ private class MockTetheringMetrics extends TetheringMetrics {
+ @Override
+ public void write(final NetworkTetheringReported reported) { }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mTetheringMetrics = spy(new MockTetheringMetrics());
+ }
+
+ private void runDownstreamTypesTest(final Pair<Integer, DownstreamType>... testPairs)
+ throws Exception {
+ for (Pair<Integer, DownstreamType> testPair : testPairs) {
+ final int type = testPair.first;
+ final DownstreamType expectedResult = testPair.second;
+
+ mTetheringMetrics.createBuilder(type, TEST_CALLER_PKG);
+ mTetheringMetrics.updateErrorCode(type, TETHER_ERROR_NO_ERROR);
+ mTetheringMetrics.sendReport(type);
+ NetworkTetheringReported expectedReport =
+ mStatsBuilder.setDownstreamType(expectedResult)
+ .setUserType(UserType.USER_UNKNOWN)
+ .setUpstreamType(UpstreamType.UT_UNKNOWN)
+ .setErrorCode(ErrorCode.EC_NO_ERROR)
+ .build();
+ verify(mTetheringMetrics).write(expectedReport);
+ reset(mTetheringMetrics);
+ }
+ }
+
+ @Test
+ public void testDownstreamTypes() throws Exception {
+ runDownstreamTypesTest(new Pair<>(TETHERING_WIFI, DownstreamType.DS_TETHERING_WIFI),
+ new Pair<>(TETHERING_WIFI_P2P, DownstreamType.DS_TETHERING_WIFI_P2P),
+ new Pair<>(TETHERING_BLUETOOTH, DownstreamType.DS_TETHERING_BLUETOOTH),
+ new Pair<>(TETHERING_USB, DownstreamType.DS_TETHERING_USB),
+ new Pair<>(TETHERING_NCM, DownstreamType.DS_TETHERING_NCM),
+ new Pair<>(TETHERING_ETHERNET, DownstreamType.DS_TETHERING_ETHERNET));
+ }
+
+ private void runErrorCodesTest(final Pair<Integer, ErrorCode>... testPairs)
+ throws Exception {
+ for (Pair<Integer, ErrorCode> testPair : testPairs) {
+ final int errorCode = testPair.first;
+ final ErrorCode expectedResult = testPair.second;
+
+ mTetheringMetrics.createBuilder(TETHERING_WIFI, TEST_CALLER_PKG);
+ mTetheringMetrics.updateErrorCode(TETHERING_WIFI, errorCode);
+ mTetheringMetrics.sendReport(TETHERING_WIFI);
+ NetworkTetheringReported expectedReport =
+ mStatsBuilder.setDownstreamType(DownstreamType.DS_TETHERING_WIFI)
+ .setUserType(UserType.USER_UNKNOWN)
+ .setUpstreamType(UpstreamType.UT_UNKNOWN)
+ .setErrorCode(expectedResult)
+ .build();
+ verify(mTetheringMetrics).write(expectedReport);
+ reset(mTetheringMetrics);
+ }
+ }
+
+ @Test
+ public void testErrorCodes() throws Exception {
+ runErrorCodesTest(new Pair<>(TETHER_ERROR_NO_ERROR, ErrorCode.EC_NO_ERROR),
+ new Pair<>(TETHER_ERROR_UNKNOWN_IFACE, ErrorCode.EC_UNKNOWN_IFACE),
+ new Pair<>(TETHER_ERROR_SERVICE_UNAVAIL, ErrorCode.EC_SERVICE_UNAVAIL),
+ new Pair<>(TETHER_ERROR_UNSUPPORTED, ErrorCode.EC_UNSUPPORTED),
+ new Pair<>(TETHER_ERROR_UNAVAIL_IFACE, ErrorCode.EC_UNAVAIL_IFACE),
+ new Pair<>(TETHER_ERROR_INTERNAL_ERROR, ErrorCode.EC_INTERNAL_ERROR),
+ new Pair<>(TETHER_ERROR_TETHER_IFACE_ERROR, ErrorCode.EC_TETHER_IFACE_ERROR),
+ new Pair<>(TETHER_ERROR_UNTETHER_IFACE_ERROR, ErrorCode.EC_UNTETHER_IFACE_ERROR),
+ new Pair<>(TETHER_ERROR_ENABLE_FORWARDING_ERROR,
+ ErrorCode.EC_ENABLE_FORWARDING_ERROR),
+ new Pair<>(TETHER_ERROR_DISABLE_FORWARDING_ERROR,
+ ErrorCode.EC_DISABLE_FORWARDING_ERROR),
+ new Pair<>(TETHER_ERROR_IFACE_CFG_ERROR, ErrorCode.EC_IFACE_CFG_ERROR),
+ new Pair<>(TETHER_ERROR_PROVISIONING_FAILED, ErrorCode.EC_PROVISIONING_FAILED),
+ new Pair<>(TETHER_ERROR_DHCPSERVER_ERROR, ErrorCode.EC_DHCPSERVER_ERROR),
+ new Pair<>(TETHER_ERROR_ENTITLEMENT_UNKNOWN, ErrorCode.EC_ENTITLEMENT_UNKNOWN),
+ new Pair<>(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION,
+ ErrorCode.EC_NO_CHANGE_TETHERING_PERMISSION),
+ new Pair<>(TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION,
+ ErrorCode.EC_NO_ACCESS_TETHERING_PERMISSION),
+ new Pair<>(TETHER_ERROR_UNKNOWN_TYPE, ErrorCode.EC_UNKNOWN_TYPE));
+ }
+
+ private void runUserTypesTest(final Pair<String, UserType>... testPairs)
+ throws Exception {
+ for (Pair<String, UserType> testPair : testPairs) {
+ final String callerPkg = testPair.first;
+ final UserType expectedResult = testPair.second;
+
+ mTetheringMetrics.createBuilder(TETHERING_WIFI, callerPkg);
+ mTetheringMetrics.updateErrorCode(TETHERING_WIFI, TETHER_ERROR_NO_ERROR);
+ mTetheringMetrics.sendReport(TETHERING_WIFI);
+ NetworkTetheringReported expectedReport =
+ mStatsBuilder.setDownstreamType(DownstreamType.DS_TETHERING_WIFI)
+ .setUserType(expectedResult)
+ .setUpstreamType(UpstreamType.UT_UNKNOWN)
+ .setErrorCode(ErrorCode.EC_NO_ERROR)
+ .build();
+ verify(mTetheringMetrics).write(expectedReport);
+ reset(mTetheringMetrics);
+ }
+ }
+
+ @Test
+ public void testUserTypes() throws Exception {
+ runUserTypesTest(new Pair<>(TEST_CALLER_PKG, UserType.USER_UNKNOWN),
+ new Pair<>(SETTINGS_PKG, UserType.USER_SETTINGS),
+ new Pair<>(SYSTEMUI_PKG, UserType.USER_SYSTEMUI),
+ new Pair<>(GMS_PKG, UserType.USER_GMS));
+ }
+}
diff --git a/bpf_progs/Android.bp b/bpf_progs/Android.bp
index 4fc678f..23af3e3 100644
--- a/bpf_progs/Android.bp
+++ b/bpf_progs/Android.bp
@@ -61,6 +61,7 @@
bpf {
name: "block.o",
srcs: ["block.c"],
+ btf: true,
cflags: [
"-Wall",
"-Werror",
@@ -71,6 +72,7 @@
bpf {
name: "dscp_policy.o",
srcs: ["dscp_policy.c"],
+ btf: true,
cflags: [
"-Wall",
"-Werror",
@@ -99,6 +101,7 @@
bpf {
name: "clatd.o",
srcs: ["clatd.c"],
+ btf: true,
cflags: [
"-Wall",
"-Werror",
@@ -112,6 +115,7 @@
bpf {
name: "netd.o",
srcs: ["netd.c"],
+ btf: true,
cflags: [
"-Wall",
"-Werror",
diff --git a/bpf_progs/block.c b/bpf_progs/block.c
index 601b932..f2a3e62 100644
--- a/bpf_progs/block.c
+++ b/bpf_progs/block.c
@@ -19,8 +19,8 @@
#include <netinet/in.h>
#include <stdint.h>
-// The resulting .o needs to load on the Android T bpfloader v0.12+
-#define BPFLOADER_MIN_VER 12u
+// The resulting .o needs to load on the Android T beta 3 bpfloader
+#define BPFLOADER_MIN_VER BPFLOADER_T_BETA3_VERSION
#include "bpf_helpers.h"
diff --git a/bpf_progs/bpf_shared.h b/bpf_progs/bpf_shared.h
index 14fcdd6..634fbf4 100644
--- a/bpf_progs/bpf_shared.h
+++ b/bpf_progs/bpf_shared.h
@@ -147,9 +147,9 @@
SELECT_MAP_B,
};
-// TODO: change the configuration object from an 8-bit bitmask to an object with clearer
+// TODO: change the configuration object from a bitmask to an object with clearer
// semantics, like a struct.
-typedef uint8_t BpfConfig;
+typedef uint32_t BpfConfig;
static const BpfConfig DEFAULT_CONFIG = 0;
typedef struct {
@@ -160,7 +160,9 @@
} UidOwnerValue;
STRUCT_SIZE(UidOwnerValue, 2 * 4); // 8
+// Entry in the configuration map that stores which UID rules are enabled.
#define UID_RULES_CONFIGURATION_KEY 1
+// Entry in the configuration map that stores which stats map is currently in use.
#define CURRENT_STATS_MAP_CONFIGURATION_KEY 2
#define BPF_CLATD_PATH "/sys/fs/bpf/net_shared/"
diff --git a/bpf_progs/clatd.c b/bpf_progs/clatd.c
index 87795f5..c5b8555 100644
--- a/bpf_progs/clatd.c
+++ b/bpf_progs/clatd.c
@@ -30,8 +30,8 @@
#define __kernel_udphdr udphdr
#include <linux/udp.h>
-// The resulting .o needs to load on the Android T bpfloader v0.12+
-#define BPFLOADER_MIN_VER 12u
+// The resulting .o needs to load on the Android T beta 3 bpfloader
+#define BPFLOADER_MIN_VER BPFLOADER_T_BETA3_VERSION
#include "bpf_helpers.h"
#include "bpf_net_helpers.h"
diff --git a/bpf_progs/dscp_policy.c b/bpf_progs/dscp_policy.c
index 7211f2b..538a9e4 100644
--- a/bpf_progs/dscp_policy.c
+++ b/bpf_progs/dscp_policy.c
@@ -27,8 +27,8 @@
#include <netinet/udp.h>
#include <string.h>
-// The resulting .o needs to load on the Android T bpfloader v0.12+
-#define BPFLOADER_MIN_VER 12u
+// The resulting .o needs to load on the Android T beta 3 bpfloader
+#define BPFLOADER_MIN_VER BPFLOADER_T_BETA3_VERSION
#include "bpf_helpers.h"
#include "dscp_policy.h"
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
index 33381d7..2a63e81 100644
--- a/bpf_progs/netd.c
+++ b/bpf_progs/netd.c
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-// The resulting .o needs to load on the Android T Beta 3 bpfloader v0.13+
-#define BPFLOADER_MIN_VER 13u
+// The resulting .o needs to load on the Android T Beta 3 bpfloader
+#define BPFLOADER_MIN_VER BPFLOADER_T_BETA3_VERSION
#include <bpf_helpers.h>
#include <linux/bpf.h>
@@ -62,7 +62,7 @@
DEFINE_BPF_MAP_GRW(stats_map_B, HASH, StatsKey, StatsValue, STATS_MAP_SIZE, AID_NET_BW_ACCT)
DEFINE_BPF_MAP_GRW(iface_stats_map, HASH, uint32_t, StatsValue, IFACE_STATS_MAP_SIZE,
AID_NET_BW_ACCT)
-DEFINE_BPF_MAP_GRW(configuration_map, HASH, uint32_t, uint8_t, CONFIGURATION_MAP_SIZE,
+DEFINE_BPF_MAP_GRW(configuration_map, HASH, uint32_t, uint32_t, CONFIGURATION_MAP_SIZE,
AID_NET_BW_ACCT)
DEFINE_BPF_MAP_GRW(uid_owner_map, HASH, uint32_t, UidOwnerValue, UID_OWNER_MAP_SIZE,
AID_NET_BW_ACCT)
@@ -234,7 +234,7 @@
}
static __always_inline inline void update_stats_with_config(struct __sk_buff* skb, int direction,
- StatsKey* key, uint8_t selectedMap) {
+ StatsKey* key, uint32_t selectedMap) {
if (selectedMap == SELECT_MAP_A) {
update_stats_map_A(skb, direction, key);
} else if (selectedMap == SELECT_MAP_B) {
@@ -286,7 +286,7 @@
if (counterSet) key.counterSet = (uint32_t)*counterSet;
uint32_t mapSettingKey = CURRENT_STATS_MAP_CONFIGURATION_KEY;
- uint8_t* selectedMap = bpf_configuration_map_lookup_elem(&mapSettingKey);
+ uint32_t* selectedMap = bpf_configuration_map_lookup_elem(&mapSettingKey);
// Use asm("%0 &= 1" : "+r"(match)) before return match,
// to help kernel's bpf verifier, so that it can be 100% certain
@@ -383,8 +383,7 @@
return BPF_NOMATCH;
}
-DEFINE_BPF_PROG_KVER("cgroupsock/inet/create", AID_ROOT, AID_ROOT, inet_socket_create,
- KVER(4, 14, 0))
+DEFINE_BPF_PROG("cgroupsock/inet/create", AID_ROOT, AID_ROOT, inet_socket_create)
(struct bpf_sock* sk) {
uint64_t gid_uid = bpf_get_current_uid_gid();
/*
diff --git a/bpf_progs/offload.c b/bpf_progs/offload.c
index 896bc09..2ec0792 100644
--- a/bpf_progs/offload.c
+++ b/bpf_progs/offload.c
@@ -24,8 +24,8 @@
#define __kernel_udphdr udphdr
#include <linux/udp.h>
-// The resulting .o needs to load on the Android S bpfloader v0.2
-#define BPFLOADER_MIN_VER 2u
+// The resulting .o needs to load on the Android S bpfloader
+#define BPFLOADER_MIN_VER BPFLOADER_S_VERSION
#include "bpf_helpers.h"
#include "bpf_net_helpers.h"
diff --git a/bpf_progs/test.c b/bpf_progs/test.c
index c9c73f1..f2fcc8c 100644
--- a/bpf_progs/test.c
+++ b/bpf_progs/test.c
@@ -18,8 +18,8 @@
#include <linux/in.h>
#include <linux/ip.h>
-// The resulting .o needs to load on the Android S bpfloader v0.2
-#define BPFLOADER_MIN_VER 2u
+// The resulting .o needs to load on the Android S bpfloader
+#define BPFLOADER_MIN_VER BPFLOADER_S_VERSION
#include "bpf_helpers.h"
#include "bpf_net_helpers.h"
diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java
index 886d194..b8070f0 100644
--- a/framework-t/src/android/net/EthernetManager.java
+++ b/framework-t/src/android/net/EthernetManager.java
@@ -22,13 +22,11 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.os.Build;
import android.os.OutcomeReceiver;
import android.os.RemoteException;
@@ -573,7 +571,6 @@
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK,
android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
- @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
public void enableInterface(
@NonNull String iface,
@Nullable @CallbackExecutor Executor executor,
@@ -582,7 +579,7 @@
final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
executor, callback);
try {
- mService.connectNetwork(iface, proxy);
+ mService.enableInterface(iface, proxy);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -610,7 +607,6 @@
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK,
android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
- @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
public void disableInterface(
@NonNull String iface,
@Nullable @CallbackExecutor Executor executor,
@@ -619,7 +615,7 @@
final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
executor, callback);
try {
- mService.disconnectNetwork(iface, proxy);
+ mService.disableInterface(iface, proxy);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/framework-t/src/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl
index 42e4c1a..c1efc29 100644
--- a/framework-t/src/android/net/IEthernetManager.aidl
+++ b/framework-t/src/android/net/IEthernetManager.aidl
@@ -43,8 +43,8 @@
void releaseTetheredInterface(in ITetheredInterfaceCallback callback);
void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request,
in INetworkInterfaceOutcomeReceiver listener);
- void connectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener);
- void disconnectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener);
+ void enableInterface(String iface, in INetworkInterfaceOutcomeReceiver listener);
+ void disableInterface(String iface, in INetworkInterfaceOutcomeReceiver listener);
void setEthernetEnabled(boolean enabled);
List<String> getInterfaceList();
}
diff --git a/framework-t/src/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java
index 9cb0947..9cceac2 100644
--- a/framework-t/src/android/net/IpSecManager.java
+++ b/framework-t/src/android/net/IpSecManager.java
@@ -817,10 +817,10 @@
* </ol>
*
* @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel.
- * This network MUST never be the network exposing this IpSecTunnelInterface, otherwise
- * this method will throw an {@link IllegalArgumentException}. If the
- * IpSecTunnelInterface is later added to this network, all outbound traffic will be
- * blackholed.
+ * This network MUST be a functional {@link Network} with valid {@link LinkProperties},
+ * and MUST never be the network exposing this IpSecTunnelInterface, otherwise this
+ * method will throw an {@link IllegalArgumentException}. If the IpSecTunnelInterface is
+ * later added to this network, all outbound traffic will be blackholed.
*/
// TODO: b/169171001 Update the documentation when transform migration is supported.
// The purpose of making updating network and applying transforms separate is to leave open
@@ -962,7 +962,6 @@
* IP header and IPsec Header on all inbound traffic).
* <p>Applications should probably not use this API directly.
*
- *
* @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied
* transform.
* @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 4ecc8a1..9f9ee95 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -2600,9 +2600,24 @@
* {@hide}
*/
public ConnectivityManager(Context context, IConnectivityManager service) {
+ this(context, service, true /* newStatic */);
+ }
+
+ private ConnectivityManager(Context context, IConnectivityManager service, boolean newStatic) {
mContext = Objects.requireNonNull(context, "missing context");
mService = Objects.requireNonNull(service, "missing IConnectivityManager");
- sInstance = this;
+ // sInstance is accessed without a lock, so it may actually be reassigned several times with
+ // different ConnectivityManager, but that's still OK considering its usage.
+ if (sInstance == null && newStatic) {
+ final Context appContext = mContext.getApplicationContext();
+ // Don't create static ConnectivityManager instance again to prevent infinite loop.
+ // If the application context is null, we're either in the system process or
+ // it's the application context very early in app initialization. In both these
+ // cases, the passed-in Context will not be freed, so it's safe to pass it to the
+ // service. http://b/27532714 .
+ sInstance = new ConnectivityManager(appContext != null ? appContext : context, service,
+ false /* newStatic */);
+ }
}
/** {@hide} */
diff --git a/framework/src/android/net/QosCallbackException.java b/framework/src/android/net/QosCallbackException.java
index ed6eb15..b80cff4 100644
--- a/framework/src/android/net/QosCallbackException.java
+++ b/framework/src/android/net/QosCallbackException.java
@@ -46,8 +46,10 @@
EX_TYPE_FILTER_NONE,
EX_TYPE_FILTER_NETWORK_RELEASED,
EX_TYPE_FILTER_SOCKET_NOT_BOUND,
+ EX_TYPE_FILTER_SOCKET_NOT_CONNECTED,
EX_TYPE_FILTER_NOT_SUPPORTED,
EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED,
+ EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ExceptionType {}
@@ -65,10 +67,16 @@
public static final int EX_TYPE_FILTER_SOCKET_NOT_BOUND = 2;
/** {@hide} */
- public static final int EX_TYPE_FILTER_NOT_SUPPORTED = 3;
+ public static final int EX_TYPE_FILTER_SOCKET_NOT_CONNECTED = 3;
/** {@hide} */
- public static final int EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED = 4;
+ public static final int EX_TYPE_FILTER_NOT_SUPPORTED = 4;
+
+ /** {@hide} */
+ public static final int EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED = 5;
+
+ /** {@hide} */
+ public static final int EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED = 6;
/**
* Creates exception based off of a type and message. Not all types of exceptions accept a
@@ -83,12 +91,17 @@
return new QosCallbackException(new NetworkReleasedException());
case EX_TYPE_FILTER_SOCKET_NOT_BOUND:
return new QosCallbackException(new SocketNotBoundException());
+ case EX_TYPE_FILTER_SOCKET_NOT_CONNECTED:
+ return new QosCallbackException(new SocketNotConnectedException());
case EX_TYPE_FILTER_NOT_SUPPORTED:
return new QosCallbackException(new UnsupportedOperationException(
"This device does not support the specified filter"));
case EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED:
return new QosCallbackException(
new SocketLocalAddressChangedException());
+ case EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED:
+ return new QosCallbackException(
+ new SocketRemoteAddressChangedException());
default:
Log.wtf(TAG, "create: No case setup for exception type: '" + type + "'");
return new QosCallbackException(
diff --git a/framework/src/android/net/QosFilter.java b/framework/src/android/net/QosFilter.java
index 5c1c3cc..b432644 100644
--- a/framework/src/android/net/QosFilter.java
+++ b/framework/src/android/net/QosFilter.java
@@ -90,5 +90,15 @@
*/
public abstract boolean matchesRemoteAddress(@NonNull InetAddress address,
int startPort, int endPort);
+
+ /**
+ * Determines whether or not the parameter will be matched with this filter.
+ *
+ * @param protocol the protocol such as TCP or UDP included in IP packet filter set of a QoS
+ * flow assigned on {@link Network}.
+ * @return whether the parameters match the socket type of the filter
+ * @hide
+ */
+ public abstract boolean matchesProtocol(int protocol);
}
diff --git a/framework/src/android/net/QosFilterParcelable.java b/framework/src/android/net/QosFilterParcelable.java
index da3b2cf..6e71fa3 100644
--- a/framework/src/android/net/QosFilterParcelable.java
+++ b/framework/src/android/net/QosFilterParcelable.java
@@ -104,7 +104,7 @@
if (mQosFilter instanceof QosSocketFilter) {
dest.writeInt(QOS_SOCKET_FILTER);
final QosSocketFilter qosSocketFilter = (QosSocketFilter) mQosFilter;
- qosSocketFilter.getQosSocketInfo().writeToParcel(dest, 0);
+ qosSocketFilter.getQosSocketInfo().writeToParcelWithoutFd(dest, 0);
return;
}
dest.writeInt(NO_FILTER_PRESENT);
diff --git a/framework/src/android/net/QosSocketFilter.java b/framework/src/android/net/QosSocketFilter.java
index 69da7f4..5ceeb67 100644
--- a/framework/src/android/net/QosSocketFilter.java
+++ b/framework/src/android/net/QosSocketFilter.java
@@ -18,6 +18,13 @@
import static android.net.QosCallbackException.EX_TYPE_FILTER_NONE;
import static android.net.QosCallbackException.EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED;
+import static android.net.QosCallbackException.EX_TYPE_FILTER_SOCKET_NOT_BOUND;
+import static android.net.QosCallbackException.EX_TYPE_FILTER_SOCKET_NOT_CONNECTED;
+import static android.net.QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED;
+import static android.system.OsConstants.IPPROTO_TCP;
+import static android.system.OsConstants.IPPROTO_UDP;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_STREAM;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -74,19 +81,34 @@
* 2. In the scenario that the socket is now bound to a different local address, which can
* happen in the case of UDP, then
* {@link QosCallbackException.EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED} is returned.
+ * 3. In the scenario that the UDP socket changed remote address, then
+ * {@link QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED} is returned.
+ *
* @return validation error code
*/
@Override
public int validate() {
- final InetSocketAddress sa = getAddressFromFileDescriptor();
- if (sa == null) {
- return QosCallbackException.EX_TYPE_FILTER_SOCKET_NOT_BOUND;
+ final InetSocketAddress sa = getLocalAddressFromFileDescriptor();
+
+ if (sa == null || (sa.getAddress().isAnyLocalAddress() && sa.getPort() == 0)) {
+ return EX_TYPE_FILTER_SOCKET_NOT_BOUND;
}
if (!sa.equals(mQosSocketInfo.getLocalSocketAddress())) {
return EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED;
}
+ if (mQosSocketInfo.getRemoteSocketAddress() != null) {
+ final InetSocketAddress da = getRemoteAddressFromFileDescriptor();
+ if (da == null) {
+ return EX_TYPE_FILTER_SOCKET_NOT_CONNECTED;
+ }
+
+ if (!da.equals(mQosSocketInfo.getRemoteSocketAddress())) {
+ return EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED;
+ }
+ }
+
return EX_TYPE_FILTER_NONE;
}
@@ -98,17 +120,14 @@
* @return the local address
*/
@Nullable
- private InetSocketAddress getAddressFromFileDescriptor() {
+ private InetSocketAddress getLocalAddressFromFileDescriptor() {
final ParcelFileDescriptor parcelFileDescriptor = mQosSocketInfo.getParcelFileDescriptor();
- if (parcelFileDescriptor == null) return null;
-
final FileDescriptor fd = parcelFileDescriptor.getFileDescriptor();
- if (fd == null) return null;
final SocketAddress address;
try {
address = Os.getsockname(fd);
- } catch (final ErrnoException e) {
+ } catch (ErrnoException e) {
Log.e(TAG, "getAddressFromFileDescriptor: getLocalAddress exception", e);
return null;
}
@@ -119,6 +138,31 @@
}
/**
+ * The remote address of the socket's connected.
+ *
+ * <p>Note: If the socket is no longer connected, null is returned.
+ *
+ * @return the remote address
+ */
+ @Nullable
+ private InetSocketAddress getRemoteAddressFromFileDescriptor() {
+ final ParcelFileDescriptor parcelFileDescriptor = mQosSocketInfo.getParcelFileDescriptor();
+ final FileDescriptor fd = parcelFileDescriptor.getFileDescriptor();
+
+ final SocketAddress address;
+ try {
+ address = Os.getpeername(fd);
+ } catch (ErrnoException e) {
+ Log.e(TAG, "getAddressFromFileDescriptor: getRemoteAddress exception", e);
+ return null;
+ }
+ if (address instanceof InetSocketAddress) {
+ return (InetSocketAddress) address;
+ }
+ return null;
+ }
+
+ /**
* The network used with this filter.
*
* @return the registered {@link Network}
@@ -156,6 +200,18 @@
}
/**
+ * @inheritDoc
+ */
+ @Override
+ public boolean matchesProtocol(final int protocol) {
+ if ((mQosSocketInfo.getSocketType() == SOCK_STREAM && protocol == IPPROTO_TCP)
+ || (mQosSocketInfo.getSocketType() == SOCK_DGRAM && protocol == IPPROTO_UDP)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Called from {@link QosSocketFilter#matchesLocalAddress(InetAddress, int, int)}
* and {@link QosSocketFilter#matchesRemoteAddress(InetAddress, int, int)} with the
* filterSocketAddress coming from {@link QosSocketInfo#getLocalSocketAddress()}.
@@ -174,6 +230,7 @@
final int startPort, final int endPort) {
return startPort <= filterSocketAddress.getPort()
&& endPort >= filterSocketAddress.getPort()
- && filterSocketAddress.getAddress().equals(address);
+ && (address.isAnyLocalAddress()
+ || filterSocketAddress.getAddress().equals(address));
}
}
diff --git a/framework/src/android/net/QosSocketInfo.java b/framework/src/android/net/QosSocketInfo.java
index 39c2f33..49ac22b 100644
--- a/framework/src/android/net/QosSocketInfo.java
+++ b/framework/src/android/net/QosSocketInfo.java
@@ -165,25 +165,28 @@
/* Parcelable methods */
private QosSocketInfo(final Parcel in) {
mNetwork = Objects.requireNonNull(Network.CREATOR.createFromParcel(in));
- mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in);
+ final boolean withFd = in.readBoolean();
+ if (withFd) {
+ mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in);
+ } else {
+ mParcelFileDescriptor = null;
+ }
- final int localAddressLength = in.readInt();
- mLocalSocketAddress = readSocketAddress(in, localAddressLength);
-
- final int remoteAddressLength = in.readInt();
- mRemoteSocketAddress = remoteAddressLength == 0 ? null
- : readSocketAddress(in, remoteAddressLength);
+ mLocalSocketAddress = readSocketAddress(in);
+ mRemoteSocketAddress = readSocketAddress(in);
mSocketType = in.readInt();
}
- private @NonNull InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) {
- final byte[] address = new byte[addressLength];
- in.readByteArray(address);
+ private InetSocketAddress readSocketAddress(final Parcel in) {
+ final byte[] addrBytes = in.createByteArray();
+ if (addrBytes == null) {
+ return null;
+ }
final int port = in.readInt();
try {
- return new InetSocketAddress(InetAddress.getByAddress(address), port);
+ return new InetSocketAddress(InetAddress.getByAddress(addrBytes), port);
} catch (final UnknownHostException e) {
/* This can never happen. UnknownHostException will never be thrown
since the address provided is numeric and non-null. */
@@ -198,20 +201,35 @@
@Override
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
- mNetwork.writeToParcel(dest, 0);
- mParcelFileDescriptor.writeToParcel(dest, 0);
+ writeToParcelInternal(dest, flags, /*includeFd=*/ true);
+ }
- final byte[] localAddress = mLocalSocketAddress.getAddress().getAddress();
- dest.writeInt(localAddress.length);
- dest.writeByteArray(localAddress);
+ /**
+ * Used when sending QosSocketInfo to telephony, which does not need access to the socket FD.
+ * @hide
+ */
+ public void writeToParcelWithoutFd(@NonNull final Parcel dest, final int flags) {
+ writeToParcelInternal(dest, flags, /*includeFd=*/ false);
+ }
+
+ private void writeToParcelInternal(
+ @NonNull final Parcel dest, final int flags, boolean includeFd) {
+ mNetwork.writeToParcel(dest, 0);
+
+ if (includeFd) {
+ dest.writeBoolean(true);
+ mParcelFileDescriptor.writeToParcel(dest, 0);
+ } else {
+ dest.writeBoolean(false);
+ }
+
+ dest.writeByteArray(mLocalSocketAddress.getAddress().getAddress());
dest.writeInt(mLocalSocketAddress.getPort());
if (mRemoteSocketAddress == null) {
- dest.writeInt(0);
+ dest.writeByteArray(null);
} else {
- final byte[] remoteAddress = mRemoteSocketAddress.getAddress().getAddress();
- dest.writeInt(remoteAddress.length);
- dest.writeByteArray(remoteAddress);
+ dest.writeByteArray(mRemoteSocketAddress.getAddress().getAddress());
dest.writeInt(mRemoteSocketAddress.getPort());
}
dest.writeInt(mSocketType);
diff --git a/framework/src/android/net/SocketNotConnectedException.java b/framework/src/android/net/SocketNotConnectedException.java
new file mode 100644
index 0000000..fa2a615
--- /dev/null
+++ b/framework/src/android/net/SocketNotConnectedException.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 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;
+
+/**
+ * Thrown when a previously bound socket becomes unbound.
+ *
+ * @hide
+ */
+public class SocketNotConnectedException extends Exception {
+ /** @hide */
+ public SocketNotConnectedException() {
+ super("The socket is not connected");
+ }
+}
diff --git a/framework/src/android/net/SocketRemoteAddressChangedException.java b/framework/src/android/net/SocketRemoteAddressChangedException.java
new file mode 100644
index 0000000..ecaeebc
--- /dev/null
+++ b/framework/src/android/net/SocketRemoteAddressChangedException.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 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;
+
+/**
+ * Thrown when the local address of the socket has changed.
+ *
+ * @hide
+ */
+public class SocketRemoteAddressChangedException extends Exception {
+ /** @hide */
+ public SocketRemoteAddressChangedException() {
+ super("The remote address of the socket changed");
+ }
+}
diff --git a/netd/Android.bp b/netd/Android.bp
index 5ac02d3..c731b8b 100644
--- a/netd/Android.bp
+++ b/netd/Android.bp
@@ -55,7 +55,8 @@
cc_test {
name: "netd_updatable_unit_test",
defaults: ["netd_defaults"],
- test_suites: ["general-tests"],
+ test_suites: ["general-tests", "mts-tethering"],
+ test_config_template: ":net_native_test_config_template",
require_root: true, // required by setrlimitForTest()
header_libs: [
"bpf_connectivity_headers",
@@ -72,6 +73,7 @@
"liblog",
"libnetdutils",
],
+ compile_multilib: "both",
multilib: {
lib32: {
suffix: "32",
diff --git a/netd/BpfHandler.cpp b/netd/BpfHandler.cpp
index f3dfb57..42d0de5 100644
--- a/netd/BpfHandler.cpp
+++ b/netd/BpfHandler.cpp
@@ -73,16 +73,7 @@
}
RETURN_IF_NOT_OK(attachProgramToCgroup(BPF_EGRESS_PROG_PATH, cg_fd, BPF_CGROUP_INET_EGRESS));
RETURN_IF_NOT_OK(attachProgramToCgroup(BPF_INGRESS_PROG_PATH, cg_fd, BPF_CGROUP_INET_INGRESS));
-
- // For the devices that support cgroup socket filter, the socket filter
- // should be loaded successfully by bpfloader. So we attach the filter to
- // cgroup if the program is pinned properly.
- // TODO: delete the if statement once all devices should support cgroup
- // socket filter (ie. the minimum kernel version required is 4.14).
- if (!access(CGROUP_SOCKET_PROG_PATH, F_OK)) {
- RETURN_IF_NOT_OK(
- attachProgramToCgroup(CGROUP_SOCKET_PROG_PATH, cg_fd, BPF_CGROUP_INET_SOCK_CREATE));
- }
+ RETURN_IF_NOT_OK(attachProgramToCgroup(CGROUP_SOCKET_PROG_PATH, cg_fd, BPF_CGROUP_INET_SOCK_CREATE));
return netdutils::status::ok;
}
@@ -113,6 +104,7 @@
RETURN_IF_NOT_OK(mConfigurationMap.writeValue(CURRENT_STATS_MAP_CONFIGURATION_KEY, SELECT_MAP_A,
BPF_ANY));
RETURN_IF_NOT_OK(mUidPermissionMap.init(UID_PERMISSION_MAP_PATH));
+ ALOGI("%s successfully", __func__);
return netdutils::status::ok;
}
@@ -242,7 +234,7 @@
if (sock_cookie == NONEXISTENT_COOKIE) return -errno;
base::Result<void> res = mCookieTagMap.deleteValue(sock_cookie);
if (!res.ok()) {
- ALOGE("Failed to untag socket: %s\n", strerror(res.error().code()));
+ ALOGE("Failed to untag socket: %s", strerror(res.error().code()));
return -res.error().code();
}
return 0;
diff --git a/netd/BpfHandler.h b/netd/BpfHandler.h
index 2ede1c1..05b9ebc 100644
--- a/netd/BpfHandler.h
+++ b/netd/BpfHandler.h
@@ -62,7 +62,7 @@
BpfMap<uint64_t, UidTagValue> mCookieTagMap;
BpfMap<StatsKey, StatsValue> mStatsMapA;
BpfMap<StatsKey, StatsValue> mStatsMapB;
- BpfMap<uint32_t, uint8_t> mConfigurationMap;
+ BpfMap<uint32_t, uint32_t> mConfigurationMap;
BpfMap<uint32_t, uint8_t> mUidPermissionMap;
std::mutex mMutex;
diff --git a/netd/BpfHandlerTest.cpp b/netd/BpfHandlerTest.cpp
index cd6b565..12ae916 100644
--- a/netd/BpfHandlerTest.cpp
+++ b/netd/BpfHandlerTest.cpp
@@ -48,7 +48,7 @@
BpfHandler mBh;
BpfMap<uint64_t, UidTagValue> mFakeCookieTagMap;
BpfMap<StatsKey, StatsValue> mFakeStatsMapA;
- BpfMap<uint32_t, uint8_t> mFakeConfigurationMap;
+ BpfMap<uint32_t, uint32_t> mFakeConfigurationMap;
BpfMap<uint32_t, uint8_t> mFakeUidPermissionMap;
void SetUp() {
diff --git a/service-t/native/libs/libnetworkstats/Android.bp b/service-t/native/libs/libnetworkstats/Android.bp
index bf56fd5..5b3d314 100644
--- a/service-t/native/libs/libnetworkstats/Android.bp
+++ b/service-t/native/libs/libnetworkstats/Android.bp
@@ -48,7 +48,8 @@
cc_test {
name: "libnetworkstats_test",
- test_suites: ["general-tests"],
+ test_suites: ["general-tests", "mts-tethering"],
+ test_config_template: ":net_native_test_config_template",
require_root: true, // required by setrlimitForTest()
header_libs: ["bpf_connectivity_headers"],
srcs: [
@@ -68,4 +69,13 @@
"libbase",
"liblog",
],
+ compile_multilib: "both",
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
}
diff --git a/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
index 4d605ce..c67821f 100644
--- a/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
+++ b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
@@ -193,7 +193,7 @@
return ret;
}
- BpfMapRO<uint32_t, uint8_t> configurationMap(CONFIGURATION_MAP_PATH);
+ BpfMapRO<uint32_t, uint32_t> configurationMap(CONFIGURATION_MAP_PATH);
if (!configurationMap.isValid()) {
int ret = -errno;
ALOGE("get configuration map fd failed: %s", strerror(errno));
@@ -205,6 +205,10 @@
configuration.error().message().c_str());
return -configuration.error().code();
}
+ if (configuration.value() != SELECT_MAP_A && configuration.value() != SELECT_MAP_B) {
+ ALOGE("%s unknown configuration value: %d", __func__, configuration.value());
+ return -EINVAL;
+ }
const char* statsMapPath = STATS_MAP_PATH[configuration.value()];
BpfMap<StatsKey, StatsValue> statsMap(statsMapPath);
if (!statsMap.isValid()) {
diff --git a/service-t/src/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java
index 4bc40ea..16b9f1e 100644
--- a/service-t/src/com/android/server/IpSecService.java
+++ b/service-t/src/com/android/server/IpSecService.java
@@ -1452,6 +1452,11 @@
final ConnectivityManager connectivityManager =
mContext.getSystemService(ConnectivityManager.class);
final LinkProperties lp = connectivityManager.getLinkProperties(underlyingNetwork);
+ if (lp == null) {
+ throw new IllegalArgumentException(
+ "LinkProperties is null. The underlyingNetwork may not be functional");
+ }
+
if (tunnelInterfaceInfo.getInterfaceName().equals(lp.getInterfaceName())) {
throw new IllegalArgumentException(
"Underlying network cannot be the network being exposed by this tunnel");
diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
index 5e830ad..71d3e4f 100644
--- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
+++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
@@ -22,11 +22,11 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.net.EthernetNetworkUpdateRequest;
import android.net.IEthernetManager;
import android.net.IEthernetServiceListener;
import android.net.INetworkInterfaceOutcomeReceiver;
import android.net.ITetheredInterfaceCallback;
-import android.net.EthernetNetworkUpdateRequest;
import android.net.IpConfiguration;
import android.net.NetworkCapabilities;
import android.os.Binder;
@@ -260,27 +260,27 @@
}
@Override
- public void connectNetwork(@NonNull final String iface,
+ public void enableInterface(@NonNull final String iface,
@Nullable final INetworkInterfaceOutcomeReceiver listener) {
- Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener);
+ Log.i(TAG, "enableInterface called with: iface=" + iface + ", listener=" + listener);
Objects.requireNonNull(iface);
throwIfEthernetNotStarted();
- enforceAdminPermission(iface, true, "connectNetwork()");
+ enforceAdminPermission(iface, false, "enableInterface()");
- mTracker.connectNetwork(iface, listener);
+ mTracker.enableInterface(iface, listener);
}
@Override
- public void disconnectNetwork(@NonNull final String iface,
+ public void disableInterface(@NonNull final String iface,
@Nullable final INetworkInterfaceOutcomeReceiver listener) {
- Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener);
+ Log.i(TAG, "disableInterface called with: iface=" + iface + ", listener=" + listener);
Objects.requireNonNull(iface);
throwIfEthernetNotStarted();
- enforceAdminPermission(iface, true, "connectNetwork()");
+ enforceAdminPermission(iface, false, "disableInterface()");
- mTracker.disconnectNetwork(iface, listener);
+ mTracker.disableInterface(iface, listener);
}
@Override
diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java
index 709b774..f701ed2 100644
--- a/service-t/src/com/android/server/ethernet/EthernetTracker.java
+++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java
@@ -286,13 +286,13 @@
}
@VisibleForTesting(visibility = PACKAGE)
- protected void connectNetwork(@NonNull final String iface,
+ protected void enableInterface(@NonNull final String iface,
@Nullable final INetworkInterfaceOutcomeReceiver listener) {
mHandler.post(() -> updateInterfaceState(iface, true, listener));
}
@VisibleForTesting(visibility = PACKAGE)
- protected void disconnectNetwork(@NonNull final String iface,
+ protected void disableInterface(@NonNull final String iface,
@Nullable final INetworkInterfaceOutcomeReceiver listener) {
mHandler.post(() -> updateInterfaceState(iface, false, listener));
}
diff --git a/service/jni/com_android_server_BpfNetMaps.cpp b/service/jni/com_android_server_BpfNetMaps.cpp
index 7b1f59c..bc70c93 100644
--- a/service/jni/com_android_server_BpfNetMaps.cpp
+++ b/service/jni/com_android_server_BpfNetMaps.cpp
@@ -39,152 +39,126 @@
namespace android {
-static void native_init(JNIEnv* env, jobject clazz) {
+#define CHECK_LOG(status) \
+ do { \
+ if (!isOk(status)) \
+ ALOGE("%s failed, error code = %d", __func__, status.code()); \
+ } while (0)
+
+static void native_init(JNIEnv* env, jclass clazz) {
Status status = mTc.start();
- if (!isOk(status)) {
- ALOGE("%s failed, error code = %d", __func__, status.code());
- }
+ CHECK_LOG(status);
}
-static jint native_addNaughtyApp(JNIEnv* env, jobject clazz, jint uid) {
+static jint native_addNaughtyApp(JNIEnv* env, jobject self, jint uid) {
const uint32_t appUids = static_cast<uint32_t>(abs(uid));
Status status = mTc.updateUidOwnerMap(appUids, PENALTY_BOX_MATCH,
TrafficController::IptOp::IptOpInsert);
- if (!isOk(status)) {
- ALOGE("%s failed, error code = %d", __func__, status.code());
- }
+ CHECK_LOG(status);
return (jint)status.code();
}
-static jint native_removeNaughtyApp(JNIEnv* env, jobject clazz, jint uid) {
+static jint native_removeNaughtyApp(JNIEnv* env, jobject self, jint uid) {
const uint32_t appUids = static_cast<uint32_t>(abs(uid));
Status status = mTc.updateUidOwnerMap(appUids, PENALTY_BOX_MATCH,
TrafficController::IptOp::IptOpDelete);
- if (!isOk(status)) {
- ALOGE("%s failed, error code = %d", __func__, status.code());
- }
+ CHECK_LOG(status);
return (jint)status.code();
}
-static jint native_addNiceApp(JNIEnv* env, jobject clazz, jint uid) {
+static jint native_addNiceApp(JNIEnv* env, jobject self, jint uid) {
const uint32_t appUids = static_cast<uint32_t>(abs(uid));
Status status = mTc.updateUidOwnerMap(appUids, HAPPY_BOX_MATCH,
TrafficController::IptOp::IptOpInsert);
- if (!isOk(status)) {
- ALOGE("%s failed, error code = %d", __func__, status.code());
- }
+ CHECK_LOG(status);
return (jint)status.code();
}
-static jint native_removeNiceApp(JNIEnv* env, jobject clazz, jint uid) {
+static jint native_removeNiceApp(JNIEnv* env, jobject self, jint uid) {
const uint32_t appUids = static_cast<uint32_t>(abs(uid));
Status status = mTc.updateUidOwnerMap(appUids, HAPPY_BOX_MATCH,
TrafficController::IptOp::IptOpDelete);
- if (!isOk(status)) {
- ALOGD("%s failed, error code = %d", __func__, status.code());
- }
+ CHECK_LOG(status);
return (jint)status.code();
}
-static jint native_setChildChain(JNIEnv* env, jobject clazz, jint childChain, jboolean enable) {
+static jint native_setChildChain(JNIEnv* env, jobject self, jint childChain, jboolean enable) {
auto chain = static_cast<ChildChain>(childChain);
int res = mTc.toggleUidOwnerMap(chain, enable);
- if (res) {
- ALOGE("%s failed, error code = %d", __func__, res);
- }
+ if (res) ALOGE("%s failed, error code = %d", __func__, res);
return (jint)res;
}
-static jint native_replaceUidChain(JNIEnv* env, jobject clazz, jstring name, jboolean isAllowlist,
- jintArray jUids) {
+static jint native_replaceUidChain(JNIEnv* env, jobject self, jstring name, jboolean isAllowlist,
+ jintArray jUids) {
const ScopedUtfChars chainNameUtf8(env, name);
- if (chainNameUtf8.c_str() == nullptr) {
- return -EINVAL;
- }
+ if (chainNameUtf8.c_str() == nullptr) return -EINVAL;
const std::string chainName(chainNameUtf8.c_str());
ScopedIntArrayRO uids(env, jUids);
- if (uids.get() == nullptr) {
- return -EINVAL;
- }
+ if (uids.get() == nullptr) return -EINVAL;
size_t size = uids.size();
static_assert(sizeof(*(uids.get())) == sizeof(int32_t));
std::vector<int32_t> data ((int32_t *)&uids[0], (int32_t*)&uids[size]);
int res = mTc.replaceUidOwnerMap(chainName, isAllowlist, data);
- if (res) {
- ALOGE("%s failed, error code = %d", __func__, res);
- }
+ if (res) ALOGE("%s failed, error code = %d", __func__, res);
return (jint)res;
}
-static jint native_setUidRule(JNIEnv* env, jobject clazz, jint childChain, jint uid,
- jint firewallRule) {
+static jint native_setUidRule(JNIEnv* env, jobject self, jint childChain, jint uid,
+ jint firewallRule) {
auto chain = static_cast<ChildChain>(childChain);
auto rule = static_cast<FirewallRule>(firewallRule);
FirewallType fType = mTc.getFirewallType(chain);
int res = mTc.changeUidOwnerRule(chain, uid, rule, fType);
- if (res) {
- ALOGE("%s failed, error code = %d", __func__, res);
- }
+ if (res) ALOGE("%s failed, error code = %d", __func__, res);
return (jint)res;
}
-static jint native_addUidInterfaceRules(JNIEnv* env, jobject clazz, jstring ifName,
- jintArray jUids) {
+static jint native_addUidInterfaceRules(JNIEnv* env, jobject self, jstring ifName,
+ jintArray jUids) {
// Null ifName is a wildcard to allow apps to receive packets on all interfaces and ifIndex is
// set to 0.
- int ifIndex;
+ int ifIndex = 0;
if (ifName != nullptr) {
const ScopedUtfChars ifNameUtf8(env, ifName);
const std::string interfaceName(ifNameUtf8.c_str());
ifIndex = if_nametoindex(interfaceName.c_str());
- } else {
- ifIndex = 0;
}
ScopedIntArrayRO uids(env, jUids);
- if (uids.get() == nullptr) {
- return -EINVAL;
- }
+ if (uids.get() == nullptr) return -EINVAL;
size_t size = uids.size();
static_assert(sizeof(*(uids.get())) == sizeof(int32_t));
std::vector<int32_t> data ((int32_t *)&uids[0], (int32_t*)&uids[size]);
Status status = mTc.addUidInterfaceRules(ifIndex, data);
- if (!isOk(status)) {
- ALOGE("%s failed, error code = %d", __func__, status.code());
- }
+ CHECK_LOG(status);
return (jint)status.code();
}
-static jint native_removeUidInterfaceRules(JNIEnv* env, jobject clazz, jintArray jUids) {
+static jint native_removeUidInterfaceRules(JNIEnv* env, jobject self, jintArray jUids) {
ScopedIntArrayRO uids(env, jUids);
- if (uids.get() == nullptr) {
- return -EINVAL;
- }
+ if (uids.get() == nullptr) return -EINVAL;
size_t size = uids.size();
static_assert(sizeof(*(uids.get())) == sizeof(int32_t));
std::vector<int32_t> data ((int32_t *)&uids[0], (int32_t*)&uids[size]);
Status status = mTc.removeUidInterfaceRules(data);
- if (!isOk(status)) {
- ALOGE("%s failed, error code = %d", __func__, status.code());
- }
+ CHECK_LOG(status);
return (jint)status.code();
}
-static jint native_swapActiveStatsMap(JNIEnv* env, jobject clazz) {
+static jint native_swapActiveStatsMap(JNIEnv* env, jobject self) {
Status status = mTc.swapActiveStatsMap();
- if (!isOk(status)) {
- ALOGD("%s failed, error code = %d", __func__, status.code());
- }
+ CHECK_LOG(status);
return (jint)status.code();
}
-static void native_setPermissionForUids(JNIEnv* env, jobject clazz, jint permission,
- jintArray jUids) {
+static void native_setPermissionForUids(JNIEnv* env, jobject self, jint permission,
+ jintArray jUids) {
ScopedIntArrayRO uids(env, jUids);
if (uids.get() == nullptr) return;
@@ -194,7 +168,7 @@
mTc.setPermissionForUids(permission, data);
}
-static void native_dump(JNIEnv* env, jobject clazz, jobject javaFd, jboolean verbose) {
+static void native_dump(JNIEnv* env, jobject self, jobject javaFd, jboolean verbose) {
int fd = netjniutils::GetNativeFileDescriptor(env, javaFd);
if (fd < 0) {
jniThrowExceptionFmt(env, "java/io/IOException", "Invalid file descriptor");
@@ -239,9 +213,8 @@
// clang-format on
int register_com_android_server_BpfNetMaps(JNIEnv* env) {
- return jniRegisterNativeMethods(env,
- "com/android/server/BpfNetMaps",
- gMethods, NELEM(gMethods));
+ return jniRegisterNativeMethods(env, "com/android/server/BpfNetMaps",
+ gMethods, NELEM(gMethods));
}
}; // namespace android
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index ba836b2..e2c5a63 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -315,10 +315,7 @@
// TODO: use android::base::ScopeGuard.
if (int ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_USEVFORK
-#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT
- | POSIX_SPAWN_CLOEXEC_DEFAULT
-#endif
- )) {
+ | POSIX_SPAWN_CLOEXEC_DEFAULT)) {
posix_spawnattr_destroy(&attr);
throwIOException(env, "posix_spawnattr_setflags failed", ret);
return -1;
diff --git a/service/native/Android.bp b/service/native/Android.bp
index cb26bc3..697fcbd 100644
--- a/service/native/Android.bp
+++ b/service/native/Android.bp
@@ -52,7 +52,8 @@
cc_test {
name: "traffic_controller_unit_test",
- test_suites: ["general-tests"],
+ test_suites: ["general-tests", "mts-tethering"],
+ test_config_template: ":net_native_test_config_template",
require_root: true,
local_include_dirs: ["include"],
header_libs: [
@@ -71,4 +72,13 @@
"libnetd_updatable",
"netd_aidl_interface-lateststable-ndk",
],
+ compile_multilib: "both",
+ multilib: {
+ lib32: {
+ suffix: "32",
+ },
+ lib64: {
+ suffix: "64",
+ },
+ },
}
diff --git a/service/native/TrafficController.cpp b/service/native/TrafficController.cpp
index 5581c40..55db393 100644
--- a/service/native/TrafficController.cpp
+++ b/service/native/TrafficController.cpp
@@ -184,6 +184,7 @@
RETURN_IF_NOT_OK(mUidOwnerMap.init(UID_OWNER_MAP_PATH));
RETURN_IF_NOT_OK(mUidOwnerMap.clear());
RETURN_IF_NOT_OK(mUidPermissionMap.init(UID_PERMISSION_MAP_PATH));
+ ALOGI("%s successfully", __func__);
return netdutils::status::ok;
}
@@ -454,15 +455,15 @@
int TrafficController::toggleUidOwnerMap(ChildChain chain, bool enable) {
std::lock_guard guard(mMutex);
uint32_t key = UID_RULES_CONFIGURATION_KEY;
- auto oldConfiguration = mConfigurationMap.readValue(key);
- if (!oldConfiguration.ok()) {
+ auto oldConfigure = mConfigurationMap.readValue(key);
+ if (!oldConfigure.ok()) {
ALOGE("Cannot read the old configuration from map: %s",
- oldConfiguration.error().message().c_str());
- return -oldConfiguration.error().code();
+ oldConfigure.error().message().c_str());
+ return -oldConfigure.error().code();
}
Status res;
BpfConfig newConfiguration;
- uint8_t match;
+ uint32_t match;
switch (chain) {
case DOZABLE:
match = DOZABLE_MATCH;
@@ -483,7 +484,7 @@
return -EINVAL;
}
newConfiguration =
- enable ? (oldConfiguration.value() | match) : (oldConfiguration.value() & (~match));
+ enable ? (oldConfigure.value() | match) : (oldConfigure.value() & (~match));
res = mConfigurationMap.writeValue(key, newConfiguration, BPF_EXIST);
if (!isOk(res)) {
ALOGE("Failed to toggleUidOwnerMap(%d): %s", chain, res.msg().c_str());
@@ -495,17 +496,17 @@
std::lock_guard guard(mMutex);
uint32_t key = CURRENT_STATS_MAP_CONFIGURATION_KEY;
- auto oldConfiguration = mConfigurationMap.readValue(key);
- if (!oldConfiguration.ok()) {
+ auto oldConfigure = mConfigurationMap.readValue(key);
+ if (!oldConfigure.ok()) {
ALOGE("Cannot read the old configuration from map: %s",
- oldConfiguration.error().message().c_str());
- return Status(oldConfiguration.error().code(), oldConfiguration.error().message());
+ oldConfigure.error().message().c_str());
+ return Status(oldConfigure.error().code(), oldConfigure.error().message());
}
// Write to the configuration map to inform the kernel eBPF program to switch
// from using one map to the other. Use flag BPF_EXIST here since the map should
// be already populated in initMaps.
- uint8_t newConfigure = (oldConfiguration.value() == SELECT_MAP_A) ? SELECT_MAP_B : SELECT_MAP_A;
+ uint32_t newConfigure = (oldConfigure.value() == SELECT_MAP_A) ? SELECT_MAP_B : SELECT_MAP_A;
auto res = mConfigurationMap.writeValue(CURRENT_STATS_MAP_CONFIGURATION_KEY, newConfigure,
BPF_EXIST);
if (!res.ok()) {
diff --git a/service/native/TrafficControllerTest.cpp b/service/native/TrafficControllerTest.cpp
index ad53cb8..96bd57c 100644
--- a/service/native/TrafficControllerTest.cpp
+++ b/service/native/TrafficControllerTest.cpp
@@ -65,7 +65,7 @@
BpfMap<uint64_t, UidTagValue> mFakeCookieTagMap;
BpfMap<uint32_t, StatsValue> mFakeAppUidStatsMap;
BpfMap<StatsKey, StatsValue> mFakeStatsMapA;
- BpfMap<uint32_t, uint8_t> mFakeConfigurationMap;
+ BpfMap<uint32_t, uint32_t> mFakeConfigurationMap;
BpfMap<uint32_t, UidOwnerValue> mFakeUidOwnerMap;
BpfMap<uint32_t, uint8_t> mFakeUidPermissionMap;
@@ -685,7 +685,7 @@
if (res.ok() || (res.error().code() == ENOENT)) {
return Result<void>();
}
- ALOGE("Failed to delete data(cookie = %" PRIu64 "): %s\n", key,
+ ALOGE("Failed to delete data(cookie = %" PRIu64 "): %s", key,
strerror(res.error().code()));
}
// Move forward to next cookie in the map.
diff --git a/service/native/include/TrafficController.h b/service/native/include/TrafficController.h
index 79e75ac..d3d52e2 100644
--- a/service/native/include/TrafficController.h
+++ b/service/native/include/TrafficController.h
@@ -155,7 +155,7 @@
* Userspace can do scraping and cleaning job on the other one depending on the
* current configs.
*/
- bpf::BpfMap<uint32_t, uint8_t> mConfigurationMap GUARDED_BY(mMutex);
+ bpf::BpfMap<uint32_t, uint32_t> mConfigurationMap GUARDED_BY(mMutex);
/*
* mUidOwnerMap: Store uids that are used for bandwidth control uid match.
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 0a6c2bd..638e8ec 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -3428,6 +3428,10 @@
for (NetworkAgentInfo nai : networksSortedById()) {
pw.println(nai.toString());
pw.increaseIndent();
+ pw.println("Nat464Xlat:");
+ pw.increaseIndent();
+ nai.dumpNat464Xlat(pw);
+ pw.decreaseIndent();
pw.println(String.format(
"Requests: REQUEST:%d LISTEN:%d BACKGROUND_REQUEST:%d total:%d",
nai.numForegroundNetworkRequests(),
@@ -3443,10 +3447,6 @@
pw.increaseIndent();
nai.dumpInactivityTimers(pw);
pw.decreaseIndent();
- pw.println("Nat464Xlat:");
- pw.increaseIndent();
- nai.dumpNat464Xlat(pw);
- pw.decreaseIndent();
pw.decreaseIndent();
}
}
@@ -3872,7 +3872,6 @@
}
final boolean wasValidated = nai.lastValidated;
- final boolean wasDefault = isDefaultNetwork(nai);
final boolean wasPartial = nai.partialConnectivity;
nai.partialConnectivity = ((testResult & NETWORK_VALIDATION_RESULT_PARTIAL) != 0);
final boolean partialConnectivityChanged =
diff --git a/service/src/com/android/server/connectivity/Nat464Xlat.java b/service/src/com/android/server/connectivity/Nat464Xlat.java
index e8fc06d..738caab 100644
--- a/service/src/com/android/server/connectivity/Nat464Xlat.java
+++ b/service/src/com/android/server/connectivity/Nat464Xlat.java
@@ -540,7 +540,7 @@
mClatCoordinator.dump(pw);
pw.decreaseIndent();
} else {
- pw.println("<not start>");
+ pw.println("<not started>");
}
}
}
diff --git a/service/src/com/android/server/connectivity/QosCallbackAgentConnection.java b/service/src/com/android/server/connectivity/QosCallbackAgentConnection.java
index 534dbe7..e682026 100644
--- a/service/src/com/android/server/connectivity/QosCallbackAgentConnection.java
+++ b/service/src/com/android/server/connectivity/QosCallbackAgentConnection.java
@@ -30,6 +30,8 @@
import android.telephony.data.NrQosSessionAttributes;
import android.util.Log;
+import com.android.modules.utils.build.SdkLevel;
+
import java.util.Objects;
/**
@@ -149,6 +151,7 @@
void sendEventEpsQosSessionAvailable(final QosSession session,
final EpsBearerQosSessionAttributes attributes) {
+ if (!validateOrSendErrorAndUnregister()) return;
try {
if (DBG) log("sendEventEpsQosSessionAvailable: sending...");
mCallback.onQosEpsBearerSessionAvailable(session, attributes);
@@ -159,6 +162,7 @@
void sendEventNrQosSessionAvailable(final QosSession session,
final NrQosSessionAttributes attributes) {
+ if (!validateOrSendErrorAndUnregister()) return;
try {
if (DBG) log("sendEventNrQosSessionAvailable: sending...");
mCallback.onNrQosSessionAvailable(session, attributes);
@@ -168,6 +172,7 @@
}
void sendEventQosSessionLost(@NonNull final QosSession session) {
+ if (!validateOrSendErrorAndUnregister()) return;
try {
if (DBG) log("sendEventQosSessionLost: sending...");
mCallback.onQosSessionLost(session);
@@ -185,6 +190,21 @@
}
}
+ private boolean validateOrSendErrorAndUnregister() {
+ final int exceptionType = mFilter.validate();
+ if (exceptionType != EX_TYPE_FILTER_NONE) {
+ log("validation fail before sending QosCallback.");
+ // Error callback is returned from Android T to prevent any disruption of application
+ // running on Android S.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventQosCallbackError(exceptionType);
+ mQosCallbackTracker.unregisterCallback(mCallback);
+ }
+ return false;
+ }
+ return true;
+ }
+
private static void log(@NonNull final String msg) {
Log.d(TAG, msg);
}
diff --git a/tests/common/java/android/net/EthernetNetworkManagementExceptionTest.java b/tests/common/java/android/net/EthernetNetworkManagementExceptionTest.java
new file mode 100644
index 0000000..84b6e54
--- /dev/null
+++ b/tests/common/java/android/net/EthernetNetworkManagementExceptionTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 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 com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
+import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
+@RunWith(DevSdkIgnoreRunner.class)
+@SmallTest
+public class EthernetNetworkManagementExceptionTest {
+ private static final String ERROR_MESSAGE = "Test error message";
+
+ @Test
+ public void testEthernetNetworkManagementExceptionParcelable() {
+ final EthernetNetworkManagementException e =
+ new EthernetNetworkManagementException(ERROR_MESSAGE);
+
+ assertParcelingIsLossless(e);
+ }
+
+ @Test
+ public void testEthernetNetworkManagementExceptionHasExpectedErrorMessage() {
+ final EthernetNetworkManagementException e =
+ new EthernetNetworkManagementException(ERROR_MESSAGE);
+
+ assertEquals(ERROR_MESSAGE, e.getMessage());
+ }
+}
diff --git a/tests/common/java/android/net/netstats/NetworkStatsHistoryTest.kt b/tests/common/java/android/net/netstats/NetworkStatsHistoryTest.kt
index 9343ea1..a6c9f3c 100644
--- a/tests/common/java/android/net/netstats/NetworkStatsHistoryTest.kt
+++ b/tests/common/java/android/net/netstats/NetworkStatsHistoryTest.kt
@@ -22,7 +22,6 @@
import com.android.testutils.ConnectivityModuleTest
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.SC_V2
-import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -37,7 +36,6 @@
@JvmField
val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = SC_V2)
- @Ignore
@Test
fun testBuilder() {
val entry1 = NetworkStatsHistory.Entry(10, 30, 40, 4, 50, 5, 60)
@@ -63,7 +61,6 @@
statsMultiple.assertEntriesEqual(entry3, entry1, entry2)
}
- @Ignore
@Test
fun testBuilderSortAndDeduplicate() {
val entry1 = NetworkStatsHistory.Entry(10, 30, 40, 4, 50, 5, 60)
diff --git a/tests/cts/hostside/Android.bp b/tests/cts/hostside/Android.bp
index c47ccbf..ac84e57 100644
--- a/tests/cts/hostside/Android.bp
+++ b/tests/cts/hostside/Android.bp
@@ -35,4 +35,12 @@
"general-tests",
"sts"
],
+ data: [
+ ":CtsHostsideNetworkTestsApp",
+ ":CtsHostsideNetworkTestsApp2",
+ ":CtsHostsideNetworkTestsApp3",
+ ":CtsHostsideNetworkTestsApp3PreT",
+ ":CtsHostsideNetworkTestsAppNext",
+ ],
+ per_testcase_directory: true,
}
diff --git a/tests/cts/hostside/app3/Android.bp b/tests/cts/hostside/app3/Android.bp
index 69667ce..141cf03 100644
--- a/tests/cts/hostside/app3/Android.bp
+++ b/tests/cts/hostside/app3/Android.bp
@@ -14,6 +14,10 @@
// limitations under the License.
//
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
java_defaults {
name: "CtsHostsideNetworkTestsApp3Defaults",
srcs: ["src/**/*.java"],
diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp
index e979a3b..4d85d72 100644
--- a/tests/cts/net/Android.bp
+++ b/tests/cts/net/Android.bp
@@ -94,7 +94,7 @@
],
jni_uses_sdk_apis: true,
min_sdk_version: "29",
- target_sdk_version: "30",
+ target_sdk_version: "33",
test_suites: [
"general-tests",
"mts-dnsresolver",
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index bdda82a..3b88189 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -165,7 +165,6 @@
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
-import android.util.Pair;
import android.util.Range;
import androidx.test.InstrumentationRegistry;
@@ -183,6 +182,7 @@
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.DevSdkIgnoreRuleKt;
+import com.android.testutils.DeviceInfoUtils;
import com.android.testutils.DumpTestUtils;
import com.android.testutils.RecorderCallback.CallbackEntry;
import com.android.testutils.TestHttpServer;
@@ -1606,51 +1606,7 @@
private static boolean isTcpKeepaliveSupportedByKernel() {
final String kVersionString = VintfRuntimeInfo.getKernelVersion();
- return compareMajorMinorVersion(kVersionString, "4.8") >= 0;
- }
-
- private static Pair<Integer, Integer> getVersionFromString(String version) {
- // Only gets major and minor number of the version string.
- final Pattern versionPattern = Pattern.compile("^(\\d+)(\\.(\\d+))?.*");
- final Matcher m = versionPattern.matcher(version);
- if (m.matches()) {
- final int major = Integer.parseInt(m.group(1));
- final int minor = TextUtils.isEmpty(m.group(3)) ? 0 : Integer.parseInt(m.group(3));
- return new Pair<>(major, minor);
- } else {
- return new Pair<>(0, 0);
- }
- }
-
- // TODO: Move to util class.
- private static int compareMajorMinorVersion(final String s1, final String s2) {
- final Pair<Integer, Integer> v1 = getVersionFromString(s1);
- final Pair<Integer, Integer> v2 = getVersionFromString(s2);
-
- if (v1.first == v2.first) {
- return Integer.compare(v1.second, v2.second);
- } else {
- return Integer.compare(v1.first, v2.first);
- }
- }
-
- /**
- * Verifies that version string compare logic returns expected result for various cases.
- * Note that only major and minor number are compared.
- */
- @Test
- public void testMajorMinorVersionCompare() {
- assertEquals(0, compareMajorMinorVersion("4.8.1", "4.8"));
- assertEquals(1, compareMajorMinorVersion("4.9", "4.8.1"));
- assertEquals(1, compareMajorMinorVersion("5.0", "4.8"));
- assertEquals(1, compareMajorMinorVersion("5", "4.8"));
- assertEquals(0, compareMajorMinorVersion("5", "5.0"));
- assertEquals(1, compareMajorMinorVersion("5-beta1", "4.8"));
- assertEquals(0, compareMajorMinorVersion("4.8.0.0", "4.8"));
- assertEquals(0, compareMajorMinorVersion("4.8-RC1", "4.8"));
- assertEquals(0, compareMajorMinorVersion("4.8", "4.8"));
- assertEquals(-1, compareMajorMinorVersion("3.10", "4.8.0"));
- assertEquals(-1, compareMajorMinorVersion("4.7.10.10", "4.8"));
+ return DeviceInfoUtils.compareMajorMinorVersion(kVersionString, "4.8") >= 0;
}
/**
@@ -3279,14 +3235,16 @@
// TODD: Have a significant signal to know the uids has been sent to netd.
assertBindSocketToNetworkSuccess(network);
- // Uid is in allowed list. Try file network request again.
- requestNetwork(restrictedRequest, restrictedNetworkCb);
- // Verify that the network is restricted.
- restrictedNetworkCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED,
- NETWORK_CALLBACK_TIMEOUT_MS,
- entry -> network.equals(entry.getNetwork())
- && (!((CallbackEntry.CapabilitiesChanged) entry).getCaps()
- .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)));
+ if (TestUtils.shouldTestTApis()) {
+ // Uid is in allowed list. Try file network request again.
+ requestNetwork(restrictedRequest, restrictedNetworkCb);
+ // Verify that the network is restricted.
+ restrictedNetworkCb.eventuallyExpect(CallbackEntry.NETWORK_CAPS_UPDATED,
+ NETWORK_CALLBACK_TIMEOUT_MS,
+ entry -> network.equals(entry.getNetwork())
+ && (!((CallbackEntry.CapabilitiesChanged) entry).getCaps()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)));
+ }
} finally {
agent.unregister();
diff --git a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
index bfc9b29..0a02593 100644
--- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
@@ -61,7 +61,6 @@
import org.junit.After
import org.junit.Before
import org.junit.Rule
-import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import java.net.Inet6Address
@@ -264,7 +263,6 @@
private fun TestableNetworkCallback.assertNotLost(n: Network? = null) =
assertNoCallbackThat() { it is Lost && (n?.equals(it.network) ?: true) }
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
fun testCallbacks() {
// If an interface exists when the callback is registered, it is reported on registration.
@@ -323,7 +321,6 @@
listener.assertNoCallback()
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
fun testGetInterfaceList() {
setIncludeTestInterfaces(true)
@@ -346,7 +343,6 @@
removeInterface(iface2)
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
fun testNetworkRequest_withSingleExistingInterface() {
setIncludeTestInterfaces(true)
@@ -365,7 +361,6 @@
listenerCb.eventuallyExpectLost(network)
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
fun testNetworkRequest_beforeSingleInterfaceIsUp() {
setIncludeTestInterfaces(true)
@@ -384,7 +379,6 @@
releaseNetwork(cb)
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
fun testNetworkRequest_withMultipleInterfaces() {
setIncludeTestInterfaces(true)
@@ -407,7 +401,6 @@
releaseNetwork(cb)
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
fun testNetworkRequest_withInterfaceBeingReplaced() {
setIncludeTestInterfaces(true)
@@ -428,7 +421,6 @@
releaseNetwork(cb)
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
fun testNetworkRequest_withMultipleInterfacesAndRequests() {
setIncludeTestInterfaces(true)
diff --git a/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java b/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java
index 7286bf6..2b1d173 100644
--- a/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java
+++ b/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java
@@ -22,6 +22,7 @@
import static android.net.cts.util.CtsNetUtils.TestNetworkCallback;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static com.android.modules.utils.build.SdkLevel.isAtLeastT;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
import static com.android.testutils.TestableNetworkCallbackKt.anyNetwork;
@@ -60,12 +61,7 @@
import com.android.internal.util.HexDump;
import com.android.networkstack.apishim.ConstantsShim;
-import com.android.networkstack.apishim.Ikev2VpnProfileBuilderShimImpl;
-import com.android.networkstack.apishim.Ikev2VpnProfileShimImpl;
import com.android.networkstack.apishim.VpnManagerShimImpl;
-import com.android.networkstack.apishim.common.Ikev2VpnProfileBuilderShim;
-import com.android.networkstack.apishim.common.Ikev2VpnProfileShim;
-import com.android.networkstack.apishim.common.UnsupportedApiLevelException;
import com.android.networkstack.apishim.common.VpnManagerShim;
import com.android.networkstack.apishim.common.VpnProfileStateShim;
import com.android.testutils.DevSdkIgnoreRule;
@@ -228,22 +224,17 @@
}
private Ikev2VpnProfile buildIkev2VpnProfileCommon(
- @NonNull Ikev2VpnProfileBuilderShim builderShim, boolean isRestrictedToTestNetworks,
+ @NonNull Ikev2VpnProfile.Builder builder, boolean isRestrictedToTestNetworks,
boolean requiresValidation) throws Exception {
- builderShim.setBypassable(true)
+ builder.setBypassable(true)
.setAllowedAlgorithms(TEST_ALLOWED_ALGORITHMS)
.setProxy(TEST_PROXY_INFO)
.setMaxMtu(TEST_MTU)
.setMetered(false);
if (TestUtils.shouldTestTApis()) {
- builderShim.setRequiresInternetValidation(requiresValidation);
+ builder.setRequiresInternetValidation(requiresValidation);
}
-
- // Convert shim back to Ikev2VpnProfile.Builder since restrictToTestNetworks is a hidden
- // method and does not defined in shims.
- // TODO: replace it in alternative way to remove the hidden method usage
- final Ikev2VpnProfile.Builder builder = (Ikev2VpnProfile.Builder) builderShim.getBuilder();
if (isRestrictedToTestNetworks) {
builder.restrictToTestNetworks();
}
@@ -259,14 +250,13 @@
? IkeSessionTestUtils.IKE_PARAMS_V6 : IkeSessionTestUtils.IKE_PARAMS_V4,
IkeSessionTestUtils.CHILD_PARAMS);
- final Ikev2VpnProfileBuilderShim builderShim =
- Ikev2VpnProfileBuilderShimImpl.newInstance(null, null, params)
+ final Ikev2VpnProfile.Builder builder =
+ new Ikev2VpnProfile.Builder(params)
.setRequiresInternetValidation(requiresValidation)
.setProxy(TEST_PROXY_INFO)
.setMaxMtu(TEST_MTU)
.setMetered(false);
- final Ikev2VpnProfile.Builder builder = (Ikev2VpnProfile.Builder) builderShim.getBuilder();
if (isRestrictedToTestNetworks) {
builder.restrictToTestNetworks();
}
@@ -275,9 +265,8 @@
private Ikev2VpnProfile buildIkev2VpnProfilePsk(@NonNull String remote,
boolean isRestrictedToTestNetworks, boolean requiresValidation) throws Exception {
- final Ikev2VpnProfileBuilderShim builder =
- Ikev2VpnProfileBuilderShimImpl.newInstance(remote, TEST_IDENTITY, null)
- .setAuthPsk(TEST_PSK);
+ final Ikev2VpnProfile.Builder builder =
+ new Ikev2VpnProfile.Builder(remote, TEST_IDENTITY).setAuthPsk(TEST_PSK);
return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks,
requiresValidation);
}
@@ -285,8 +274,8 @@
private Ikev2VpnProfile buildIkev2VpnProfileUsernamePassword(boolean isRestrictedToTestNetworks)
throws Exception {
- final Ikev2VpnProfileBuilderShim builder =
- Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY, null)
+ final Ikev2VpnProfile.Builder builder =
+ new Ikev2VpnProfile.Builder(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
.setAuthUsernamePassword(TEST_USER, TEST_PASSWORD, mServerRootCa);
return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks,
false /* requiresValidation */);
@@ -294,8 +283,8 @@
private Ikev2VpnProfile buildIkev2VpnProfileDigitalSignature(boolean isRestrictedToTestNetworks)
throws Exception {
- final Ikev2VpnProfileBuilderShim builder =
- Ikev2VpnProfileBuilderShimImpl.newInstance(TEST_SERVER_ADDR_V6, TEST_IDENTITY, null)
+ final Ikev2VpnProfile.Builder builder =
+ new Ikev2VpnProfile.Builder(TEST_SERVER_ADDR_V6, TEST_IDENTITY)
.setAuthDigitalSignature(
mUserCertKey.cert, mUserCertKey.key, mServerRootCa);
return buildIkev2VpnProfileCommon(builder, isRestrictedToTestNetworks,
@@ -328,15 +317,8 @@
assertNull(profile.getServerRootCaCert());
assertNull(profile.getRsaPrivateKey());
assertNull(profile.getUserCert());
- final Ikev2VpnProfileShim<Ikev2VpnProfile> shim = new Ikev2VpnProfileShimImpl(profile);
- if (TestUtils.shouldTestTApis()) {
- assertEquals(requiresValidation, shim.isInternetValidationRequired());
- } else {
- try {
- shim.isInternetValidationRequired();
- fail("Only supported from API level 33");
- } catch (UnsupportedApiLevelException expected) {
- }
+ if (isAtLeastT()) {
+ assertEquals(requiresValidation, profile.isInternetValidationRequired());
}
}
@@ -348,8 +330,8 @@
final IkeTunnelConnectionParams expectedParams = new IkeTunnelConnectionParams(
IkeSessionTestUtils.IKE_PARAMS_V6, IkeSessionTestUtils.CHILD_PARAMS);
- final Ikev2VpnProfileBuilderShim ikeProfileBuilder =
- Ikev2VpnProfileBuilderShimImpl.newInstance(null, null, expectedParams);
+ final Ikev2VpnProfile.Builder ikeProfileBuilder =
+ new Ikev2VpnProfile.Builder(expectedParams);
// Verify the other Ike options could not be set with IkeTunnelConnectionParams.
final Class<IllegalArgumentException> expected = IllegalArgumentException.class;
assertThrows(expected, () -> ikeProfileBuilder.setAuthPsk(TEST_PSK));
@@ -358,10 +340,9 @@
assertThrows(expected, () -> ikeProfileBuilder.setAuthDigitalSignature(
mUserCertKey.cert, mUserCertKey.key, mServerRootCa));
- final Ikev2VpnProfile profile = (Ikev2VpnProfile) ikeProfileBuilder.build().getProfile();
+ final Ikev2VpnProfile profile = ikeProfileBuilder.build();
- assertEquals(expectedParams,
- new Ikev2VpnProfileShimImpl(profile).getIkeTunnelConnectionParams());
+ assertEquals(expectedParams, profile.getIkeTunnelConnectionParams());
}
@Test
diff --git a/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java b/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
index d618915..5ba6d69 100644
--- a/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
@@ -56,6 +56,7 @@
import android.net.NetworkStatsHistory;
import android.net.TrafficStats;
import android.net.netstats.NetworkStatsDataMigrationUtils;
+import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
@@ -99,7 +100,7 @@
@RunWith(AndroidJUnit4.class)
public class NetworkStatsManagerTest {
@Rule
- public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(SC_V2 /* ignoreClassUpTo */);
+ public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(Build.VERSION_CODES.Q);
private static final String LOG_TAG = "NetworkStatsManagerTest";
private static final String APPOPS_SET_SHELL_COMMAND = "appops set {0} {1} {2}";
diff --git a/tests/native/Android.bp b/tests/native/Android.bp
index a8d908a..7d43aa8 100644
--- a/tests/native/Android.bp
+++ b/tests/native/Android.bp
@@ -31,3 +31,10 @@
],
compile_multilib: "first",
}
+
+filegroup {
+ name: "net_native_test_config_template",
+ srcs: [
+ "NetNativeTestConfigTemplate.xml",
+ ],
+}
diff --git a/tests/native/NetNativeTestConfigTemplate.xml b/tests/native/NetNativeTestConfigTemplate.xml
new file mode 100644
index 0000000..b71e9aa
--- /dev/null
+++ b/tests/native/NetNativeTestConfigTemplate.xml
@@ -0,0 +1,31 @@
+<!-- Copyright (C) 2022 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.
+-->
+<configuration description="Configuration for {MODULE} tests">
+ <option name="test-suite-tag" value="mts" />
+ <option name="config-descriptor:metadata" key="mainline-param" value="CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex" />
+ <!-- Only run tests if the device under test is SDK version 33 (Android 13) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk33ModuleController" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
+ <option name="append-bitness" value="true" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="{MODULE}" />
+ </test>
+</configuration>
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index c9a41ba..c976bd7 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -58,42 +58,21 @@
filegroup {
name: "non-connectivity-module-test",
srcs: [
- "java/android/app/usage/*.java",
- "java/android/net/EthernetNetworkUpdateRequestTest.java",
"java/android/net/Ikev2VpnProfileTest.java",
"java/android/net/IpMemoryStoreTest.java",
- "java/android/net/IpSecAlgorithmTest.java",
- "java/android/net/IpSecConfigTest.java",
- "java/android/net/IpSecManagerTest.java",
- "java/android/net/IpSecTransformTest.java",
- "java/android/net/KeepalivePacketDataUtilTest.java",
- "java/android/net/NetworkIdentitySetTest.kt",
- "java/android/net/NetworkIdentityTest.kt",
- "java/android/net/NetworkStats*.java",
- "java/android/net/NetworkTemplateTest.kt",
"java/android/net/TelephonyNetworkSpecifierTest.java",
"java/android/net/VpnManagerTest.java",
"java/android/net/ipmemorystore/*.java",
"java/android/net/netstats/NetworkStatsDataMigrationUtilsTest.kt",
- "java/android/net/nsd/*.java",
"java/com/android/internal/net/NetworkUtilsInternalTest.java",
"java/com/android/internal/net/VpnProfileTest.java",
- "java/com/android/server/IpSecServiceParameterizedTest.java",
- "java/com/android/server/IpSecServiceRefcountedResourceTest.java",
- "java/com/android/server/IpSecServiceTest.java",
"java/com/android/server/NetworkManagementServiceTest.java",
- "java/com/android/server/NsdServiceTest.java",
"java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java",
"java/com/android/server/connectivity/IpConnectivityMetricsTest.java",
"java/com/android/server/connectivity/MultipathPolicyTrackerTest.java",
"java/com/android/server/connectivity/NetdEventListenerServiceTest.java",
"java/com/android/server/connectivity/VpnTest.java",
- "java/com/android/server/ethernet/*.java",
"java/com/android/server/net/ipmemorystore/*.java",
- "java/com/android/server/net/BpfInterfaceMapUpdaterTest.java",
- "java/com/android/server/net/IpConfigStoreTest.java",
- "java/com/android/server/net/NetworkStats*.java",
- "java/com/android/server/net/TestableUsageCallback.kt",
]
}
diff --git a/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java b/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java
index 561e621..b1b76ec 100644
--- a/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java
+++ b/tests/unit/java/android/app/usage/NetworkStatsManagerTest.java
@@ -54,7 +54,7 @@
@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class NetworkStatsManagerTest {
private static final String TEST_SUBSCRIBER_ID = "subid";
diff --git a/tests/unit/java/android/net/ConnectivityManagerTest.java b/tests/unit/java/android/net/ConnectivityManagerTest.java
index f324630..c327868 100644
--- a/tests/unit/java/android/net/ConnectivityManagerTest.java
+++ b/tests/unit/java/android/net/ConnectivityManagerTest.java
@@ -41,6 +41,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -72,6 +73,7 @@
import androidx.test.filters.SmallTest;
+import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
@@ -82,6 +84,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.lang.ref.WeakReference;
+
@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
@DevSdkIgnoreRule.IgnoreUpTo(VERSION_CODES.R)
@@ -461,4 +465,49 @@
}
fail("expected exception of type " + throwableType);
}
+
+ private static class MockContext extends BroadcastInterceptingContext {
+ MockContext(Context base) {
+ super(base);
+ }
+
+ @Override
+ public Context getApplicationContext() {
+ return mock(Context.class);
+ }
+ }
+
+ private WeakReference<Context> makeConnectivityManagerAndReturnContext() {
+ // Mockito may have an internal reference to the mock, creating MockContext for testing.
+ final Context c = new MockContext(mock(Context.class));
+
+ new ConnectivityManager(c, mService);
+
+ return new WeakReference<>(c);
+ }
+
+ private void forceGC() {
+ // First GC ensures that objects are collected for finalization, then second GC ensures
+ // they're garbage-collected after being finalized.
+ System.gc();
+ System.runFinalization();
+ System.gc();
+ }
+
+ @Test
+ public void testConnectivityManagerDoesNotLeakContext() throws Exception {
+ final WeakReference<Context> ref = makeConnectivityManagerAndReturnContext();
+
+ final int attempts = 100;
+ final long waitIntervalMs = 50;
+ for (int i = 0; i < attempts; i++) {
+ forceGC();
+ if (ref.get() == null) break;
+
+ Thread.sleep(waitIntervalMs);
+ }
+
+ assertNull("ConnectivityManager weak reference still not null after " + attempts
+ + " attempts", ref.get());
+ }
}
diff --git a/tests/unit/java/android/net/IpSecAlgorithmTest.java b/tests/unit/java/android/net/IpSecAlgorithmTest.java
index c473e82..1482055 100644
--- a/tests/unit/java/android/net/IpSecAlgorithmTest.java
+++ b/tests/unit/java/android/net/IpSecAlgorithmTest.java
@@ -47,7 +47,7 @@
/** Unit tests for {@link IpSecAlgorithm}. */
@SmallTest
@RunWith(DevSdkIgnoreRunner.class)
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class IpSecAlgorithmTest {
private static final byte[] KEY_MATERIAL;
diff --git a/tests/unit/java/android/net/IpSecConfigTest.java b/tests/unit/java/android/net/IpSecConfigTest.java
index b87cb48..9f83036 100644
--- a/tests/unit/java/android/net/IpSecConfigTest.java
+++ b/tests/unit/java/android/net/IpSecConfigTest.java
@@ -36,7 +36,7 @@
/** Unit tests for {@link IpSecConfig}. */
@SmallTest
@RunWith(DevSdkIgnoreRunner.class)
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class IpSecConfigTest {
@Test
diff --git a/tests/unit/java/android/net/IpSecManagerTest.java b/tests/unit/java/android/net/IpSecManagerTest.java
index cda8eb7..335f539 100644
--- a/tests/unit/java/android/net/IpSecManagerTest.java
+++ b/tests/unit/java/android/net/IpSecManagerTest.java
@@ -52,7 +52,7 @@
/** Unit tests for {@link IpSecManager}. */
@SmallTest
@RunWith(DevSdkIgnoreRunner.class)
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class IpSecManagerTest {
private static final int TEST_UDP_ENCAP_PORT = 34567;
diff --git a/tests/unit/java/android/net/IpSecTransformTest.java b/tests/unit/java/android/net/IpSecTransformTest.java
index 81375f1..c1bd719 100644
--- a/tests/unit/java/android/net/IpSecTransformTest.java
+++ b/tests/unit/java/android/net/IpSecTransformTest.java
@@ -32,7 +32,7 @@
/** Unit tests for {@link IpSecTransform}. */
@SmallTest
@RunWith(DevSdkIgnoreRunner.class)
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class IpSecTransformTest {
@Test
diff --git a/tests/unit/java/android/net/NetworkIdentityTest.kt b/tests/unit/java/android/net/NetworkIdentityTest.kt
index bf5568d..d84328c 100644
--- a/tests/unit/java/android/net/NetworkIdentityTest.kt
+++ b/tests/unit/java/android/net/NetworkIdentityTest.kt
@@ -47,7 +47,7 @@
private const val TEST_SUBID2 = 2
@RunWith(DevSdkIgnoreRunner::class)
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
class NetworkIdentityTest {
private val mockContext = mock(Context::class.java)
diff --git a/tests/unit/java/android/net/NetworkStatsAccessTest.java b/tests/unit/java/android/net/NetworkStatsAccessTest.java
index 97a93ca..a74056b 100644
--- a/tests/unit/java/android/net/NetworkStatsAccessTest.java
+++ b/tests/unit/java/android/net/NetworkStatsAccessTest.java
@@ -19,6 +19,7 @@
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.when;
import android.Manifest;
@@ -66,6 +67,10 @@
when(mContext.getSystemServiceName(DevicePolicyManager.class))
.thenReturn(Context.DEVICE_POLICY_SERVICE);
when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(mDpm);
+ if (mContext.getSystemService(DevicePolicyManager.class) == null) {
+ // Test is using mockito-extended
+ doCallRealMethod().when(mContext).getSystemService(DevicePolicyManager.class);
+ }
setHasCarrierPrivileges(false);
setIsDeviceOwner(false);
diff --git a/tests/unit/java/android/net/NetworkStatsHistoryTest.java b/tests/unit/java/android/net/NetworkStatsHistoryTest.java
index 26079a2..43e331b 100644
--- a/tests/unit/java/android/net/NetworkStatsHistoryTest.java
+++ b/tests/unit/java/android/net/NetworkStatsHistoryTest.java
@@ -60,7 +60,7 @@
@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class NetworkStatsHistoryTest {
private static final String TAG = "NetworkStatsHistoryTest";
diff --git a/tests/unit/java/android/net/NetworkStatsTest.java b/tests/unit/java/android/net/NetworkStatsTest.java
index b0cc16c..6d79869 100644
--- a/tests/unit/java/android/net/NetworkStatsTest.java
+++ b/tests/unit/java/android/net/NetworkStatsTest.java
@@ -61,7 +61,7 @@
@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class NetworkStatsTest {
private static final String TEST_IFACE = "test0";
diff --git a/tests/unit/java/android/net/NetworkTemplateTest.kt b/tests/unit/java/android/net/NetworkTemplateTest.kt
index abd1825..3e9662d 100644
--- a/tests/unit/java/android/net/NetworkTemplateTest.kt
+++ b/tests/unit/java/android/net/NetworkTemplateTest.kt
@@ -70,7 +70,7 @@
private const val TEST_WIFI_KEY2 = "wifiKey2"
@RunWith(DevSdkIgnoreRunner::class)
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
class NetworkTemplateTest {
private val mockContext = mock(Context::class.java)
private val mockWifiInfo = mock(WifiInfo::class.java)
diff --git a/tests/unit/java/android/net/QosSocketFilterTest.java b/tests/unit/java/android/net/QosSocketFilterTest.java
index 91f2cdd..6820b40 100644
--- a/tests/unit/java/android/net/QosSocketFilterTest.java
+++ b/tests/unit/java/android/net/QosSocketFilterTest.java
@@ -16,8 +16,17 @@
package android.net;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
+import static android.net.QosCallbackException.EX_TYPE_FILTER_NONE;
+import static android.net.QosCallbackException.EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED;
+import static android.net.QosCallbackException.EX_TYPE_FILTER_SOCKET_NOT_BOUND;
+import static android.net.QosCallbackException.EX_TYPE_FILTER_SOCKET_NOT_CONNECTED;
+import static android.net.QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED;
+import static android.system.OsConstants.IPPROTO_TCP;
+import static android.system.OsConstants.IPPROTO_UDP;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import android.os.Build;
@@ -29,6 +38,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -36,14 +46,14 @@
@SmallTest
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class QosSocketFilterTest {
-
+ private static final int TEST_NET_ID = 1777;
+ private final Network mNetwork = new Network(TEST_NET_ID);
@Test
public void testPortExactMatch() {
final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
final InetAddress addressB = InetAddresses.parseNumericAddress("1.2.3.4");
assertTrue(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), addressB, 10, 10));
-
}
@Test
@@ -77,5 +87,90 @@
assertFalse(QosSocketFilter.matchesAddress(
new InetSocketAddress(addressA, 10), addressB, 10, 10));
}
+
+ @Test
+ public void testAddressMatchWithAnyLocalAddresses() {
+ final InetAddress addressA = InetAddresses.parseNumericAddress("1.2.3.4");
+ final InetAddress addressB = InetAddresses.parseNumericAddress("0.0.0.0");
+ assertTrue(QosSocketFilter.matchesAddress(
+ new InetSocketAddress(addressA, 10), addressB, 10, 10));
+ assertFalse(QosSocketFilter.matchesAddress(
+ new InetSocketAddress(addressB, 10), addressA, 10, 10));
+ }
+
+ @Test
+ public void testProtocolMatch() throws Exception {
+ DatagramSocket socket = new DatagramSocket(new InetSocketAddress("127.0.0.1", 0));
+ socket.connect(new InetSocketAddress("127.0.0.1", socket.getLocalPort() + 10));
+ DatagramSocket socketV6 = new DatagramSocket(new InetSocketAddress("::1", 0));
+ socketV6.connect(new InetSocketAddress("::1", socketV6.getLocalPort() + 10));
+ QosSocketInfo socketInfo = new QosSocketInfo(mNetwork, socket);
+ QosSocketFilter socketFilter = new QosSocketFilter(socketInfo);
+ QosSocketInfo socketInfo6 = new QosSocketInfo(mNetwork, socketV6);
+ QosSocketFilter socketFilter6 = new QosSocketFilter(socketInfo6);
+ assertTrue(socketFilter.matchesProtocol(IPPROTO_UDP));
+ assertTrue(socketFilter6.matchesProtocol(IPPROTO_UDP));
+ assertFalse(socketFilter.matchesProtocol(IPPROTO_TCP));
+ assertFalse(socketFilter6.matchesProtocol(IPPROTO_TCP));
+ socket.close();
+ socketV6.close();
+ }
+
+ @Test
+ public void testValidate() throws Exception {
+ DatagramSocket socket = new DatagramSocket(new InetSocketAddress("127.0.0.1", 0));
+ socket.connect(new InetSocketAddress("127.0.0.1", socket.getLocalPort() + 7));
+ DatagramSocket socketV6 = new DatagramSocket(new InetSocketAddress("::1", 0));
+
+ QosSocketInfo socketInfo = new QosSocketInfo(mNetwork, socket);
+ QosSocketFilter socketFilter = new QosSocketFilter(socketInfo);
+ QosSocketInfo socketInfo6 = new QosSocketInfo(mNetwork, socketV6);
+ QosSocketFilter socketFilter6 = new QosSocketFilter(socketInfo6);
+ assertEquals(EX_TYPE_FILTER_NONE, socketFilter.validate());
+ assertEquals(EX_TYPE_FILTER_NONE, socketFilter6.validate());
+ socket.close();
+ socketV6.close();
+ }
+
+ @Test
+ public void testValidateUnbind() throws Exception {
+ DatagramSocket socket;
+ socket = new DatagramSocket(null);
+ QosSocketInfo socketInfo = new QosSocketInfo(mNetwork, socket);
+ QosSocketFilter socketFilter = new QosSocketFilter(socketInfo);
+ assertEquals(EX_TYPE_FILTER_SOCKET_NOT_BOUND, socketFilter.validate());
+ socket.close();
+ }
+
+ @Test
+ public void testValidateLocalAddressChanged() throws Exception {
+ DatagramSocket socket = new DatagramSocket(null);
+ DatagramSocket socket6 = new DatagramSocket(null);
+ QosSocketInfo socketInfo = new QosSocketInfo(mNetwork, socket);
+ QosSocketFilter socketFilter = new QosSocketFilter(socketInfo);
+ QosSocketInfo socketInfo6 = new QosSocketInfo(mNetwork, socket6);
+ QosSocketFilter socketFilter6 = new QosSocketFilter(socketInfo6);
+ socket.bind(new InetSocketAddress("127.0.0.1", 0));
+ socket6.bind(new InetSocketAddress("::1", 0));
+ assertEquals(EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED, socketFilter.validate());
+ assertEquals(EX_TYPE_FILTER_SOCKET_LOCAL_ADDRESS_CHANGED, socketFilter6.validate());
+ socket.close();
+ socket6.close();
+ }
+
+ @Test
+ public void testValidateRemoteAddressChanged() throws Exception {
+ DatagramSocket socket;
+ socket = new DatagramSocket(new InetSocketAddress("127.0.0.1", 53137));
+ socket.connect(new InetSocketAddress("127.0.0.1", socket.getLocalPort() + 11));
+ QosSocketInfo socketInfo = new QosSocketInfo(mNetwork, socket);
+ QosSocketFilter socketFilter = new QosSocketFilter(socketInfo);
+ assertEquals(EX_TYPE_FILTER_NONE, socketFilter.validate());
+ socket.disconnect();
+ assertEquals(EX_TYPE_FILTER_SOCKET_NOT_CONNECTED, socketFilter.validate());
+ socket.connect(new InetSocketAddress("127.0.0.1", socket.getLocalPort() + 13));
+ assertEquals(EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED, socketFilter.validate());
+ socket.close();
+ }
}
diff --git a/tests/unit/java/android/net/QosSocketInfoTest.java b/tests/unit/java/android/net/QosSocketInfoTest.java
new file mode 100644
index 0000000..749c182
--- /dev/null
+++ b/tests/unit/java/android/net/QosSocketInfoTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2022 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 android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_STREAM;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import android.os.Build;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import java.net.DatagramSocket;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+@RunWith(DevSdkIgnoreRunner.class)
+@SmallTest
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+public class QosSocketInfoTest {
+ @Mock
+ private Network mMockNetwork = mock(Network.class);
+
+ @Test
+ public void testConstructWithSock() throws Exception {
+ ServerSocket server = new ServerSocket();
+ ServerSocket server6 = new ServerSocket();
+
+ InetSocketAddress clientAddr = new InetSocketAddress("127.0.0.1", 0);
+ InetSocketAddress serverAddr = new InetSocketAddress("127.0.0.1", 0);
+ InetSocketAddress clientAddr6 = new InetSocketAddress("::1", 0);
+ InetSocketAddress serverAddr6 = new InetSocketAddress("::1", 0);
+ server.bind(serverAddr);
+ server6.bind(serverAddr6);
+ Socket socket = new Socket(serverAddr.getAddress(), server.getLocalPort(),
+ clientAddr.getAddress(), clientAddr.getPort());
+ Socket socket6 = new Socket(serverAddr6.getAddress(), server6.getLocalPort(),
+ clientAddr6.getAddress(), clientAddr6.getPort());
+ QosSocketInfo sockInfo = new QosSocketInfo(mMockNetwork, socket);
+ QosSocketInfo sockInfo6 = new QosSocketInfo(mMockNetwork, socket6);
+ assertTrue(sockInfo.getLocalSocketAddress()
+ .equals(new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort())));
+ assertTrue(sockInfo.getRemoteSocketAddress()
+ .equals((InetSocketAddress) socket.getRemoteSocketAddress()));
+ assertEquals(SOCK_STREAM, sockInfo.getSocketType());
+ assertTrue(sockInfo6.getLocalSocketAddress()
+ .equals(new InetSocketAddress(socket6.getLocalAddress(), socket6.getLocalPort())));
+ assertTrue(sockInfo6.getRemoteSocketAddress()
+ .equals((InetSocketAddress) socket6.getRemoteSocketAddress()));
+ assertEquals(SOCK_STREAM, sockInfo6.getSocketType());
+ socket.close();
+ socket6.close();
+ server.close();
+ server6.close();
+ }
+
+ @Test
+ public void testConstructWithDatagramSock() throws Exception {
+ InetSocketAddress clientAddr = new InetSocketAddress("127.0.0.1", 0);
+ InetSocketAddress serverAddr = new InetSocketAddress("127.0.0.1", 0);
+ InetSocketAddress clientAddr6 = new InetSocketAddress("::1", 0);
+ InetSocketAddress serverAddr6 = new InetSocketAddress("::1", 0);
+ DatagramSocket socket = new DatagramSocket(null);
+ socket.setReuseAddress(true);
+ socket.bind(clientAddr);
+ socket.connect(serverAddr);
+ DatagramSocket socket6 = new DatagramSocket(null);
+ socket6.setReuseAddress(true);
+ socket6.bind(clientAddr);
+ socket6.connect(serverAddr);
+ QosSocketInfo sockInfo = new QosSocketInfo(mMockNetwork, socket);
+ QosSocketInfo sockInfo6 = new QosSocketInfo(mMockNetwork, socket6);
+ assertTrue(sockInfo.getLocalSocketAddress()
+ .equals((InetSocketAddress) socket.getLocalSocketAddress()));
+ assertTrue(sockInfo.getRemoteSocketAddress()
+ .equals((InetSocketAddress) socket.getRemoteSocketAddress()));
+ assertEquals(SOCK_DGRAM, sockInfo.getSocketType());
+ assertTrue(sockInfo6.getLocalSocketAddress()
+ .equals((InetSocketAddress) socket6.getLocalSocketAddress()));
+ assertTrue(sockInfo6.getRemoteSocketAddress()
+ .equals((InetSocketAddress) socket6.getRemoteSocketAddress()));
+ assertEquals(SOCK_DGRAM, sockInfo6.getSocketType());
+ socket.close();
+ }
+}
diff --git a/tests/unit/java/android/net/nsd/NsdManagerTest.java b/tests/unit/java/android/net/nsd/NsdManagerTest.java
index 30b8fcd..32274bc 100644
--- a/tests/unit/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/unit/java/android/net/nsd/NsdManagerTest.java
@@ -51,7 +51,7 @@
@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class NsdManagerTest {
static final int PROTOCOL = NsdManager.PROTOCOL_DNS_SD;
diff --git a/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java b/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java
index e5e7ebc..0354377 100644
--- a/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java
+++ b/tests/unit/java/android/net/nsd/NsdServiceInfoTest.java
@@ -42,7 +42,7 @@
@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class NsdServiceInfoTest {
public final static InetAddress LOCALHOST;
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 44550e6..a2902a6 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -144,6 +144,8 @@
import static com.android.server.ConnectivityService.PREFERENCE_ORDER_PROFILE;
import static com.android.server.ConnectivityService.PREFERENCE_ORDER_VPN;
import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
+import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackRegister;
+import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister;
import static com.android.testutils.ConcurrentUtils.await;
import static com.android.testutils.ConcurrentUtils.durationOf;
import static com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
@@ -9507,7 +9509,7 @@
b2.expectBroadcast();
}
- @Test
+ @Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
public void testLockdownSetFirewallUidRule() throws Exception {
// For ConnectivityService#setAlwaysOnVpnPackage.
mServiceContext.setPermission(
@@ -10430,7 +10432,7 @@
}
@Test
- public void testLegacyVpnSetInterfaceFilteringRuleWithWildcard() throws Exception {
+ public void testLegacyVpnInterfaceFilteringRule() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
@@ -10440,29 +10442,34 @@
mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
- // A connected Legacy VPN should have interface rules with null interface.
- // Null Interface is a wildcard and this accepts traffic from all the interfaces.
- // There are two expected invocations, one during the VPN initial connection,
- // one during the VPN LinkProperties update.
- ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
- verify(mBpfNetMaps, times(2)).addUidInterfaceRules(
- eq(null) /* iface */, uidCaptor.capture());
- assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
- assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
- assertEquals(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */),
- vpnRange);
+ if (SdkLevel.isAtLeastT()) {
+ // On T and above, A connected Legacy VPN should have interface rules with null
+ // interface. Null Interface is a wildcard and this accepts traffic from all the
+ // interfaces. There are two expected invocations, one during the VPN initial
+ // connection, one during the VPN LinkProperties update.
+ ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
+ verify(mBpfNetMaps, times(2)).addUidInterfaceRules(
+ eq(null) /* iface */, uidCaptor.capture());
+ assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
+ assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
+ assertEquals(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */),
+ vpnRange);
- mMockVpn.disconnect();
- waitForIdle();
+ mMockVpn.disconnect();
+ waitForIdle();
- // Disconnected VPN should have interface rules removed
- verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
- assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
- assertNull(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */));
+ // Disconnected VPN should have interface rules removed
+ verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
+ assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
+ assertNull(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */));
+ } else {
+ // Before T, Legacy VPN should not have interface rules.
+ verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
+ }
}
@Test
- public void testLocalIpv4OnlyVpnSetInterfaceFilteringRuleWithWildcard() throws Exception {
+ public void testLocalIpv4OnlyVpnInterfaceFilteringRule() throws Exception {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("tun0");
lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
@@ -10472,26 +10479,31 @@
mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
- // IPv6 unreachable route should not be misinterpreted as a default route
- // A connected VPN should have interface rules with null interface.
- // Null Interface is a wildcard and this accepts traffic from all the interfaces.
- // There are two expected invocations, one during the VPN initial connection,
- // one during the VPN LinkProperties update.
- ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
- verify(mBpfNetMaps, times(2)).addUidInterfaceRules(
- eq(null) /* iface */, uidCaptor.capture());
- assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
- assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
- assertEquals(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */),
- vpnRange);
+ if (SdkLevel.isAtLeastT()) {
+ // IPv6 unreachable route should not be misinterpreted as a default route
+ // On T and above, A connected VPN that does not provide a default route should have
+ // interface rules with null interface. Null Interface is a wildcard and this accepts
+ // traffic from all the interfaces. There are two expected invocations, one during the
+ // VPN initial connection, one during the VPN LinkProperties update.
+ ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
+ verify(mBpfNetMaps, times(2)).addUidInterfaceRules(
+ eq(null) /* iface */, uidCaptor.capture());
+ assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
+ assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
+ assertEquals(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */),
+ vpnRange);
- mMockVpn.disconnect();
- waitForIdle();
+ mMockVpn.disconnect();
+ waitForIdle();
- // Disconnected VPN should have interface rules removed
- verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
- assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
- assertNull(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */));
+ // Disconnected VPN should have interface rules removed
+ verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
+ assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
+ assertNull(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */));
+ } else {
+ // Before T, VPN with IPv6 unreachable route should not have interface rules.
+ verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
+ }
}
@Test
@@ -12056,16 +12068,14 @@
mQosCallbackMockHelper.registerQosCallback(
mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
- final NetworkAgentWrapper.CallbackType.OnQosCallbackRegister cbRegister1 =
- (NetworkAgentWrapper.CallbackType.OnQosCallbackRegister)
- wrapper.getCallbackHistory().poll(1000, x -> true);
+ final OnQosCallbackRegister cbRegister1 =
+ (OnQosCallbackRegister) wrapper.getCallbackHistory().poll(1000, x -> true);
assertNotNull(cbRegister1);
final int registerCallbackId = cbRegister1.mQosCallbackId;
mService.unregisterQosCallback(mQosCallbackMockHelper.mCallback);
- final NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister cbUnregister;
- cbUnregister = (NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister)
- wrapper.getCallbackHistory().poll(1000, x -> true);
+ final OnQosCallbackUnregister cbUnregister =
+ (OnQosCallbackUnregister) wrapper.getCallbackHistory().poll(1000, x -> true);
assertNotNull(cbUnregister);
assertEquals(registerCallbackId, cbUnregister.mQosCallbackId);
assertNull(wrapper.getCallbackHistory().poll(200, x -> true));
@@ -12144,6 +12154,86 @@
&& session.getSessionType() == QosSession.TYPE_NR_BEARER));
}
+ @Test @IgnoreUpTo(SC_V2)
+ public void testQosCallbackAvailableOnValidationError() throws Exception {
+ mQosCallbackMockHelper = new QosCallbackMockHelper();
+ final NetworkAgentWrapper wrapper = mQosCallbackMockHelper.mAgentWrapper;
+ final int sessionId = 10;
+ final int qosCallbackId = 1;
+
+ doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
+ .when(mQosCallbackMockHelper.mFilter).validate();
+ mQosCallbackMockHelper.registerQosCallback(
+ mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
+ OnQosCallbackRegister cbRegister1 =
+ (OnQosCallbackRegister) wrapper.getCallbackHistory().poll(1000, x -> true);
+ assertNotNull(cbRegister1);
+ final int registerCallbackId = cbRegister1.mQosCallbackId;
+
+ waitForIdle();
+
+ doReturn(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED)
+ .when(mQosCallbackMockHelper.mFilter).validate();
+ final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes(
+ 1, 2, 3, 4, 5, new ArrayList<>());
+ mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
+ .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
+ waitForIdle();
+
+ final NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister cbUnregister;
+ cbUnregister = (NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister)
+ wrapper.getCallbackHistory().poll(1000, x -> true);
+ assertNotNull(cbUnregister);
+ assertEquals(registerCallbackId, cbUnregister.mQosCallbackId);
+ waitForIdle();
+ verify(mQosCallbackMockHelper.mCallback)
+ .onError(eq(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED));
+ }
+
+ @Test @IgnoreUpTo(SC_V2)
+ public void testQosCallbackLostOnValidationError() throws Exception {
+ mQosCallbackMockHelper = new QosCallbackMockHelper();
+ final int sessionId = 10;
+ final int qosCallbackId = 1;
+
+ doReturn(QosCallbackException.EX_TYPE_FILTER_NONE)
+ .when(mQosCallbackMockHelper.mFilter).validate();
+ mQosCallbackMockHelper.registerQosCallback(
+ mQosCallbackMockHelper.mFilter, mQosCallbackMockHelper.mCallback);
+ waitForIdle();
+ EpsBearerQosSessionAttributes attributes =
+ sendQosSessionEvent(qosCallbackId, sessionId, true);
+ waitForIdle();
+
+ verify(mQosCallbackMockHelper.mCallback).onQosEpsBearerSessionAvailable(argThat(session ->
+ session.getSessionId() == sessionId
+ && session.getSessionType() == QosSession.TYPE_EPS_BEARER), eq(attributes));
+
+ doReturn(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED)
+ .when(mQosCallbackMockHelper.mFilter).validate();
+
+ sendQosSessionEvent(qosCallbackId, sessionId, false);
+ waitForIdle();
+ verify(mQosCallbackMockHelper.mCallback)
+ .onError(eq(QosCallbackException.EX_TYPE_FILTER_SOCKET_REMOTE_ADDRESS_CHANGED));
+ }
+
+ private EpsBearerQosSessionAttributes sendQosSessionEvent(
+ int qosCallbackId, int sessionId, boolean available) {
+ if (available) {
+ final EpsBearerQosSessionAttributes attributes = new EpsBearerQosSessionAttributes(
+ 1, 2, 3, 4, 5, new ArrayList<>());
+ mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
+ .sendQosSessionAvailable(qosCallbackId, sessionId, attributes);
+ return attributes;
+ } else {
+ mQosCallbackMockHelper.mAgentWrapper.getNetworkAgent()
+ .sendQosSessionLost(qosCallbackId, sessionId, QosSession.TYPE_EPS_BEARER);
+ return null;
+ }
+
+ }
+
@Test
public void testQosCallbackTooManyRequests() throws Exception {
mQosCallbackMockHelper = new QosCallbackMockHelper();
diff --git a/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
index 45f3d3c..9401d47 100644
--- a/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -89,7 +89,7 @@
public class IpSecServiceParameterizedTest {
@Rule
public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(
- Build.VERSION_CODES.R /* ignoreClassUpTo */);
+ Build.VERSION_CODES.S_V2 /* ignoreClassUpTo */);
private static final int TEST_SPI = 0xD1201D;
@@ -783,6 +783,23 @@
}
@Test
+ public void testSetNetworkForTunnelInterfaceFailsForNullLp() throws Exception {
+ final IpSecTunnelInterfaceResponse createTunnelResp =
+ createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE);
+ final Network newFakeNetwork = new Network(1000);
+ final int tunnelIfaceResourceId = createTunnelResp.resourceId;
+
+ try {
+ mIpSecService.setNetworkForTunnelInterface(
+ tunnelIfaceResourceId, newFakeNetwork, BLESSED_PACKAGE);
+ fail(
+ "Expected an IllegalArgumentException for underlying network with null"
+ + " LinkProperties");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ @Test
public void testSetNetworkForTunnelInterfaceFailsForInvalidResourceId() throws Exception {
final IpSecTunnelInterfaceResponse createTunnelResp =
createAndValidateTunnel(mSourceAddr, mDestinationAddr, BLESSED_PACKAGE);
diff --git a/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java b/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java
index 5c7ca6f..8595ab9 100644
--- a/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java
+++ b/tests/unit/java/com/android/server/IpSecServiceRefcountedResourceTest.java
@@ -54,7 +54,7 @@
/** Unit tests for {@link IpSecService.RefcountedResource}. */
@SmallTest
@RunWith(DevSdkIgnoreRunner.class)
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class IpSecServiceRefcountedResourceTest {
Context mMockContext;
IpSecService.Dependencies mMockDeps;
diff --git a/tests/unit/java/com/android/server/IpSecServiceTest.java b/tests/unit/java/com/android/server/IpSecServiceTest.java
index 7e6b157..6955620 100644
--- a/tests/unit/java/com/android/server/IpSecServiceTest.java
+++ b/tests/unit/java/com/android/server/IpSecServiceTest.java
@@ -75,7 +75,7 @@
/** Unit tests for {@link IpSecService}. */
@SmallTest
@RunWith(DevSdkIgnoreRunner.class)
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class IpSecServiceTest {
private static final int DROID_SPI = 0xD1201D;
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index 3c228d0..7ecf1f3 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
@@ -74,7 +75,7 @@
// - test NSD_ON ENABLE/DISABLED listening
@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class NsdServiceTest {
static final int PROTOCOL = NsdManager.PROTOCOL_DNS_SD;
@@ -114,6 +115,10 @@
doReturn(MDnsManager.MDNS_SERVICE).when(mContext)
.getSystemServiceName(MDnsManager.class);
doReturn(mMockMDnsM).when(mContext).getSystemService(MDnsManager.MDNS_SERVICE);
+ if (mContext.getSystemService(MDnsManager.class) == null) {
+ // Test is using mockito-extended
+ doCallRealMethod().when(mContext).getSystemService(MDnsManager.class);
+ }
doReturn(true).when(mMockMDnsM).registerService(
anyInt(), anyString(), anyString(), anyInt(), any(), anyInt());
doReturn(true).when(mMockMDnsM).stopOperation(anyInt());
diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java
index bae0433..11fbcb9 100644
--- a/tests/unit/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java
@@ -100,7 +100,11 @@
import android.net.VpnService;
import android.net.VpnTransportInfo;
import android.net.ipsec.ike.IkeSessionCallback;
+import android.net.ipsec.ike.exceptions.IkeException;
+import android.net.ipsec.ike.exceptions.IkeNetworkLostException;
+import android.net.ipsec.ike.exceptions.IkeNonProtocolException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
+import android.net.ipsec.ike.exceptions.IkeTimeoutException;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.ConditionVariable;
@@ -149,6 +153,7 @@
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -1284,15 +1289,16 @@
config -> Arrays.asList(config.flags).contains(flag)));
}
- @Test
- public void testStartPlatformVpnAuthenticationFailed() throws Exception {
+ private void setupPlatformVpnWithSpecificExceptionAndItsErrorCode(IkeException exception,
+ String category, int errorType, int errorCode) throws Exception {
final ArgumentCaptor<IkeSessionCallback> captor =
ArgumentCaptor.forClass(IkeSessionCallback.class);
- final IkeProtocolException exception = mock(IkeProtocolException.class);
- when(exception.getErrorType())
- .thenReturn(IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED);
- final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), (mVpnProfile));
+ final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN);
+ when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
+ .thenReturn(mVpnProfile.encode());
+
+ final String sessionKey = vpn.startVpnProfile(TEST_VPN_PKG);
final NetworkCallback cb = triggerOnAvailableAndGetCallback();
verifyInterfaceSetCfgWithFlags(IF_STATE_UP);
@@ -1302,10 +1308,75 @@
verify(mIkev2SessionCreator, timeout(TEST_TIMEOUT_MS))
.createIkeSession(any(), any(), any(), any(), captor.capture(), any());
final IkeSessionCallback ikeCb = captor.getValue();
- ikeCb.onClosedExceptionally(exception);
+ ikeCb.onClosedWithException(exception);
- verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb));
- assertEquals(LegacyVpnInfo.STATE_FAILED, vpn.getLegacyVpnInfo().state);
+ verifyVpnManagerEvent(sessionKey, category, errorType, errorCode, null /* profileState */);
+ if (errorType == VpnManager.ERROR_CLASS_NOT_RECOVERABLE) {
+ verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS))
+ .unregisterNetworkCallback(eq(cb));
+ }
+ }
+
+ @Test
+ public void testStartPlatformVpnAuthenticationFailed() throws Exception {
+ final IkeProtocolException exception = mock(IkeProtocolException.class);
+ final int errorCode = IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED;
+ when(exception.getErrorType()).thenReturn(errorCode);
+ setupPlatformVpnWithSpecificExceptionAndItsErrorCode(exception,
+ VpnManager.CATEGORY_EVENT_IKE_ERROR, VpnManager.ERROR_CLASS_NOT_RECOVERABLE,
+ errorCode);
+ }
+
+ @Test
+ public void testStartPlatformVpnFailedWithRecoverableError() throws Exception {
+ final IkeProtocolException exception = mock(IkeProtocolException.class);
+ final int errorCode = IkeProtocolException.ERROR_TYPE_TEMPORARY_FAILURE;
+ when(exception.getErrorType()).thenReturn(errorCode);
+ setupPlatformVpnWithSpecificExceptionAndItsErrorCode(exception,
+ VpnManager.CATEGORY_EVENT_IKE_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE, errorCode);
+ }
+
+ @Test
+ public void testStartPlatformVpnFailedWithUnknownHostException() throws Exception {
+ final IkeNonProtocolException exception = mock(IkeNonProtocolException.class);
+ final UnknownHostException unknownHostException = new UnknownHostException();
+ final int errorCode = VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST;
+ when(exception.getCause()).thenReturn(unknownHostException);
+ setupPlatformVpnWithSpecificExceptionAndItsErrorCode(exception,
+ VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE,
+ errorCode);
+ }
+
+ @Test
+ public void testStartPlatformVpnFailedWithIkeTimeoutException() throws Exception {
+ final IkeNonProtocolException exception = mock(IkeNonProtocolException.class);
+ final IkeTimeoutException ikeTimeoutException =
+ new IkeTimeoutException("IkeTimeoutException");
+ final int errorCode = VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT;
+ when(exception.getCause()).thenReturn(ikeTimeoutException);
+ setupPlatformVpnWithSpecificExceptionAndItsErrorCode(exception,
+ VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE,
+ errorCode);
+ }
+
+ @Test
+ public void testStartPlatformVpnFailedWithIkeNetworkLostException() throws Exception {
+ final IkeNetworkLostException exception = new IkeNetworkLostException(
+ new Network(100));
+ setupPlatformVpnWithSpecificExceptionAndItsErrorCode(exception,
+ VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE,
+ VpnManager.ERROR_CODE_NETWORK_LOST);
+ }
+
+ @Test
+ public void testStartPlatformVpnFailedWithIOException() throws Exception {
+ final IkeNonProtocolException exception = mock(IkeNonProtocolException.class);
+ final IOException ioException = new IOException();
+ final int errorCode = VpnManager.ERROR_CODE_NETWORK_IO;
+ when(exception.getCause()).thenReturn(ioException);
+ setupPlatformVpnWithSpecificExceptionAndItsErrorCode(exception,
+ VpnManager.CATEGORY_EVENT_NETWORK_ERROR, VpnManager.ERROR_CLASS_RECOVERABLE,
+ errorCode);
}
@Test
diff --git a/tests/unit/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/unit/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
index 8e43253..4f849d2 100644
--- a/tests/unit/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
+++ b/tests/unit/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
@@ -16,8 +16,6 @@
package com.android.server.ethernet;
-import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
@@ -55,20 +53,20 @@
import android.net.StaticIpConfiguration;
import android.net.ip.IpClientCallbacks;
import android.net.ip.IpClientManager;
+import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.test.TestLooper;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.net.module.util.InterfaceParams;
import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -80,8 +78,9 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
-@RunWith(AndroidJUnit4.class)
@SmallTest
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class EthernetNetworkFactoryTest {
private static final int TIMEOUT_MS = 2_000;
private static final String TEST_IFACE = "test123";
@@ -298,7 +297,6 @@
clearInvocations(mNetworkAgent);
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateInterfaceLinkStateForActiveProvisioningInterface() throws Exception {
initEthernetNetworkFactory();
@@ -314,7 +312,6 @@
assertEquals(listener.expectOnResult(), TEST_IFACE);
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateInterfaceLinkStateForProvisionedInterface() throws Exception {
initEthernetNetworkFactory();
@@ -329,7 +326,6 @@
assertEquals(listener.expectOnResult(), TEST_IFACE);
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateInterfaceLinkStateForUnprovisionedInterface() throws Exception {
initEthernetNetworkFactory();
@@ -347,7 +343,6 @@
assertEquals(listener.expectOnResult(), TEST_IFACE);
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateInterfaceLinkStateForNonExistingInterface() throws Exception {
initEthernetNetworkFactory();
@@ -362,7 +357,6 @@
listener.expectOnError();
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateInterfaceLinkStateWithNoChanges() throws Exception {
initEthernetNetworkFactory();
@@ -377,7 +371,6 @@
listener.expectOnError();
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testProvisioningLoss() throws Exception {
initEthernetNetworkFactory();
@@ -390,7 +383,6 @@
verify(mIpClient).startProvisioning(any());
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testProvisioningLossForDisappearedInterface() throws Exception {
initEthernetNetworkFactory();
@@ -412,7 +404,6 @@
verify(mIpClient, never()).startProvisioning(any());
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testLinkPropertiesChanged() throws Exception {
initEthernetNetworkFactory();
@@ -424,7 +415,6 @@
verify(mNetworkAgent).sendLinkPropertiesImpl(same(lp));
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testNetworkUnwanted() throws Exception {
initEthernetNetworkFactory();
@@ -435,7 +425,6 @@
verifyStop();
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testNetworkUnwantedWithStaleNetworkAgent() throws Exception {
initEthernetNetworkFactory();
@@ -460,7 +449,6 @@
verify(mNetworkAgent, never()).unregister();
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testTransportOverrideIsCorrectlySet() throws Exception {
initEthernetNetworkFactory();
@@ -482,7 +470,6 @@
ConnectivityManager.TYPE_NONE);
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testReachabilityLoss() throws Exception {
initEthernetNetworkFactory();
@@ -503,7 +490,6 @@
return staleIpClientCallbacks;
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testIgnoreOnIpLayerStartedCallbackForStaleCallback() throws Exception {
initEthernetNetworkFactory();
@@ -516,7 +502,6 @@
verify(mNetworkAgent, never()).register();
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testIgnoreOnIpLayerStoppedCallbackForStaleCallback() throws Exception {
initEthernetNetworkFactory();
@@ -529,7 +514,6 @@
verify(mIpClient, never()).startProvisioning(any());
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testIgnoreLinkPropertiesCallbackForStaleCallback() throws Exception {
initEthernetNetworkFactory();
@@ -542,7 +526,6 @@
verify(mNetworkAgent, never()).sendLinkPropertiesImpl(eq(lp));
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testIgnoreNeighborLossCallbackForStaleCallback() throws Exception {
initEthernetNetworkFactory();
@@ -611,7 +594,6 @@
}
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateInterfaceCallsListenerCorrectlyOnSuccess() throws Exception {
initEthernetNetworkFactory();
@@ -626,8 +608,6 @@
assertEquals(listener.expectOnResult(), TEST_IFACE);
}
- @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateInterfaceAbortsOnConcurrentRemoveInterface() throws Exception {
initEthernetNetworkFactory();
@@ -636,8 +616,6 @@
() -> mNetFactory.removeInterface(TEST_IFACE));
}
- @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateInterfaceAbortsOnConcurrentUpdateInterfaceLinkState() throws Exception {
initEthernetNetworkFactory();
@@ -646,8 +624,6 @@
() -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER));
}
- @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateInterfaceCallsListenerCorrectlyOnConcurrentRequests() throws Exception {
initEthernetNetworkFactory();
@@ -684,7 +660,6 @@
failedListener.expectOnError();
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateInterfaceRestartsAgentCorrectly() throws Exception {
initEthernetNetworkFactory();
@@ -702,7 +677,6 @@
verifyRestart(ipConfiguration);
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateInterfaceForNonExistingInterface() throws Exception {
initEthernetNetworkFactory();
@@ -717,7 +691,6 @@
listener.expectOnError();
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateInterfaceWithNullIpConfiguration() throws Exception {
initEthernetNetworkFactory();
diff --git a/tests/unit/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/unit/java/com/android/server/ethernet/EthernetServiceImplTest.java
index e8e54f8..b2b9f2c 100644
--- a/tests/unit/java/com/android/server/ethernet/EthernetServiceImplTest.java
+++ b/tests/unit/java/com/android/server/ethernet/EthernetServiceImplTest.java
@@ -20,12 +20,12 @@
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
-
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
@@ -35,24 +35,25 @@
import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.net.INetworkInterfaceOutcomeReceiver;
import android.net.EthernetNetworkUpdateRequest;
+import android.net.INetworkInterfaceOutcomeReceiver;
import android.net.IpConfiguration;
import android.net.NetworkCapabilities;
+import android.os.Build;
import android.os.Handler;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-@RunWith(AndroidJUnit4.class)
@SmallTest
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class EthernetServiceImplTest {
private static final String TEST_IFACE = "test123";
private static final EthernetNetworkUpdateRequest UPDATE_REQUEST =
@@ -70,14 +71,17 @@
.build();
private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null;
private EthernetServiceImpl mEthernetServiceImpl;
- @Mock private Context mContext;
- @Mock private Handler mHandler;
- @Mock private EthernetTracker mEthernetTracker;
- @Mock private PackageManager mPackageManager;
+ private Context mContext;
+ private Handler mHandler;
+ private EthernetTracker mEthernetTracker;
+ private PackageManager mPackageManager;
@Before
public void setup() {
- MockitoAnnotations.initMocks(this);
+ mContext = mock(Context.class);
+ mHandler = mock(Handler.class);
+ mEthernetTracker = mock(EthernetTracker.class);
+ mPackageManager = mock(PackageManager.class);
doReturn(mPackageManager).when(mContext).getPackageManager();
mEthernetServiceImpl = new EthernetServiceImpl(mContext, mHandler, mEthernetTracker);
mEthernetServiceImpl.mStarted.set(true);
@@ -94,7 +98,6 @@
doReturn(shouldTrack).when(mEthernetTracker).isTrackingInterface(iface);
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testSetConfigurationRejectsWhenEthNotStarted() {
mEthernetServiceImpl.mStarted.set(false);
@@ -103,7 +106,6 @@
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateConfigurationRejectsWhenEthNotStarted() {
mEthernetServiceImpl.mStarted.set(false);
@@ -113,25 +115,22 @@
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testConnectNetworkRejectsWhenEthNotStarted() {
+ public void testEnableInterfaceRejectsWhenEthNotStarted() {
mEthernetServiceImpl.mStarted.set(false);
assertThrows(IllegalStateException.class, () -> {
- mEthernetServiceImpl.connectNetwork("" /* iface */, null /* listener */);
+ mEthernetServiceImpl.enableInterface("" /* iface */, null /* listener */);
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testDisconnectNetworkRejectsWhenEthNotStarted() {
+ public void testDisableInterfaceRejectsWhenEthNotStarted() {
mEthernetServiceImpl.mStarted.set(false);
assertThrows(IllegalStateException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork("" /* iface */, null /* listener */);
+ mEthernetServiceImpl.disableInterface("" /* iface */, null /* listener */);
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateConfigurationRejectsNullIface() {
assertThrows(NullPointerException.class, () -> {
@@ -139,23 +138,20 @@
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testConnectNetworkRejectsNullIface() {
+ public void testEnableInterfaceRejectsNullIface() {
assertThrows(NullPointerException.class, () -> {
- mEthernetServiceImpl.connectNetwork(null /* iface */, NULL_LISTENER);
+ mEthernetServiceImpl.enableInterface(null /* iface */, NULL_LISTENER);
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testDisconnectNetworkRejectsNullIface() {
+ public void testDisableInterfaceRejectsNullIface() {
assertThrows(NullPointerException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork(null /* iface */, NULL_LISTENER);
+ mEthernetServiceImpl.disableInterface(null /* iface */, NULL_LISTENER);
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateConfigurationWithCapabilitiesRejectsWithoutAutomotiveFeature() {
toggleAutomotiveFeature(false);
@@ -164,7 +160,6 @@
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateConfigurationWithCapabilitiesWithAutomotiveFeature() {
toggleAutomotiveFeature(false);
@@ -175,24 +170,6 @@
eq(UPDATE_REQUEST_WITHOUT_CAPABILITIES.getNetworkCapabilities()), isNull());
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
- @Test
- public void testConnectNetworkRejectsWithoutAutomotiveFeature() {
- toggleAutomotiveFeature(false);
- assertThrows(UnsupportedOperationException.class, () -> {
- mEthernetServiceImpl.connectNetwork("" /* iface */, NULL_LISTENER);
- });
- }
-
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
- @Test
- public void testDisconnectNetworkRejectsWithoutAutomotiveFeature() {
- toggleAutomotiveFeature(false);
- assertThrows(UnsupportedOperationException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork("" /* iface */, NULL_LISTENER);
- });
- }
-
private void denyManageEthPermission() {
doThrow(new SecurityException("")).when(mContext)
.enforceCallingOrSelfPermission(
@@ -205,7 +182,6 @@
eq(Manifest.permission.MANAGE_TEST_NETWORKS), anyString());
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateConfigurationRejectsWithoutManageEthPermission() {
denyManageEthPermission();
@@ -214,21 +190,19 @@
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testConnectNetworkRejectsWithoutManageEthPermission() {
+ public void testEnableInterfaceRejectsWithoutManageEthPermission() {
denyManageEthPermission();
assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER);
+ mEthernetServiceImpl.enableInterface(TEST_IFACE, NULL_LISTENER);
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testDisconnectNetworkRejectsWithoutManageEthPermission() {
+ public void testDisableInterfaceRejectsWithoutManageEthPermission() {
denyManageEthPermission();
assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER);
+ mEthernetServiceImpl.disableInterface(TEST_IFACE, NULL_LISTENER);
});
}
@@ -236,7 +210,6 @@
when(mEthernetTracker.isValidTestInterface(eq(TEST_IFACE))).thenReturn(true);
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateConfigurationRejectsTestRequestWithoutTestPermission() {
enableTestInterface();
@@ -246,27 +219,24 @@
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testConnectNetworkRejectsTestRequestWithoutTestPermission() {
+ public void testEnableInterfaceRejectsTestRequestWithoutTestPermission() {
enableTestInterface();
denyManageTestNetworksPermission();
assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER);
+ mEthernetServiceImpl.enableInterface(TEST_IFACE, NULL_LISTENER);
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testDisconnectNetworkRejectsTestRequestWithoutTestPermission() {
+ public void testDisableInterfaceRejectsTestRequestWithoutTestPermission() {
enableTestInterface();
denyManageTestNetworksPermission();
assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER);
+ mEthernetServiceImpl.disableInterface(TEST_IFACE, NULL_LISTENER);
});
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateConfiguration() {
mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER);
@@ -276,21 +246,18 @@
eq(UPDATE_REQUEST.getNetworkCapabilities()), eq(NULL_LISTENER));
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testConnectNetwork() {
- mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER);
- verify(mEthernetTracker).connectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER));
+ public void testEnableInterface() {
+ mEthernetServiceImpl.enableInterface(TEST_IFACE, NULL_LISTENER);
+ verify(mEthernetTracker).enableInterface(eq(TEST_IFACE), eq(NULL_LISTENER));
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testDisconnectNetwork() {
- mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER);
- verify(mEthernetTracker).disconnectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER));
+ public void testDisableInterface() {
+ mEthernetServiceImpl.disableInterface(TEST_IFACE, NULL_LISTENER);
+ verify(mEthernetTracker).disableInterface(eq(TEST_IFACE), eq(NULL_LISTENER));
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateConfigurationAcceptsTestRequestWithNullCapabilities() {
enableTestInterface();
@@ -304,7 +271,6 @@
eq(request.getNetworkCapabilities()), isNull());
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateConfigurationAcceptsRequestWithNullIpConfiguration() {
mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST_WITHOUT_IP_CONFIG,
@@ -314,7 +280,6 @@
eq(UPDATE_REQUEST_WITHOUT_IP_CONFIG.getNetworkCapabilities()), isNull());
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateConfigurationRejectsInvalidTestRequest() {
enableTestInterface();
@@ -333,7 +298,6 @@
.setNetworkCapabilities(nc).build();
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateConfigurationForTestRequestDoesNotRequireAutoOrEthernetPermission() {
enableTestInterface();
@@ -348,26 +312,24 @@
eq(request.getNetworkCapabilities()), eq(NULL_LISTENER));
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testConnectNetworkForTestRequestDoesNotRequireAutoOrNetPermission() {
+ public void testEnableInterfaceForTestRequestDoesNotRequireNetPermission() {
enableTestInterface();
toggleAutomotiveFeature(false);
denyManageEthPermission();
- mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER);
- verify(mEthernetTracker).connectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER));
+ mEthernetServiceImpl.enableInterface(TEST_IFACE, NULL_LISTENER);
+ verify(mEthernetTracker).enableInterface(eq(TEST_IFACE), eq(NULL_LISTENER));
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testDisconnectNetworkForTestRequestDoesNotRequireAutoOrNetPermission() {
+ public void testDisableInterfaceForTestRequestDoesNotRequireAutoOrNetPermission() {
enableTestInterface();
toggleAutomotiveFeature(false);
denyManageEthPermission();
- mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER);
- verify(mEthernetTracker).disconnectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER));
+ mEthernetServiceImpl.disableInterface(TEST_IFACE, NULL_LISTENER);
+ verify(mEthernetTracker).disableInterface(eq(TEST_IFACE), eq(NULL_LISTENER));
}
private void denyPermissions(String... permissions) {
@@ -377,7 +339,6 @@
}
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testSetEthernetEnabled() {
denyPermissions(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
diff --git a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
index 115f0e1..4c35221 100644
--- a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
+++ b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
@@ -49,17 +49,18 @@
import android.net.LinkAddress;
import android.net.NetworkCapabilities;
import android.net.StaticIpConfiguration;
+import android.os.Build;
import android.os.HandlerThread;
import android.os.RemoteException;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import com.android.testutils.HandlerUtils;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -70,7 +71,8 @@
import java.util.ArrayList;
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class EthernetTrackerTest {
private static final String TEST_IFACE = "test123";
private static final int TIMEOUT_MS = 1_000;
@@ -112,7 +114,6 @@
/**
* Test: Creation of various valid static IP configurations
*/
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void createStaticIpConfiguration() {
// Empty gives default StaticIPConfiguration object
@@ -145,7 +146,6 @@
/**
* Test: Attempt creation of various bad static IP configurations
*/
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void createStaticIpConfiguration_Bad() {
assertStaticConfigurationFails("ip=192.0.2.1/24 gateway= blah=20.20.20.20"); // Unknown key
@@ -189,7 +189,6 @@
/**
* Test: Attempt to create a capabilties with various valid sets of capabilities/transports
*/
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void createNetworkCapabilities() {
@@ -316,7 +315,6 @@
configTransports).build());
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testCreateEthernetTrackerConfigReturnsCorrectValue() {
final String capabilities = "2";
@@ -333,14 +331,12 @@
assertEquals(transport, config.mTransport);
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testCreateEthernetTrackerConfigThrowsNpeWithNullInput() {
assertThrows(NullPointerException.class,
() -> EthernetTracker.createEthernetTrackerConfig(null));
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testUpdateConfiguration() {
final NetworkCapabilities capabilities = new NetworkCapabilities.Builder().build();
@@ -358,27 +354,24 @@
eq(TEST_IFACE), eq(ipConfig), eq(capabilities), eq(listener));
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testConnectNetworkCorrectlyCallsFactory() {
- tracker.connectNetwork(TEST_IFACE, NULL_LISTENER);
+ public void testEnableInterfaceCorrectlyCallsFactory() {
+ tracker.enableInterface(TEST_IFACE, NULL_LISTENER);
waitForIdle();
verify(mFactory).updateInterfaceLinkState(eq(TEST_IFACE), eq(true /* up */),
eq(NULL_LISTENER));
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
- public void testDisconnectNetworkCorrectlyCallsFactory() {
- tracker.disconnectNetwork(TEST_IFACE, NULL_LISTENER);
+ public void testDisableInterfaceCorrectlyCallsFactory() {
+ tracker.disableInterface(TEST_IFACE, NULL_LISTENER);
waitForIdle();
verify(mFactory).updateInterfaceLinkState(eq(TEST_IFACE), eq(false /* up */),
eq(NULL_LISTENER));
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testIsValidTestInterfaceIsFalseWhenTestInterfacesAreNotIncluded() {
final String validIfaceName = TEST_TAP_PREFIX + "123";
@@ -390,7 +383,6 @@
assertFalse(isValidTestInterface);
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testIsValidTestInterfaceIsFalseWhenTestInterfaceNameIsInvalid() {
final String invalidIfaceName = "123" + TEST_TAP_PREFIX;
@@ -402,7 +394,6 @@
assertFalse(isValidTestInterface);
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testIsValidTestInterfaceIsTrueWhenTestInterfacesIncludedAndValidName() {
final String validIfaceName = TEST_TAP_PREFIX + "123";
@@ -432,7 +423,6 @@
return ifaceParcel;
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testListenEthernetStateChange() throws Exception {
tracker.setIncludeTestInterfaces(true);
@@ -474,7 +464,6 @@
anyInt(), any());
}
- @Ignore("TODO: temporarily ignore tests until prebuilts are updated")
@Test
public void testListenEthernetStateChange_unsolicitedEventListener() throws Exception {
when(mNetd.interfaceGetList()).thenReturn(new String[] {});
diff --git a/tests/unit/java/com/android/server/net/BpfInterfaceMapUpdaterTest.java b/tests/unit/java/com/android/server/net/BpfInterfaceMapUpdaterTest.java
index 987b7b7..c6852d1 100644
--- a/tests/unit/java/com/android/server/net/BpfInterfaceMapUpdaterTest.java
+++ b/tests/unit/java/com/android/server/net/BpfInterfaceMapUpdaterTest.java
@@ -24,16 +24,18 @@
import android.content.Context;
import android.net.INetd;
import android.net.MacAddress;
+import android.os.Build;
import android.os.Handler;
import android.os.test.TestLooper;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
import com.android.net.module.util.IBpfMap;
import com.android.net.module.util.InterfaceParams;
import com.android.net.module.util.Struct.U32;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Before;
import org.junit.Test;
@@ -42,8 +44,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-@RunWith(AndroidJUnit4.class)
@SmallTest
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public final class BpfInterfaceMapUpdaterTest {
private static final int TEST_INDEX = 1;
private static final int TEST_INDEX2 = 2;
diff --git a/tests/unit/java/com/android/server/net/IpConfigStoreTest.java b/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
index e9a5309..1801c45 100644
--- a/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
+++ b/tests/unit/java/com/android/server/net/IpConfigStoreTest.java
@@ -27,9 +27,11 @@
import android.net.LinkAddress;
import android.net.ProxyInfo;
import android.net.StaticIpConfiguration;
+import android.os.Build;
import android.util.ArrayMap;
-import androidx.test.runner.AndroidJUnit4;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -46,7 +48,8 @@
/**
* Unit tests for {@link IpConfigStore}
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(DevSdkIgnoreRunner.class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
public class IpConfigStoreTest {
private static final int KEY_CONFIG = 17;
private static final String IFACE_1 = "eth0";
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
index 79744b1..5400a00 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsFactoryTest.java
@@ -29,6 +29,7 @@
import static android.net.NetworkStats.UID_ALL;
import static com.android.server.net.NetworkStatsFactory.kernelToTag;
+import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@@ -38,7 +39,6 @@
import android.net.NetworkStats;
import android.net.TrafficStats;
import android.net.UnderlyingNetworkInfo;
-import android.os.Build;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -67,7 +67,7 @@
/** Tests for {@link NetworkStatsFactory}. */
@RunWith(DevSdkIgnoreRunner.class)
@SmallTest
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
public class NetworkStatsFactoryTest extends NetworkStatsBaseTest {
private static final String CLAT_PREFIX = "v4-";
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
index 0d34609..622f2be 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
@@ -19,6 +19,8 @@
import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
+import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
@@ -37,7 +39,6 @@
import android.annotation.Nullable;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
-import android.os.Build;
import android.os.Looper;
import android.os.Parcel;
import android.telephony.SubscriptionManager;
@@ -63,7 +64,7 @@
import java.util.concurrent.Executors;
@RunWith(DevSdkIgnoreRunner.class)
-@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+@DevSdkIgnoreRule.IgnoreUpTo(SC_V2)
public final class NetworkStatsSubscriptionsMonitorTest {
private static final int TEST_SUBID1 = 3;
private static final int TEST_SUBID2 = 5;