Merge "CTS test for EthernetNetworkUpdateRequest"
diff --git a/TEST_MAPPING b/TEST_MAPPING
index c4c79c6..85072a7 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -75,9 +75,6 @@
"keywords": ["netd-device-kernel-4.9", "netd-device-kernel-4.14"]
},
{
- "name": "libnetworkstats_test"
- },
- {
"name": "FrameworksNetDeflakeTest"
}
],
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index bb40935..76c5d5c 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -105,12 +105,6 @@
certificate: "com.android.tethering",
}
-filegroup {
- name: "connectivity-hiddenapi-files",
- srcs: ["hiddenapi/*.txt"],
- visibility: ["//packages/modules/Connectivity:__subpackages__"],
-}
-
// Encapsulate the contributions made by the com.android.tethering to the bootclasspath.
bootclasspath_fragment {
name: "com.android.tethering-bootclasspath-fragment",
diff --git a/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java b/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java
index 75c2ad1..68c1c57 100644
--- a/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java
+++ b/Tethering/tests/privileged/src/com/android/networkstack/tethering/BpfMapTest.java
@@ -352,15 +352,6 @@
assertFalse(mTestMap.isEmpty());
mTestMap.clear();
assertTrue(mTestMap.isEmpty());
-
- // Clearing an already-closed map throws.
- mTestMap.close();
- try {
- mTestMap.clear();
- fail("clearing already-closed map should throw");
- } catch (IllegalStateException expected) {
- // ParcelFileDescriptor.getFd throws IllegalStateException: Already closed.
- }
}
@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/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index 80666e6..773cae3 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -195,12 +195,14 @@
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;
@@ -223,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";
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/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/dscp_policy.h b/bpf_progs/dscp_policy.h
index 777c4ff..1637f7a 100644
--- a/bpf_progs/dscp_policy.h
+++ b/bpf_progs/dscp_policy.h
@@ -26,12 +26,11 @@
#define STRUCT_SIZE(name, size) _Static_assert(sizeof(name) == (size), "Incorrect struct size.")
-#ifndef v6_equal
-#define v6_equal(a, b) (a.s6_addr32[0] == b.s6_addr32[0] && \
- a.s6_addr32[1] == b.s6_addr32[1] && \
- a.s6_addr32[2] == b.s6_addr32[2] && \
- a.s6_addr32[3] == b.s6_addr32[3])
-#endif
+#define v6_equal(a, b) \
+ (((a.s6_addr32[0] ^ b.s6_addr32[0]) | \
+ (a.s6_addr32[1] ^ b.s6_addr32[1]) | \
+ (a.s6_addr32[2] ^ b.s6_addr32[2]) | \
+ (a.s6_addr32[3] ^ b.s6_addr32[3])) == 0)
// TODO: these are already defined in packages/modules/Connectivity/bpf_progs/bpf_net_helpers.h.
// smove to common location in future.
diff --git a/bpf_progs/netd.c b/bpf_progs/netd.c
index d019257..ae92686 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>
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/Android.bp b/framework-t/Android.bp
index 8c32ded..1e508a0 100644
--- a/framework-t/Android.bp
+++ b/framework-t/Android.bp
@@ -103,7 +103,7 @@
// Do not add static_libs to this library: put them in framework-connectivity instead.
// The jarjar rules are only so that references to jarjared utils in
// framework-connectivity-pre-jarjar match at runtime.
- jarjar_rules: ":framework-connectivity-jarjar-rules",
+ jarjar_rules: ":connectivity-jarjar-rules",
permitted_packages: [
"android.app.usage",
"android.net",
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/Android.bp b/framework/Android.bp
index c8b64c7..d7de439 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -111,7 +111,6 @@
// because the tethering stubs depend on the connectivity stubs (e.g.,
// TetheringRequest depends on LinkAddress).
"framework-tethering.stubs.module_lib",
- "framework-wifi.stubs.module_lib",
],
visibility: ["//packages/modules/Connectivity:__subpackages__"]
}
@@ -120,7 +119,7 @@
name: "framework-connectivity",
defaults: ["framework-connectivity-defaults"],
installable: true,
- jarjar_rules: ":framework-connectivity-jarjar-rules",
+ jarjar_rules: ":connectivity-jarjar-rules",
permitted_packages: ["android.net"],
impl_library_visibility: [
"//packages/modules/Connectivity/Tethering/apex",
@@ -223,35 +222,3 @@
],
output_extension: "srcjar",
}
-
-java_genrule {
- name: "framework-connectivity-jarjar-rules",
- tool_files: [
- ":connectivity-hiddenapi-files",
- ":framework-connectivity-pre-jarjar",
- ":framework-connectivity-t-pre-jarjar",
- ":framework-connectivity.stubs.module_lib",
- ":framework-connectivity-t.stubs.module_lib",
- "jarjar-excludes.txt",
- ],
- tools: [
- "jarjar-rules-generator",
- "dexdump",
- ],
- out: ["framework_connectivity_jarjar_rules.txt"],
- cmd: "$(location jarjar-rules-generator) " +
- "--jars $(location :framework-connectivity-pre-jarjar) " +
- "$(location :framework-connectivity-t-pre-jarjar) " +
- "--prefix android.net.connectivity " +
- "--apistubs $(location :framework-connectivity.stubs.module_lib) " +
- "$(location :framework-connectivity-t.stubs.module_lib) " +
- "--unsupportedapi $(locations :connectivity-hiddenapi-files) " +
- "--excludes $(location jarjar-excludes.txt) " +
- "--dexdump $(location dexdump) " +
- "--output $(out)",
- visibility: [
- "//packages/modules/Connectivity/framework:__subpackages__",
- "//packages/modules/Connectivity/framework-t:__subpackages__",
- "//packages/modules/Connectivity/service",
- ],
-}
diff --git a/framework/jarjar-excludes.txt b/framework/jarjar-excludes.txt
deleted file mode 100644
index 1311765..0000000
--- a/framework/jarjar-excludes.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-# INetworkStatsProvider / INetworkStatsProviderCallback are referenced from net-tests-utils, which
-# may be used by tests that do not apply connectivity jarjar rules.
-# TODO: move files to a known internal package (like android.net.connectivity.visiblefortesting)
-# so that they do not need jarjar
-android\.net\.netstats\.provider\.INetworkStatsProvider(\$.+)?
-android\.net\.netstats\.provider\.INetworkStatsProviderCallback(\$.+)?
-
-# INetworkAgent / INetworkAgentRegistry are used in NetworkAgentTest
-# TODO: move files to android.net.connectivity.visiblefortesting
-android\.net\.INetworkAgent(\$.+)?
-android\.net\.INetworkAgentRegistry(\$.+)?
-
-# IConnectivityDiagnosticsCallback used in ConnectivityDiagnosticsManagerTest
-# TODO: move files to android.net.connectivity.visiblefortesting
-android\.net\.IConnectivityDiagnosticsCallback(\$.+)?
-
-
-# KeepaliveUtils is used by ConnectivityManager CTS
-# TODO: move into service-connectivity so framework-connectivity stops using
-# ServiceConnectivityResources (callers need high permissions to find/query the resource apk anyway)
-# and have a ConnectivityManager test API instead
-android\.net\.util\.KeepaliveUtils(\$.+)?
-
-# TODO (b/217115866): add jarjar rules for Nearby
-android\.nearby\..+
diff --git a/framework/jni/android_net_NetworkUtils.cpp b/framework/jni/android_net_NetworkUtils.cpp
index 857ece5..7478b3e 100644
--- a/framework/jni/android_net_NetworkUtils.cpp
+++ b/framework/jni/android_net_NetworkUtils.cpp
@@ -232,8 +232,7 @@
return NULL;
}
- jclass class_TcpRepairWindow = env->FindClass(
- "android/net/connectivity/android/net/TcpRepairWindow");
+ jclass class_TcpRepairWindow = env->FindClass("android/net/TcpRepairWindow");
jmethodID ctor = env->GetMethodID(class_TcpRepairWindow, "<init>", "(IIIIII)V");
return env->NewObject(class_TcpRepairWindow, ctor, trw.snd_wl1, trw.snd_wnd, trw.max_window,
@@ -254,7 +253,7 @@
{ "bindSocketToNetworkHandle", "(Ljava/io/FileDescriptor;J)I", (void*) android_net_utils_bindSocketToNetworkHandle },
{ "attachDropAllBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDropAllBPFFilter },
{ "detachBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_detachBPFFilter },
- { "getTcpRepairWindow", "(Ljava/io/FileDescriptor;)Landroid/net/connectivity/android/net/TcpRepairWindow;", (void*) android_net_utils_getTcpRepairWindow },
+ { "getTcpRepairWindow", "(Ljava/io/FileDescriptor;)Landroid/net/TcpRepairWindow;", (void*) android_net_utils_getTcpRepairWindow },
{ "resNetworkSend", "(J[BII)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkSend },
{ "resNetworkQuery", "(JLjava/lang/String;III)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkQuery },
{ "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult },
diff --git a/framework/src/android/net/DnsResolverServiceManager.java b/framework/src/android/net/DnsResolverServiceManager.java
index e64d2ae..79009e8 100644
--- a/framework/src/android/net/DnsResolverServiceManager.java
+++ b/framework/src/android/net/DnsResolverServiceManager.java
@@ -29,7 +29,7 @@
private final IBinder mResolver;
- public DnsResolverServiceManager(IBinder resolver) {
+ DnsResolverServiceManager(IBinder resolver) {
mResolver = resolver;
}
diff --git a/framework/src/android/net/NattSocketKeepalive.java b/framework/src/android/net/NattSocketKeepalive.java
index 56cc923..a15d165 100644
--- a/framework/src/android/net/NattSocketKeepalive.java
+++ b/framework/src/android/net/NattSocketKeepalive.java
@@ -33,7 +33,7 @@
@NonNull private final InetAddress mDestination;
private final int mResourceId;
- public NattSocketKeepalive(@NonNull IConnectivityManager service,
+ NattSocketKeepalive(@NonNull IConnectivityManager service,
@NonNull Network network,
@NonNull ParcelFileDescriptor pfd,
int resourceId,
@@ -48,7 +48,7 @@
}
@Override
- protected void startImpl(int intervalSec) {
+ void startImpl(int intervalSec) {
mExecutor.execute(() -> {
try {
mService.startNattKeepaliveWithFd(mNetwork, mPfd, mResourceId,
@@ -62,7 +62,7 @@
}
@Override
- protected void stopImpl() {
+ void stopImpl() {
mExecutor.execute(() -> {
try {
if (mSlot != null) {
diff --git a/framework/src/android/net/QosCallbackConnection.java b/framework/src/android/net/QosCallbackConnection.java
index cfceddd..de0fc24 100644
--- a/framework/src/android/net/QosCallbackConnection.java
+++ b/framework/src/android/net/QosCallbackConnection.java
@@ -35,7 +35,7 @@
*
* @hide
*/
-public class QosCallbackConnection extends android.net.IQosCallback.Stub {
+class QosCallbackConnection extends android.net.IQosCallback.Stub {
@NonNull private final ConnectivityManager mConnectivityManager;
@Nullable private volatile QosCallback mCallback;
@@ -56,7 +56,7 @@
* {@link Executor} must run callback sequentially, otherwise the order of
* callbacks cannot be guaranteed.
*/
- public QosCallbackConnection(@NonNull final ConnectivityManager connectivityManager,
+ QosCallbackConnection(@NonNull final ConnectivityManager connectivityManager,
@NonNull final QosCallback callback,
@NonNull final Executor executor) {
mConnectivityManager = Objects.requireNonNull(connectivityManager,
@@ -142,7 +142,7 @@
* There are no synchronization guarantees on exactly when the callback will stop receiving
* messages.
*/
- public void stopReceivingMessages() {
+ void stopReceivingMessages() {
mCallback = null;
}
}
diff --git a/framework/src/android/net/QosCallbackException.java b/framework/src/android/net/QosCallbackException.java
index 9e5d98a..b80cff4 100644
--- a/framework/src/android/net/QosCallbackException.java
+++ b/framework/src/android/net/QosCallbackException.java
@@ -85,7 +85,7 @@
* {@hide}
*/
@NonNull
- public static QosCallbackException createException(@ExceptionType final int type) {
+ static QosCallbackException createException(@ExceptionType final int type) {
switch (type) {
case EX_TYPE_FILTER_NETWORK_RELEASED:
return new QosCallbackException(new NetworkReleasedException());
diff --git a/framework/src/android/net/QosFilter.java b/framework/src/android/net/QosFilter.java
index 01dc4bb..b432644 100644
--- a/framework/src/android/net/QosFilter.java
+++ b/framework/src/android/net/QosFilter.java
@@ -33,15 +33,13 @@
@SystemApi
public abstract class QosFilter {
- /** @hide */
- protected QosFilter() {
- // Ensure that all derived types are known, and known to be properly handled when being
- // passed to and from NetworkAgent.
- // For now the only known derived type is QosSocketFilter.
- if (!(this instanceof QosSocketFilter)) {
- throw new UnsupportedOperationException(
- "Unsupported QosFilter type: " + this.getClass().getName());
- }
+ /**
+ * The constructor is kept hidden from outside this package to ensure that all derived types
+ * are known and properly handled when being passed to and from {@link NetworkAgent}.
+ *
+ * @hide
+ */
+ QosFilter() {
}
/**
diff --git a/framework/src/android/net/QosSocketInfo.java b/framework/src/android/net/QosSocketInfo.java
index da9b356..49ac22b 100644
--- a/framework/src/android/net/QosSocketInfo.java
+++ b/framework/src/android/net/QosSocketInfo.java
@@ -73,10 +73,9 @@
* The parcel file descriptor wrapped around the socket's file descriptor.
*
* @return the parcel file descriptor of the socket
- * @hide
*/
@NonNull
- public ParcelFileDescriptor getParcelFileDescriptor() {
+ ParcelFileDescriptor getParcelFileDescriptor() {
return mParcelFileDescriptor;
}
diff --git a/framework/src/android/net/SocketKeepalive.java b/framework/src/android/net/SocketKeepalive.java
index 57cf5e3..f6cae72 100644
--- a/framework/src/android/net/SocketKeepalive.java
+++ b/framework/src/android/net/SocketKeepalive.java
@@ -52,8 +52,7 @@
* request. If it does, it MUST support at least 3 concurrent keepalive slots.
*/
public abstract class SocketKeepalive implements AutoCloseable {
- /** @hide */
- protected static final String TAG = "SocketKeepalive";
+ static final String TAG = "SocketKeepalive";
/**
* Success. It indicates there is no error.
@@ -216,22 +215,15 @@
}
}
- /** @hide */
- @NonNull protected final IConnectivityManager mService;
- /** @hide */
- @NonNull protected final Network mNetwork;
- /** @hide */
- @NonNull protected final ParcelFileDescriptor mPfd;
- /** @hide */
- @NonNull protected final Executor mExecutor;
- /** @hide */
- @NonNull protected final ISocketKeepaliveCallback mCallback;
+ @NonNull final IConnectivityManager mService;
+ @NonNull final Network mNetwork;
+ @NonNull final ParcelFileDescriptor mPfd;
+ @NonNull final Executor mExecutor;
+ @NonNull final ISocketKeepaliveCallback mCallback;
// TODO: remove slot since mCallback could be used to identify which keepalive to stop.
- /** @hide */
- @Nullable protected Integer mSlot;
+ @Nullable Integer mSlot;
- /** @hide */
- public SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network,
+ SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network,
@NonNull ParcelFileDescriptor pfd,
@NonNull Executor executor, @NonNull Callback callback) {
mService = service;
@@ -311,8 +303,7 @@
startImpl(intervalSec);
}
- /** @hide */
- protected abstract void startImpl(int intervalSec);
+ abstract void startImpl(int intervalSec);
/**
* Requests that keepalive be stopped. The application must wait for {@link Callback#onStopped}
@@ -322,8 +313,7 @@
stopImpl();
}
- /** @hide */
- protected abstract void stopImpl();
+ abstract void stopImpl();
/**
* Deactivate this {@link SocketKeepalive} and free allocated resources. The instance won't be
diff --git a/framework/src/android/net/TcpSocketKeepalive.java b/framework/src/android/net/TcpSocketKeepalive.java
index 7131784..d89814d 100644
--- a/framework/src/android/net/TcpSocketKeepalive.java
+++ b/framework/src/android/net/TcpSocketKeepalive.java
@@ -24,9 +24,9 @@
import java.util.concurrent.Executor;
/** @hide */
-public final class TcpSocketKeepalive extends SocketKeepalive {
+final class TcpSocketKeepalive extends SocketKeepalive {
- public TcpSocketKeepalive(@NonNull IConnectivityManager service,
+ TcpSocketKeepalive(@NonNull IConnectivityManager service,
@NonNull Network network,
@NonNull ParcelFileDescriptor pfd,
@NonNull Executor executor,
@@ -50,7 +50,7 @@
* acknowledgement.
*/
@Override
- protected void startImpl(int intervalSec) {
+ void startImpl(int intervalSec) {
mExecutor.execute(() -> {
try {
mService.startTcpKeepalive(mNetwork, mPfd, intervalSec, mCallback);
@@ -62,7 +62,7 @@
}
@Override
- protected void stopImpl() {
+ void stopImpl() {
mExecutor.execute(() -> {
try {
if (mSlot != null) {
diff --git a/netd/BpfHandler.cpp b/netd/BpfHandler.cpp
index 08e66d9..42d0de5 100644
--- a/netd/BpfHandler.cpp
+++ b/netd/BpfHandler.cpp
@@ -104,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;
}
@@ -233,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/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
index 4d605ce..6c7a15e 100644
--- a/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
+++ b/service-t/native/libs/libnetworkstats/BpfNetworkStats.cpp
@@ -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/EthernetConfigStore.java b/service-t/src/com/android/server/ethernet/EthernetConfigStore.java
index 6b623f4..6006539 100644
--- a/service-t/src/com/android/server/ethernet/EthernetConfigStore.java
+++ b/service-t/src/com/android/server/ethernet/EthernetConfigStore.java
@@ -16,23 +16,37 @@
package com.android.server.ethernet;
+import static com.android.net.module.util.DeviceConfigUtils.TETHERING_MODULE_NAME;
+
import android.annotation.Nullable;
+import android.content.ApexEnvironment;
import android.net.IpConfiguration;
import android.os.Environment;
import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.net.IpConfigStore;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
/**
* This class provides an API to store and manage Ethernet network configuration.
*/
public class EthernetConfigStore {
- private static final String ipConfigFile = Environment.getDataDirectory() +
- "/misc/ethernet/ipconfig.txt";
+ private static final String TAG = EthernetConfigStore.class.getSimpleName();
+ private static final String CONFIG_FILE = "ipconfig.txt";
+ private static final String FILE_PATH = "/misc/ethernet/";
+ private static final String LEGACY_IP_CONFIG_FILE_PATH = Environment.getDataDirectory()
+ + FILE_PATH;
+ private static final String APEX_IP_CONFIG_FILE_PATH = ApexEnvironment.getApexEnvironment(
+ TETHERING_MODULE_NAME).getDeviceProtectedDataDir() + FILE_PATH;
private IpConfigStore mStore = new IpConfigStore();
- private ArrayMap<String, IpConfiguration> mIpConfigurations;
+ private final ArrayMap<String, IpConfiguration> mIpConfigurations;
private IpConfiguration mIpConfigurationForDefaultInterface;
private final Object mSync = new Object();
@@ -40,22 +54,70 @@
mIpConfigurations = new ArrayMap<>(0);
}
- public void read() {
- synchronized (mSync) {
- ArrayMap<String, IpConfiguration> configs =
- IpConfigStore.readIpConfigurations(ipConfigFile);
+ private static boolean doesConfigFileExist(final String filepath) {
+ return new File(filepath).exists();
+ }
- // This configuration may exist in old file versions when there was only a single active
- // Ethernet interface.
- if (configs.containsKey("0")) {
- mIpConfigurationForDefaultInterface = configs.remove("0");
+ private void writeLegacyIpConfigToApexPath(final String newFilePath, final String oldFilePath,
+ final String filename) {
+ final File directory = new File(newFilePath);
+ if (!directory.exists()) {
+ directory.mkdirs();
+ }
+
+ // Write the legacy IP config to the apex file path.
+ FileOutputStream fos = null;
+ final AtomicFile dst = new AtomicFile(new File(newFilePath + filename));
+ final AtomicFile src = new AtomicFile(new File(oldFilePath + filename));
+ try {
+ final byte[] raw = src.readFully();
+ if (raw.length > 0) {
+ fos = dst.startWrite();
+ fos.write(raw);
+ fos.flush();
+ dst.finishWrite(fos);
}
-
- mIpConfigurations = configs;
+ } catch (IOException e) {
+ Log.e(TAG, "Fail to sync the legacy IP config to the apex file path.");
+ dst.failWrite(fos);
}
}
+ public void read() {
+ read(APEX_IP_CONFIG_FILE_PATH, LEGACY_IP_CONFIG_FILE_PATH, CONFIG_FILE);
+ }
+
+ @VisibleForTesting
+ void read(final String newFilePath, final String oldFilePath, final String filename) {
+ synchronized (mSync) {
+ // Attempt to read the IP configuration from apex file path first.
+ if (doesConfigFileExist(newFilePath + filename)) {
+ loadConfigFileLocked(newFilePath + filename);
+ return;
+ }
+
+ // If the config file doesn't exist in the apex file path, attempt to read it from
+ // the legacy file path, if config file exists, write the legacy IP configuration to
+ // apex config file path, this should just happen on the first boot. New or updated
+ // config entries are only written to the apex config file later.
+ if (!doesConfigFileExist(oldFilePath + filename)) return;
+ loadConfigFileLocked(oldFilePath + filename);
+ writeLegacyIpConfigToApexPath(newFilePath, oldFilePath, filename);
+ }
+ }
+
+ private void loadConfigFileLocked(final String filepath) {
+ final ArrayMap<String, IpConfiguration> configs =
+ IpConfigStore.readIpConfigurations(filepath);
+ mIpConfigurations.putAll(configs);
+ }
+
public void write(String iface, IpConfiguration config) {
+ write(iface, config, APEX_IP_CONFIG_FILE_PATH + CONFIG_FILE);
+ }
+
+ @VisibleForTesting
+ void write(String iface, IpConfiguration config, String filepath) {
boolean modified;
synchronized (mSync) {
@@ -67,7 +129,7 @@
}
if (modified) {
- mStore.writeIpConfigurations(ipConfigFile, mIpConfigurations);
+ mStore.writeIpConfigurations(filepath, mIpConfigurations);
}
}
}
@@ -80,9 +142,6 @@
@Nullable
public IpConfiguration getIpConfigurationForDefaultInterface() {
- synchronized (mSync) {
- return mIpConfigurationForDefaultInterface == null
- ? null : new IpConfiguration(mIpConfigurationForDefaultInterface);
- }
+ return null;
}
}
diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
index e2cceda..79802fb 100644
--- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
+++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
@@ -31,10 +31,9 @@
import android.net.LinkProperties;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
-import android.net.NetworkFactory;
import android.net.NetworkProvider;
import android.net.NetworkRequest;
-import android.net.NetworkSpecifier;
+import android.net.NetworkScore;
import android.net.ip.IIpClient;
import android.net.ip.IpClientCallbacks;
import android.net.ip.IpClientManager;
@@ -61,22 +60,19 @@
import java.util.concurrent.ConcurrentHashMap;
/**
- * {@link NetworkFactory} that represents Ethernet networks.
- *
- * This class reports a static network score of 70 when it is tracking an interface and that
- * interface's link is up, and a score of 0 otherwise.
+ * {@link NetworkProvider} that manages NetworkOffers for Ethernet networks.
*/
-public class EthernetNetworkFactory extends NetworkFactory {
+public class EthernetNetworkFactory {
private final static String TAG = EthernetNetworkFactory.class.getSimpleName();
final static boolean DBG = true;
- private final static int NETWORK_SCORE = 70;
private static final String NETWORK_TYPE = "Ethernet";
private final ConcurrentHashMap<String, NetworkInterfaceState> mTrackingInterfaces =
new ConcurrentHashMap<>();
private final Handler mHandler;
private final Context mContext;
+ private final NetworkProvider mProvider;
final Dependencies mDeps;
public static class Dependencies {
@@ -111,54 +107,24 @@
}
public EthernetNetworkFactory(Handler handler, Context context) {
- this(handler, context, new Dependencies());
+ this(handler, context, new NetworkProvider(context, handler.getLooper(), TAG),
+ new Dependencies());
}
@VisibleForTesting
- EthernetNetworkFactory(Handler handler, Context context, Dependencies deps) {
- super(handler.getLooper(), context, NETWORK_TYPE, createDefaultNetworkCapabilities());
-
+ EthernetNetworkFactory(Handler handler, Context context, NetworkProvider provider,
+ Dependencies deps) {
mHandler = handler;
mContext = context;
+ mProvider = provider;
mDeps = deps;
-
- setScoreFilter(NETWORK_SCORE);
}
- @Override
- public boolean acceptRequest(NetworkRequest request) {
- if (DBG) {
- Log.d(TAG, "acceptRequest, request: " + request);
- }
-
- return networkForRequest(request) != null;
- }
-
- @Override
- protected void needNetworkFor(NetworkRequest networkRequest) {
- NetworkInterfaceState network = networkForRequest(networkRequest);
-
- if (network == null) {
- Log.e(TAG, "needNetworkFor, failed to get a network for " + networkRequest);
- return;
- }
-
- if (++network.refCount == 1) {
- network.start();
- }
- }
-
- @Override
- protected void releaseNetworkFor(NetworkRequest networkRequest) {
- NetworkInterfaceState network = networkForRequest(networkRequest);
- if (network == null) {
- Log.e(TAG, "releaseNetworkFor, failed to get a network for " + networkRequest);
- return;
- }
-
- if (--network.refCount == 0) {
- network.stop();
- }
+ /**
+ * Registers the network provider with the system.
+ */
+ public void register() {
+ mContext.getSystemService(ConnectivityManager.class).registerNetworkProvider(mProvider);
}
/**
@@ -196,9 +162,8 @@
}
final NetworkInterfaceState iface = new NetworkInterfaceState(
- ifaceName, hwAddress, mHandler, mContext, ipConfig, nc, getProvider(), mDeps);
+ ifaceName, hwAddress, mHandler, mContext, ipConfig, nc, mProvider, mDeps);
mTrackingInterfaces.put(ifaceName, iface);
- updateCapabilityFilter();
}
@VisibleForTesting
@@ -239,7 +204,6 @@
final NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName);
iface.updateInterface(ipConfig, capabilities, listener);
mTrackingInterfaces.put(ifaceName, iface);
- updateCapabilityFilter();
}
private static NetworkCapabilities mixInCapabilities(NetworkCapabilities nc,
@@ -250,16 +214,6 @@
return builder.build();
}
- private void updateCapabilityFilter() {
- NetworkCapabilities capabilitiesFilter = createDefaultNetworkCapabilities();
- for (NetworkInterfaceState iface: mTrackingInterfaces.values()) {
- capabilitiesFilter = mixInCapabilities(capabilitiesFilter, iface.mCapabilities);
- }
-
- if (DBG) Log.d(TAG, "updateCapabilityFilter: " + capabilitiesFilter);
- setCapabilityFilter(capabilitiesFilter);
- }
-
private static NetworkCapabilities createDefaultNetworkCapabilities() {
return NetworkCapabilities.Builder
.withoutDefaultCapabilities()
@@ -270,11 +224,8 @@
protected void removeInterface(String interfaceName) {
NetworkInterfaceState iface = mTrackingInterfaces.remove(interfaceName);
if (iface != null) {
- iface.maybeSendNetworkManagementCallbackForAbort();
- iface.stop();
+ iface.destroy();
}
-
- updateCapabilityFilter();
}
/** Returns true if state has been modified */
@@ -306,37 +257,6 @@
return mTrackingInterfaces.containsKey(ifaceName);
}
- private NetworkInterfaceState networkForRequest(NetworkRequest request) {
- String requestedIface = null;
-
- NetworkSpecifier specifier = request.getNetworkSpecifier();
- if (specifier instanceof EthernetNetworkSpecifier) {
- requestedIface = ((EthernetNetworkSpecifier) specifier)
- .getInterfaceName();
- }
-
- NetworkInterfaceState network = null;
- if (!TextUtils.isEmpty(requestedIface)) {
- NetworkInterfaceState n = mTrackingInterfaces.get(requestedIface);
- if (n != null && request.canBeSatisfiedBy(n.mCapabilities)) {
- network = n;
- }
- } else {
- for (NetworkInterfaceState n : mTrackingInterfaces.values()) {
- if (request.canBeSatisfiedBy(n.mCapabilities) && n.mLinkUp) {
- network = n;
- break;
- }
- }
- }
-
- if (DBG) {
- Log.i(TAG, "networkForRequest, request: " + request + ", network: " + network);
- }
-
- return network;
- }
-
private static void maybeSendNetworkManagementCallback(
@Nullable final INetworkInterfaceOutcomeReceiver listener,
@Nullable final String iface,
@@ -401,8 +321,6 @@
ConnectivityManager.TYPE_NONE);
}
- long refCount = 0;
-
private class EthernetIpClientCallback extends IpClientCallbacks {
private final ConditionVariable mIpClientStartCv = new ConditionVariable(false);
private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false);
@@ -476,6 +394,9 @@
private class EthernetNetworkOfferCallback implements NetworkProvider.NetworkOfferCallback {
@Override
public void onNetworkNeeded(@NonNull NetworkRequest request) {
+ if (DBG) {
+ Log.d(TAG, String.format("%s: onNetworkNeeded for request: %s", name, request));
+ }
// When the network offer is first registered, onNetworkNeeded is called with all
// existing requests.
// ConnectivityService filters requests for us based on the NetworkCapabilities
@@ -487,6 +408,10 @@
@Override
public void onNetworkUnneeded(@NonNull NetworkRequest request) {
+ if (DBG) {
+ Log.d(TAG,
+ String.format("%s: onNetworkUnneeded for request: %s", name, request));
+ }
mRequests.remove(request);
if (mRequests.isEmpty()) {
// not currently serving any requests, stop the network.
@@ -529,9 +454,21 @@
+ "transport type.");
}
+ private static NetworkScore getBestNetworkScore() {
+ return new NetworkScore.Builder().build();
+ }
+
private void setCapabilities(@NonNull final NetworkCapabilities capabilities) {
mCapabilities = new NetworkCapabilities(capabilities);
mLegacyType = getLegacyType(mCapabilities);
+
+ if (mLinkUp) {
+ // registering a new network offer will update the existing one, not install a
+ // new one.
+ mNetworkProvider.registerNetworkOffer(getBestNetworkScore(),
+ new NetworkCapabilities(capabilities), cmd -> mHandler.post(cmd),
+ mNetworkOfferCallback);
+ }
}
void updateInterface(@Nullable final IpConfiguration ipConfig,
@@ -693,20 +630,21 @@
mLinkUp = up;
if (!up) { // was up, goes down
- // Send an abort on a provisioning request callback if necessary before stopping.
- maybeSendNetworkManagementCallbackForAbort();
- stop();
+ // retract network offer and stop IpClient.
+ destroy();
// If only setting the interface down, send a callback to signal completion.
EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, name, null);
} else { // was down, goes up
- stop();
- start(listener);
+ // register network offer
+ mNetworkProvider.registerNetworkOffer(getBestNetworkScore(),
+ new NetworkCapabilities(mCapabilities), (cmd) -> mHandler.post(cmd),
+ mNetworkOfferCallback);
}
return true;
}
- void stop() {
+ private void stop() {
// Invalidate all previous start requests
if (mIpClient != null) {
mIpClient.shutdown();
@@ -722,6 +660,13 @@
mLinkProperties.clear();
}
+ public void destroy() {
+ mNetworkProvider.unregisterNetworkOffer(mNetworkOfferCallback);
+ maybeSendNetworkManagementCallbackForAbort();
+ stop();
+ mRequests.clear();
+ }
+
private static void provisionIpClient(@NonNull final IpClientManager ipClient,
@NonNull final IpConfiguration config, @NonNull final String tcpBufferSizes) {
if (config.getProxySettings() == ProxySettings.STATIC ||
@@ -761,7 +706,6 @@
@Override
public String toString() {
return getClass().getSimpleName() + "{ "
- + "refCount: " + refCount + ", "
+ "iface: " + name + ", "
+ "up: " + mLinkUp + ", "
+ "hwAddress: " + mHwAddress + ", "
@@ -774,7 +718,6 @@
}
void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
- super.dump(fd, pw, args);
pw.println(getClass().getSimpleName());
pw.println("Tracking interfaces:");
pw.increaseIndent();
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 e9053dd..c8a0412 100644
--- a/service-t/src/com/android/server/ethernet/EthernetTracker.java
+++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java
@@ -285,13 +285,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));
}
@@ -586,14 +586,18 @@
}
}
- private class InterfaceObserver extends BaseNetdUnsolicitedEventListener {
+ @VisibleForTesting
+ class InterfaceObserver extends BaseNetdUnsolicitedEventListener {
@Override
public void onInterfaceLinkStateChanged(String iface, boolean up) {
if (DBG) {
Log.i(TAG, "interfaceLinkStateChanged, iface: " + iface + ", up: " + up);
}
- mHandler.post(() -> updateInterfaceState(iface, up));
+ mHandler.post(() -> {
+ if (mEthernetState == ETHERNET_STATE_DISABLED) return;
+ updateInterfaceState(iface, up);
+ });
}
@Override
@@ -601,7 +605,10 @@
if (DBG) {
Log.i(TAG, "onInterfaceAdded, iface: " + iface);
}
- mHandler.post(() -> maybeTrackInterface(iface));
+ mHandler.post(() -> {
+ if (mEthernetState == ETHERNET_STATE_DISABLED) return;
+ maybeTrackInterface(iface);
+ });
}
@Override
@@ -609,7 +616,10 @@
if (DBG) {
Log.i(TAG, "onInterfaceRemoved, iface: " + iface);
}
- mHandler.post(() -> stopTrackingInterface(iface));
+ mHandler.post(() -> {
+ if (mEthernetState == ETHERNET_STATE_DISABLED) return;
+ stopTrackingInterface(iface);
+ });
}
}
@@ -888,6 +898,8 @@
void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
postAndWaitForRunnable(() -> {
pw.println(getClass().getSimpleName());
+ pw.println("Ethernet State: "
+ + (mEthernetState == ETHERNET_STATE_ENABLED ? "enabled" : "disabled"));
pw.println("Ethernet interface name filter: " + mIfaceMatch);
pw.println("Default interface: " + mDefaultInterface);
pw.println("Default interface mode: " + mDefaultInterfaceMode);
diff --git a/service/Android.bp b/service/Android.bp
index 0393c79..91b9d1c 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -224,15 +224,9 @@
lint: { strict_updatability_linting: true },
}
-genrule {
+filegroup {
name: "connectivity-jarjar-rules",
- defaults: ["jarjar-rules-combine-defaults"],
- srcs: [
- ":framework-connectivity-jarjar-rules",
- ":service-connectivity-jarjar-gen",
- ":service-nearby-jarjar-gen",
- ],
- out: ["connectivity-jarjar-rules.txt"],
+ srcs: ["jarjar-rules.txt"],
visibility: ["//packages/modules/Connectivity:__subpackages__"],
}
@@ -243,45 +237,3 @@
srcs: ["src/com/android/server/BpfNetMaps.java"],
visibility: ["//packages/modules/Connectivity:__subpackages__"],
}
-
-java_genrule {
- name: "service-connectivity-jarjar-gen",
- tool_files: [
- ":service-connectivity-pre-jarjar",
- ":service-connectivity-tiramisu-pre-jarjar",
- "jarjar-excludes.txt",
- ],
- tools: [
- "jarjar-rules-generator",
- "dexdump",
- ],
- out: ["service_connectivity_jarjar_rules.txt"],
- cmd: "$(location jarjar-rules-generator) " +
- "--jars $(location :service-connectivity-pre-jarjar) " +
- "$(location :service-connectivity-tiramisu-pre-jarjar) " +
- "--prefix android.net.connectivity " +
- "--excludes $(location jarjar-excludes.txt) " +
- "--dexdump $(location dexdump) " +
- "--output $(out)",
- visibility: ["//visibility:private"],
-}
-
-java_genrule {
- name: "service-nearby-jarjar-gen",
- tool_files: [
- ":service-nearby-pre-jarjar",
- "jarjar-excludes.txt",
- ],
- tools: [
- "jarjar-rules-generator",
- "dexdump",
- ],
- out: ["service_nearby_jarjar_rules.txt"],
- cmd: "$(location jarjar-rules-generator) " +
- "--jars $(location :service-nearby-pre-jarjar) " +
- "--prefix com.android.server.nearby " +
- "--excludes $(location jarjar-excludes.txt) " +
- "--dexdump $(location dexdump) " +
- "--output $(out)",
- visibility: ["//visibility:private"],
-}
diff --git a/service/jarjar-excludes.txt b/service/jarjar-excludes.txt
deleted file mode 100644
index b0d6763..0000000
--- a/service/jarjar-excludes.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-# Classes loaded by SystemServer via their hardcoded name, so they can't be jarjared
-com\.android\.server\.ConnectivityServiceInitializer(\$.+)?
-com\.android\.server\.NetworkStatsServiceInitializer(\$.+)?
-
-# Do not jarjar com.android.server, as several unit tests fail because they lose
-# package-private visibility between jarjared and non-jarjared classes.
-# TODO: fix the tests and also jarjar com.android.server, or at least only exclude a package that
-# is specific to the module like com.android.server.connectivity
-com\.android\.server\..+
diff --git a/service/jarjar-rules.txt b/service/jarjar-rules.txt
new file mode 100644
index 0000000..c7223fc
--- /dev/null
+++ b/service/jarjar-rules.txt
@@ -0,0 +1,123 @@
+# Classes in framework-connectivity are restricted to the android.net package.
+# This cannot be changed because it is harcoded in ART in S.
+# Any missing jarjar rule for framework-connectivity would be caught by the
+# build as an unexpected class outside of the android.net package.
+rule com.android.net.module.util.** android.net.connectivity.@0
+rule com.android.modules.utils.** android.net.connectivity.@0
+rule android.net.NetworkFactory* android.net.connectivity.@0
+
+# From modules-utils-preconditions
+rule com.android.internal.util.Preconditions* android.net.connectivity.@0
+
+# From framework-connectivity-shared-srcs
+rule android.util.LocalLog* android.net.connectivity.@0
+rule android.util.IndentingPrintWriter* android.net.connectivity.@0
+rule com.android.internal.util.IndentingPrintWriter* android.net.connectivity.@0
+rule com.android.internal.util.MessageUtils* android.net.connectivity.@0
+rule com.android.internal.util.WakeupMessage* android.net.connectivity.@0
+rule com.android.internal.util.FileRotator* android.net.connectivity.@0
+rule com.android.internal.util.ProcFileReader* android.net.connectivity.@0
+
+# From framework-connectivity-protos
+rule com.google.protobuf.** android.net.connectivity.@0
+rule android.service.** android.net.connectivity.@0
+
+rule android.sysprop.** com.android.connectivity.@0
+
+rule com.android.internal.messages.** com.android.connectivity.@0
+
+# From dnsresolver_aidl_interface (newer AIDLs should go to android.net.resolv.aidl)
+rule android.net.resolv.aidl.** com.android.connectivity.@0
+rule android.net.IDnsResolver* com.android.connectivity.@0
+rule android.net.ResolverHostsParcel* com.android.connectivity.@0
+rule android.net.ResolverOptionsParcel* com.android.connectivity.@0
+rule android.net.ResolverParamsParcel* com.android.connectivity.@0
+rule android.net.ResolverParamsParcel* com.android.connectivity.@0
+# Also includes netd event listener AIDL, but this is handled by netd-client rules
+
+# From netd-client (newer AIDLs should go to android.net.netd.aidl)
+rule android.net.netd.aidl.** com.android.connectivity.@0
+# Avoid including android.net.INetdEventCallback, used in tests but not part of the module
+rule android.net.INetd com.android.connectivity.@0
+rule android.net.INetd$* com.android.connectivity.@0
+rule android.net.INetdUnsolicitedEventListener* com.android.connectivity.@0
+rule android.net.InterfaceConfigurationParcel* com.android.connectivity.@0
+rule android.net.MarkMaskParcel* com.android.connectivity.@0
+rule android.net.NativeNetworkConfig* com.android.connectivity.@0
+rule android.net.NativeNetworkType* com.android.connectivity.@0
+rule android.net.NativeVpnType* com.android.connectivity.@0
+rule android.net.RouteInfoParcel* com.android.connectivity.@0
+rule android.net.TetherConfigParcel* com.android.connectivity.@0
+rule android.net.TetherOffloadRuleParcel* com.android.connectivity.@0
+rule android.net.TetherStatsParcel* com.android.connectivity.@0
+rule android.net.UidRangeParcel* com.android.connectivity.@0
+rule android.net.metrics.INetdEventListener* com.android.connectivity.@0
+
+# From netlink-client
+rule android.net.netlink.** com.android.connectivity.@0
+
+# From networkstack-client (newer AIDLs should go to android.net.[networkstack|ipmemorystore].aidl)
+rule android.net.networkstack.aidl.** com.android.connectivity.@0
+rule android.net.ipmemorystore.aidl.** com.android.connectivity.@0
+rule android.net.ipmemorystore.aidl.** com.android.connectivity.@0
+rule android.net.DataStallReportParcelable* com.android.connectivity.@0
+rule android.net.DhcpResultsParcelable* com.android.connectivity.@0
+rule android.net.IIpMemoryStore* com.android.connectivity.@0
+rule android.net.INetworkMonitor* com.android.connectivity.@0
+rule android.net.INetworkStackConnector* com.android.connectivity.@0
+rule android.net.INetworkStackStatusCallback* com.android.connectivity.@0
+rule android.net.InformationElementParcelable* com.android.connectivity.@0
+rule android.net.InitialConfigurationParcelable* com.android.connectivity.@0
+rule android.net.IpMemoryStore* com.android.connectivity.@0
+rule android.net.Layer2InformationParcelable* com.android.connectivity.@0
+rule android.net.Layer2PacketParcelable* com.android.connectivity.@0
+rule android.net.NattKeepalivePacketDataParcelable* com.android.connectivity.@0
+rule android.net.NetworkMonitorManager* com.android.connectivity.@0
+rule android.net.NetworkTestResultParcelable* com.android.connectivity.@0
+rule android.net.PrivateDnsConfigParcel* com.android.connectivity.@0
+rule android.net.ProvisioningConfigurationParcelable* com.android.connectivity.@0
+rule android.net.ScanResultInfoParcelable* com.android.connectivity.@0
+rule android.net.TcpKeepalivePacketDataParcelable* com.android.connectivity.@0
+rule android.net.dhcp.DhcpLeaseParcelable* com.android.connectivity.@0
+rule android.net.dhcp.DhcpServingParamsParcel* com.android.connectivity.@0
+rule android.net.dhcp.IDhcpEventCallbacks* com.android.connectivity.@0
+rule android.net.dhcp.IDhcpServer* com.android.connectivity.@0
+rule android.net.ip.IIpClient* com.android.connectivity.@0
+rule android.net.ip.IpClientCallbacks* com.android.connectivity.@0
+rule android.net.ip.IpClientManager* com.android.connectivity.@0
+rule android.net.ip.IpClientUtil* com.android.connectivity.@0
+rule android.net.ipmemorystore.** com.android.connectivity.@0
+rule android.net.networkstack.** com.android.connectivity.@0
+rule android.net.shared.** com.android.connectivity.@0
+rule android.net.util.KeepalivePacketDataUtil* com.android.connectivity.@0
+
+# From connectivity-module-utils
+rule android.net.util.SharedLog* com.android.connectivity.@0
+rule android.net.shared.** com.android.connectivity.@0
+
+# From services-connectivity-shared-srcs
+rule android.net.util.NetworkConstants* com.android.connectivity.@0
+
+# From modules-utils-statemachine
+rule com.android.internal.util.IState* com.android.connectivity.@0
+rule com.android.internal.util.State* com.android.connectivity.@0
+
+# From the API shims
+rule com.android.networkstack.apishim.** com.android.connectivity.@0
+
+# From filegroup framework-connectivity-protos
+rule android.service.*Proto com.android.connectivity.@0
+
+# From mdns-aidl-interface
+rule android.net.mdns.aidl.** android.net.connectivity.@0
+
+# From nearby-service, including proto
+rule service.proto.** com.android.server.nearby.@0
+rule androidx.annotation.Keep* com.android.server.nearby.@0
+rule androidx.collection.** com.android.server.nearby.@0
+rule androidx.core.** com.android.server.nearby.@0
+rule androidx.versionedparcelable.** com.android.server.nearby.@0
+rule com.google.common.** com.android.server.nearby.@0
+
+# Remaining are connectivity sources in com.android.server and com.android.server.connectivity:
+# TODO: move to a subpackage of com.android.connectivity (such as com.android.connectivity.server)
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/native/TrafficController.cpp b/service/native/TrafficController.cpp
index 5581c40..a9ede6a 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;
}
diff --git a/service/native/TrafficControllerTest.cpp b/service/native/TrafficControllerTest.cpp
index ad53cb8..3f13532 100644
--- a/service/native/TrafficControllerTest.cpp
+++ b/service/native/TrafficControllerTest.cpp
@@ -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/proguard.flags b/service/proguard.flags
index 557ba59..94397ab 100644
--- a/service/proguard.flags
+++ b/service/proguard.flags
@@ -2,6 +2,8 @@
# TODO: instead of keeping everything, consider listing only "entry points"
# (service loader, JNI registered methods, etc) and letting the optimizer do its job
-keep class android.net.** { *; }
+-keep class com.android.connectivity.** { *; }
+-keep class com.android.net.** { *; }
-keep class !com.android.server.nearby.**,com.android.server.** { *; }
# Prevent proguard from stripping out any nearby-service and fast-pair-lite-protos fields.
@@ -13,4 +15,4 @@
# This replicates the base proguard rule used by the build by default
# (proguard_basic_keeps.flags), but needs to be specified here because the
# com.google.protobuf package is jarjared to the below package.
--keepclassmembers class * extends com.android.server.nearby.com.google.protobuf.MessageLite { <fields>; }
+-keepclassmembers class * extends com.android.connectivity.com.google.protobuf.MessageLite { <fields>; }
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 691cb4d..f760d3b 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();
}
}
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/tests/common/Android.bp b/tests/common/Android.bp
index efea0f9..509e881 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -23,7 +23,7 @@
java_library {
name: "FrameworksNetCommonTests",
- defaults: ["framework-connectivity-internal-test-defaults"],
+ defaults: ["framework-connectivity-test-defaults"],
srcs: [
"java/**/*.java",
"java/**/*.kt",
@@ -49,7 +49,6 @@
// jarjar stops at the first matching rule, so order of concatenation affects the output.
genrule {
name: "ConnectivityCoverageJarJarRules",
- defaults: ["jarjar-rules-combine-defaults"],
srcs: [
"tethering-jni-jarjar-rules.txt",
":connectivity-jarjar-rules",
@@ -57,6 +56,8 @@
":NetworkStackJarJarRules",
],
out: ["jarjar-rules-connectivity-coverage.txt"],
+ // Concat files with a line break in the middle
+ cmd: "for src in $(in); do cat $${src}; echo; done > $(out)",
visibility: ["//visibility:private"],
}
@@ -83,7 +84,7 @@
target_sdk_version: "31",
test_suites: ["general-tests", "mts-tethering"],
defaults: [
- "framework-connectivity-internal-test-defaults",
+ "framework-connectivity-test-defaults",
"FrameworksNetTests-jni-defaults",
"libnetworkstackutilsjni_deps",
],
@@ -139,30 +140,6 @@
],
}
-// defaults for tests that need to build against framework-connectivity's @hide APIs, but also
-// using fully @hide classes that are jarjared (because they have no API member). Similar to
-// framework-connectivity-test-defaults above but uses pre-jarjar class names.
-// Only usable from targets that have visibility on framework-connectivity-pre-jarjar, and apply
-// connectivity jarjar rules so that references to jarjared classes still match: this is limited to
-// connectivity internal tests only.
-java_defaults {
- name: "framework-connectivity-internal-test-defaults",
- sdk_version: "core_platform", // tests can use @CorePlatformApi's
- libs: [
- // order matters: classes in framework-connectivity are resolved before framework,
- // meaning @hide APIs in framework-connectivity are resolved before @SystemApi
- // stubs in framework
- "framework-connectivity-pre-jarjar",
- "framework-connectivity-t-pre-jarjar",
- "framework-tethering.impl",
- "framework",
-
- // if sdk_version="" this gets automatically included, but here we need to add manually.
- "framework-res",
- ],
- defaults_visibility: ["//packages/modules/Connectivity/tests:__subpackages__"],
-}
-
// Defaults for tests that want to run in mainline-presubmit.
// Not widely used because many of our tests have AndroidTest.xml files and
// use the mainline-param config-descriptor metadata in AndroidTest.xml.
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 524bd65..93e9dcd 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -217,7 +217,10 @@
Log.d(TAG, "Expecting count " + expectedCount + " but actual is " + count + " after "
+ attempts + " attempts; sleeping "
+ SLEEP_TIME_SEC + " seconds before trying again");
- SystemClock.sleep(SLEEP_TIME_SEC * SECOND_IN_MS);
+ // No sleep after the last turn
+ if (attempts <= maxAttempts) {
+ SystemClock.sleep(SLEEP_TIME_SEC * SECOND_IN_MS);
+ }
} while (attempts <= maxAttempts);
assertEquals("Number of expected broadcasts for " + receiverName + " not reached after "
+ maxAttempts * SLEEP_TIME_SEC + " seconds", expectedCount, count);
@@ -328,7 +331,10 @@
}
Log.d(TAG, "App not on background state (" + state + ") on attempt #" + i
+ "; sleeping 1s before trying again");
- SystemClock.sleep(SECOND_IN_MS);
+ // No sleep after the last turn
+ if (i < maxTries) {
+ SystemClock.sleep(SECOND_IN_MS);
+ }
}
fail("App2 (" + mUid + ") is not on background state after "
+ maxTries + " attempts: " + state);
@@ -347,7 +353,10 @@
Log.d(TAG, "App not on foreground state on attempt #" + i
+ "; sleeping 1s before trying again");
turnScreenOn();
- SystemClock.sleep(SECOND_IN_MS);
+ // No sleep after the last turn
+ if (i < maxTries) {
+ SystemClock.sleep(SECOND_IN_MS);
+ }
}
fail("App2 (" + mUid + ") is not on foreground state after "
+ maxTries + " attempts: " + state);
@@ -365,7 +374,10 @@
}
Log.d(TAG, "App not on foreground service state on attempt #" + i
+ "; sleeping 1s before trying again");
- SystemClock.sleep(SECOND_IN_MS);
+ // No sleep after the last turn
+ if (i < maxTries) {
+ SystemClock.sleep(SECOND_IN_MS);
+ }
}
fail("App2 (" + mUid + ") is not on foreground service state after "
+ maxTries + " attempts: " + state);
@@ -506,7 +518,10 @@
Log.v(TAG, "Command '" + command + "' returned '" + result + " instead of '"
+ checker.getExpected() + "' on attempt #" + i
+ "; sleeping " + napTimeSeconds + "s before trying again");
- SystemClock.sleep(napTimeSeconds * SECOND_IN_MS);
+ // No sleep after the last turn
+ if (i < maxTries) {
+ SystemClock.sleep(napTimeSeconds * SECOND_IN_MS);
+ }
}
fail("Command '" + command + "' did not return '" + checker.getExpected() + "' after "
+ maxTries
@@ -578,7 +593,10 @@
}
Log.v(TAG, list + " check for uid " + uid + " doesn't match yet (expected "
+ expected + ", got " + actual + "); sleeping 1s before polling again");
- SystemClock.sleep(SECOND_IN_MS);
+ // No sleep after the last turn
+ if (i < maxTries) {
+ SystemClock.sleep(SECOND_IN_MS);
+ }
}
fail(list + " check for uid " + uid + " failed: expected " + expected + ", got " + actual
+ ". Full list: " + uids);
@@ -738,7 +756,8 @@
protected void assertAppIdle(boolean enabled) throws Exception {
try {
- assertDelayedShellCommand("am get-inactive " + TEST_APP2_PKG, 15, 2, "Idle=" + enabled);
+ assertDelayedShellCommand("am get-inactive " + TEST_APP2_PKG,
+ 30 /* maxTries */, 1 /* napTimeSeconds */, "Idle=" + enabled);
} catch (Throwable e) {
throw e;
}
@@ -765,7 +784,10 @@
return;
}
Log.v(TAG, "app2 receiver is not ready yet; sleeping 1s before polling again");
- SystemClock.sleep(SECOND_IN_MS);
+ // No sleep after the last turn
+ if (i < maxTries) {
+ SystemClock.sleep(SECOND_IN_MS);
+ }
}
fail("app2 receiver is not ready in " + mUid);
}
@@ -814,8 +836,6 @@
return;
} else if (type == TYPE_COMPONENT_ACTIVTIY) {
turnScreenOn();
- // Wait for screen-on state to propagate through the system.
- SystemClock.sleep(2000);
final CountDownLatch latch = new CountDownLatch(1);
final Intent launchIntent = getIntentForComponent(type);
final Bundle extras = new Bundle();
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
index 51acfdf..82f13ae 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/MyActivity.java
@@ -29,6 +29,7 @@
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
+import android.view.WindowManager;
import androidx.annotation.GuardedBy;
@@ -46,6 +47,8 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "MyActivity.onCreate()");
+
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
@Override
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/api23Test/Android.bp b/tests/cts/net/api23Test/Android.bp
index 5b37294..9b81a56 100644
--- a/tests/cts/net/api23Test/Android.bp
+++ b/tests/cts/net/api23Test/Android.bp
@@ -51,5 +51,8 @@
"cts",
"general-tests",
],
-
+ data: [
+ ":CtsNetTestAppForApi23",
+ ],
+ per_testcase_directory: true,
}
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 8f6786f..3b88189 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -3235,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 b12c4db..0a02593 100644
--- a/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/EthernetManagerTest.kt
@@ -19,9 +19,16 @@
import android.Manifest.permission.MANAGE_TEST_NETWORKS
import android.Manifest.permission.NETWORK_SETTINGS
import android.content.Context
+import android.net.ConnectivityManager
+import android.net.EthernetNetworkSpecifier
import android.net.InetAddresses
import android.net.IpConfiguration
import android.net.MacAddress
+import android.net.Network
+import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
+import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
+import android.net.NetworkCapabilities.TRANSPORT_TEST
+import android.net.NetworkRequest
import android.net.TestNetworkInterface
import android.net.TestNetworkManager
import android.net.cts.EthernetManagerTest.EthernetStateListener.CallbackEntry.InterfaceStateChanged
@@ -41,10 +48,14 @@
import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_ABSENT
import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_LINK_DOWN
import com.android.networkstack.apishim.common.EthernetManagerShim.STATE_LINK_UP
+import com.android.testutils.anyNetwork
import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.RecorderCallback.CallbackEntry.Available
+import com.android.testutils.RecorderCallback.CallbackEntry.Lost
import com.android.testutils.RouterAdvertisementResponder
import com.android.testutils.SC_V2
import com.android.testutils.TapPacketReader
+import com.android.testutils.TestableNetworkCallback
import com.android.testutils.runAsShell
import com.android.testutils.waitForIdle
import org.junit.After
@@ -53,10 +64,9 @@
import org.junit.Test
import org.junit.runner.RunWith
import java.net.Inet6Address
-import java.net.NetworkInterface
-import java.util.concurrent.Executor
import kotlin.test.assertEquals
import kotlin.test.assertFalse
+import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue
import kotlin.test.fail
@@ -65,6 +75,11 @@
private const val NO_CALLBACK_TIMEOUT_MS = 200L
private val DEFAULT_IP_CONFIGURATION = IpConfiguration(IpConfiguration.IpAssignment.DHCP,
IpConfiguration.ProxySettings.NONE, null, null)
+private val ETH_REQUEST: NetworkRequest = NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_TEST)
+ .addTransportType(TRANSPORT_ETHERNET)
+ .removeCapability(NET_CAPABILITY_TRUSTED)
+ .build()
@AppModeFull(reason = "Instant apps can't access EthernetManager")
@RunWith(AndroidJUnit4::class)
@@ -75,9 +90,12 @@
private val context by lazy { InstrumentationRegistry.getInstrumentation().context }
private val em by lazy { EthernetManagerShimImpl.newInstance(context) }
+ private val cm by lazy { context.getSystemService(ConnectivityManager::class.java) }
+ private val ifaceListener = EthernetStateListener()
private val createdIfaces = ArrayList<EthernetTestInterface>()
private val addedListeners = ArrayList<EthernetStateListener>()
+ private val networkRequests = ArrayList<TestableNetworkCallback>()
private class EthernetTestInterface(
context: Context,
@@ -93,7 +111,7 @@
val tnm = context.getSystemService(TestNetworkManager::class.java)
tnm.createTapInterface(false /* bringUp */)
}
- val mtu = NetworkInterface.getByName(tapInterface.interfaceName).getMTU()
+ val mtu = 1500
packetReader = TapPacketReader(handler, tapInterface.fileDescriptor.fileDescriptor, mtu)
raResponder = RouterAdvertisementResponder(packetReader)
raResponder.addRouterEntry(MacAddress.fromString("01:23:45:67:89:ab"),
@@ -154,6 +172,12 @@
return events.poll(TIMEOUT_MS) ?: fail("Did not receive callback after ${TIMEOUT_MS}ms")
}
+ fun eventuallyExpect(expected: CallbackEntry) = events.poll(TIMEOUT_MS) { it == expected }
+
+ fun eventuallyExpect(iface: EthernetTestInterface, state: Int, role: Int) {
+ assertNotNull(eventuallyExpect(createChangeEvent(iface, state, role)))
+ }
+
fun assertNoCallback() {
val cb = events.poll(NO_CALLBACK_TIMEOUT_MS)
assertNull(cb, "Expected no callback but got $cb")
@@ -163,6 +187,7 @@
@Before
fun setUp() {
setIncludeTestInterfaces(true)
+ addInterfaceStateListener(ifaceListener)
}
@After
@@ -170,24 +195,32 @@
setIncludeTestInterfaces(false)
for (iface in createdIfaces) {
iface.destroy()
+ ifaceListener.eventuallyExpect(iface, STATE_ABSENT, ROLE_NONE)
}
for (listener in addedListeners) {
em.removeInterfaceStateListener(listener)
}
+ networkRequests.forEach { cm.unregisterNetworkCallback(it) }
}
- private fun addInterfaceStateListener(executor: Executor, listener: EthernetStateListener) {
+ private fun addInterfaceStateListener(listener: EthernetStateListener) {
runAsShell(CONNECTIVITY_USE_RESTRICTED_NETWORKS) {
- em.addInterfaceStateListener(executor, listener)
+ em.addInterfaceStateListener(HandlerExecutor(Handler(Looper.getMainLooper())), listener)
}
addedListeners.add(listener)
}
private fun createInterface(): EthernetTestInterface {
- return EthernetTestInterface(
+ val iface = EthernetTestInterface(
context,
Handler(Looper.getMainLooper())
).also { createdIfaces.add(it) }
+ with(ifaceListener) {
+ // when an interface comes up, we should always see a down cb before an up cb.
+ eventuallyExpect(iface, STATE_LINK_DOWN, ROLE_CLIENT)
+ expectCallback(iface, STATE_LINK_UP, ROLE_CLIENT)
+ }
+ return iface
}
private fun setIncludeTestInterfaces(value: Boolean) {
@@ -199,16 +232,43 @@
private fun removeInterface(iface: EthernetTestInterface) {
iface.destroy()
createdIfaces.remove(iface)
+ ifaceListener.eventuallyExpect(iface, STATE_ABSENT, ROLE_NONE)
}
+ private fun requestNetwork(request: NetworkRequest): TestableNetworkCallback {
+ return TestableNetworkCallback().also {
+ cm.requestNetwork(request, it)
+ networkRequests.add(it)
+ }
+ }
+
+ private fun releaseNetwork(cb: TestableNetworkCallback) {
+ cm.unregisterNetworkCallback(cb)
+ networkRequests.remove(cb)
+ }
+
+ private fun NetworkRequest.createCopyWithEthernetSpecifier(ifaceName: String) =
+ NetworkRequest.Builder(NetworkRequest(ETH_REQUEST))
+ .setNetworkSpecifier(EthernetNetworkSpecifier(ifaceName)).build()
+
+ // It can take multiple seconds for the network to become available.
+ private fun TestableNetworkCallback.expectAvailable() =
+ expectCallback<Available>(anyNetwork(), 5000/*ms timeout*/).network
+
+ // b/233534110: eventuallyExpect<Lost>() does not advance ReadHead, use
+ // eventuallyExpect(Lost::class) instead.
+ private fun TestableNetworkCallback.eventuallyExpectLost(n: Network? = null) =
+ eventuallyExpect(Lost::class, TIMEOUT_MS) { n?.equals(it.network) ?: true }
+
+ private fun TestableNetworkCallback.assertNotLost(n: Network? = null) =
+ assertNoCallbackThat() { it is Lost && (n?.equals(it.network) ?: true) }
+
@Test
fun testCallbacks() {
- val executor = HandlerExecutor(Handler(Looper.getMainLooper()))
-
// If an interface exists when the callback is registered, it is reported on registration.
val iface = createInterface()
val listener1 = EthernetStateListener()
- addInterfaceStateListener(executor, listener1)
+ addInterfaceStateListener(listener1)
validateListenerOnRegistration(listener1)
// If an interface appears, existing callbacks see it.
@@ -221,18 +281,18 @@
// Register a new listener, it should see state of all existing interfaces immediately.
val listener2 = EthernetStateListener()
- addInterfaceStateListener(executor, listener2)
+ addInterfaceStateListener(listener2)
validateListenerOnRegistration(listener2)
// Removing interfaces first sends link down, then STATE_ABSENT/ROLE_NONE.
removeInterface(iface)
- for (listener in addedListeners) {
+ for (listener in listOf(listener1, listener2)) {
listener.expectCallback(iface, STATE_LINK_DOWN, ROLE_CLIENT)
listener.expectCallback(iface, STATE_ABSENT, ROLE_NONE)
}
removeInterface(iface2)
- for (listener in addedListeners) {
+ for (listener in listOf(listener1, listener2)) {
listener.expectCallback(iface2, STATE_LINK_DOWN, ROLE_CLIENT)
listener.expectCallback(iface2, STATE_ABSENT, ROLE_NONE)
listener.assertNoCallback()
@@ -282,4 +342,105 @@
removeInterface(iface2)
}
+
+ @Test
+ fun testNetworkRequest_withSingleExistingInterface() {
+ setIncludeTestInterfaces(true)
+ createInterface()
+
+ // install a listener which will later be used to verify the Lost callback
+ val listenerCb = TestableNetworkCallback()
+ cm.registerNetworkCallback(ETH_REQUEST, listenerCb)
+ networkRequests.add(listenerCb)
+
+ val cb = requestNetwork(ETH_REQUEST)
+ val network = cb.expectAvailable()
+
+ cb.assertNotLost()
+ releaseNetwork(cb)
+ listenerCb.eventuallyExpectLost(network)
+ }
+
+ @Test
+ fun testNetworkRequest_beforeSingleInterfaceIsUp() {
+ setIncludeTestInterfaces(true)
+
+ val cb = requestNetwork(ETH_REQUEST)
+
+ // bring up interface after network has been requested
+ val iface = createInterface()
+ val network = cb.expectAvailable()
+
+ // remove interface before network request has been removed
+ cb.assertNotLost()
+ removeInterface(iface)
+ cb.eventuallyExpectLost()
+
+ releaseNetwork(cb)
+ }
+
+ @Test
+ fun testNetworkRequest_withMultipleInterfaces() {
+ setIncludeTestInterfaces(true)
+
+ val iface1 = createInterface()
+ val iface2 = createInterface()
+
+ val cb = requestNetwork(ETH_REQUEST.createCopyWithEthernetSpecifier(iface2.interfaceName))
+
+ val network = cb.expectAvailable()
+ cb.expectCapabilitiesThat(network) {
+ it.networkSpecifier == EthernetNetworkSpecifier(iface2.interfaceName)
+ }
+
+ removeInterface(iface1)
+ cb.assertNotLost()
+ removeInterface(iface2)
+ cb.eventuallyExpectLost()
+
+ releaseNetwork(cb)
+ }
+
+ @Test
+ fun testNetworkRequest_withInterfaceBeingReplaced() {
+ setIncludeTestInterfaces(true)
+ val iface1 = createInterface()
+
+ val cb = requestNetwork(ETH_REQUEST)
+ val network = cb.expectAvailable()
+
+ // create another network and verify the request sticks to the current network
+ val iface2 = createInterface()
+ cb.assertNotLost()
+
+ // remove iface1 and verify the request brings up iface2
+ removeInterface(iface1)
+ cb.eventuallyExpectLost(network)
+ val network2 = cb.expectAvailable()
+
+ releaseNetwork(cb)
+ }
+
+ @Test
+ fun testNetworkRequest_withMultipleInterfacesAndRequests() {
+ setIncludeTestInterfaces(true)
+ val iface1 = createInterface()
+ val iface2 = createInterface()
+
+ val cb1 = requestNetwork(ETH_REQUEST.createCopyWithEthernetSpecifier(iface1.interfaceName))
+ val cb2 = requestNetwork(ETH_REQUEST.createCopyWithEthernetSpecifier(iface2.interfaceName))
+ val cb3 = requestNetwork(ETH_REQUEST)
+
+ cb1.expectAvailable()
+ cb2.expectAvailable()
+ cb3.expectAvailable()
+
+ cb1.assertNotLost()
+ cb2.assertNotLost()
+ cb3.assertNotLost()
+
+ releaseNetwork(cb1)
+ releaseNetwork(cb2)
+ releaseNetwork(cb3)
+ }
}
diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
index 088d202..33a0a83 100644
--- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
+++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt
@@ -52,9 +52,7 @@
import androidx.test.runner.AndroidJUnit4
import com.android.net.module.util.ArrayTrackRecord
import com.android.net.module.util.TrackRecord
-import com.android.networkstack.apishim.ConstantsShim
import com.android.networkstack.apishim.NsdShimImpl
-import com.android.testutils.SC_V2
import com.android.testutils.TestableNetworkAgent
import com.android.testutils.TestableNetworkCallback
import com.android.testutils.runAsShell
@@ -249,9 +247,11 @@
fun setUp() {
handlerThread.start()
- runAsShell(MANAGE_TEST_NETWORKS) {
- testNetwork1 = createTestNetwork()
- testNetwork2 = createTestNetwork()
+ if (TestUtils.shouldTestTApis()) {
+ runAsShell(MANAGE_TEST_NETWORKS) {
+ testNetwork1 = createTestNetwork()
+ testNetwork2 = createTestNetwork()
+ }
}
}
@@ -290,9 +290,11 @@
@After
fun tearDown() {
- runAsShell(MANAGE_TEST_NETWORKS) {
- testNetwork1.close(cm)
- testNetwork2.close(cm)
+ if (TestUtils.shouldTestTApis()) {
+ runAsShell(MANAGE_TEST_NETWORKS) {
+ testNetwork1.close(cm)
+ testNetwork2.close(cm)
+ }
}
handlerThread.quitSafely()
}
@@ -419,7 +421,7 @@
@Test
fun testNsdManager_DiscoverOnNetwork() {
// This test requires shims supporting T+ APIs (discovering on specific network)
- assumeTrue(ConstantsShim.VERSION > SC_V2)
+ assumeTrue(TestUtils.shouldTestTApis())
val si = NsdServiceInfo()
si.serviceType = SERVICE_TYPE
@@ -453,7 +455,7 @@
@Test
fun testNsdManager_DiscoverWithNetworkRequest() {
// This test requires shims supporting T+ APIs (discovering on network request)
- assumeTrue(ConstantsShim.VERSION > SC_V2)
+ assumeTrue(TestUtils.shouldTestTApis())
val si = NsdServiceInfo()
si.serviceType = SERVICE_TYPE
@@ -518,7 +520,7 @@
@Test
fun testNsdManager_ResolveOnNetwork() {
// This test requires shims supporting T+ APIs (NsdServiceInfo.network)
- assumeTrue(ConstantsShim.VERSION > SC_V2)
+ assumeTrue(TestUtils.shouldTestTApis())
val si = NsdServiceInfo()
si.serviceType = SERVICE_TYPE
@@ -562,7 +564,7 @@
@Test
fun testNsdManager_RegisterOnNetwork() {
// This test requires shims supporting T+ APIs (NsdServiceInfo.network)
- assumeTrue(ConstantsShim.VERSION > SC_V2)
+ assumeTrue(TestUtils.shouldTestTApis())
val si = NsdServiceInfo()
si.serviceType = SERVICE_TYPE
diff --git a/tests/integration/Android.bp b/tests/integration/Android.bp
index e3d80a0..97c1265 100644
--- a/tests/integration/Android.bp
+++ b/tests/integration/Android.bp
@@ -21,7 +21,7 @@
android_test {
name: "FrameworksNetIntegrationTests",
- defaults: ["framework-connectivity-internal-test-defaults"],
+ defaults: ["framework-connectivity-test-defaults"],
platform_apis: true,
certificate: "platform",
srcs: [
@@ -71,12 +71,8 @@
"net-tests-utils",
],
libs: [
- "service-connectivity-pre-jarjar",
+ "service-connectivity",
"services.core",
"services.net",
],
- visibility: [
- "//packages/modules/Connectivity/tests/integration",
- "//packages/modules/Connectivity/tests/unit",
- ],
}
diff --git a/tests/mts/bpf_existence_test.cpp b/tests/mts/bpf_existence_test.cpp
index 7efc2b1..db39e6f 100644
--- a/tests/mts/bpf_existence_test.cpp
+++ b/tests/mts/bpf_existence_test.cpp
@@ -107,14 +107,10 @@
NETD "map_netd_uid_counterset_map",
NETD "map_netd_uid_owner_map",
NETD "map_netd_uid_permission_map",
- SHARED "prog_block_bind4_block_port",
- SHARED "prog_block_bind6_block_port",
SHARED "prog_clatd_schedcls_egress4_clat_ether",
SHARED "prog_clatd_schedcls_egress4_clat_rawip",
SHARED "prog_clatd_schedcls_ingress6_clat_ether",
SHARED "prog_clatd_schedcls_ingress6_clat_rawip",
- SHARED "prog_dscp_policy_schedcls_set_dscp_ether",
- SHARED "prog_dscp_policy_schedcls_set_dscp_raw_ip",
NETD "prog_netd_cgroupskb_egress_stats",
NETD "prog_netd_cgroupskb_ingress_stats",
NETD "prog_netd_cgroupsock_inet_create",
@@ -125,6 +121,13 @@
NETD "prog_netd_skfilter_ingress_xtbpf",
};
+static const set<string> INTRODUCED_T_5_4 = {
+ SHARED "prog_block_bind4_block_port",
+ SHARED "prog_block_bind6_block_port",
+ SHARED "prog_dscp_policy_schedcls_set_dscp_ether",
+ SHARED "prog_dscp_policy_schedcls_set_dscp_raw_ip",
+};
+
static const set<string> REMOVED_T = {
};
@@ -164,6 +167,7 @@
if (IsAtLeastT()) {
addAll(expected, INTRODUCED_T);
+ if (android::bpf::isAtLeastKernelVersion(5, 4, 0)) addAll(expected, INTRODUCED_T_5_4);
removeAll(expected, REMOVED_T);
addAll(unexpected, REMOVED_T);
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 5a7208c..5b926de 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -108,7 +108,7 @@
name: "FrameworksNetTestsDefaults",
min_sdk_version: "30",
defaults: [
- "framework-connectivity-internal-test-defaults",
+ "framework-connectivity-test-defaults",
],
srcs: [
"java/**/*.java",
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index f6ccd8a..ef97168 100644
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -9505,7 +9505,7 @@
b2.expectBroadcast();
}
- @Test
+ @Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
public void testLockdownSetFirewallUidRule() throws Exception {
// For ConnectivityService#setAlwaysOnVpnPackage.
mServiceContext.setPermission(
@@ -10428,7 +10428,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));
@@ -10438,29 +10438,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"));
@@ -10470,26 +10475,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
diff --git a/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
index 45f3d3c..061dc87 100644
--- a/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/unit/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -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/ethernet/EthernetConfigStoreTest.java b/tests/unit/java/com/android/server/ethernet/EthernetConfigStoreTest.java
new file mode 100644
index 0000000..a9f80ea
--- /dev/null
+++ b/tests/unit/java/com/android/server/ethernet/EthernetConfigStoreTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.server.ethernet;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.net.InetAddresses;
+import android.net.IpConfiguration;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
+import android.net.LinkAddress;
+import android.net.ProxyInfo;
+import android.net.StaticIpConfiguration;
+import android.util.ArrayMap;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class EthernetConfigStoreTest {
+ private static final LinkAddress LINKADDR = new LinkAddress("192.168.1.100/25");
+ private static final InetAddress GATEWAY = InetAddresses.parseNumericAddress("192.168.1.1");
+ private static final InetAddress DNS1 = InetAddresses.parseNumericAddress("8.8.8.8");
+ private static final InetAddress DNS2 = InetAddresses.parseNumericAddress("8.8.4.4");
+ private static final StaticIpConfiguration STATIC_IP_CONFIG =
+ new StaticIpConfiguration.Builder()
+ .setIpAddress(LINKADDR)
+ .setGateway(GATEWAY)
+ .setDnsServers(new ArrayList<InetAddress>(
+ List.of(DNS1, DNS2)))
+ .build();
+ private static final ProxyInfo PROXY_INFO = ProxyInfo.buildDirectProxy("test", 8888);
+ private static final IpConfiguration APEX_IP_CONFIG =
+ new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null);
+ private static final IpConfiguration LEGACY_IP_CONFIG =
+ new IpConfiguration(IpAssignment.STATIC, ProxySettings.STATIC, STATIC_IP_CONFIG,
+ PROXY_INFO);
+
+ private EthernetConfigStore mEthernetConfigStore;
+ private File mApexTestDir;
+ private File mLegacyTestDir;
+ private File mApexConfigFile;
+ private File mLegacyConfigFile;
+
+ private void createTestDir() {
+ final Context context = InstrumentationRegistry.getContext();
+ final File baseDir = context.getFilesDir();
+ mApexTestDir = new File(baseDir.getPath() + "/apex");
+ mApexTestDir.mkdirs();
+
+ mLegacyTestDir = new File(baseDir.getPath() + "/legacy");
+ mLegacyTestDir.mkdirs();
+ }
+
+ @Before
+ public void setUp() {
+ createTestDir();
+ mEthernetConfigStore = new EthernetConfigStore();
+ }
+
+ @After
+ public void tearDown() {
+ mApexTestDir.delete();
+ mLegacyTestDir.delete();
+ }
+
+ private void assertConfigFileExist(final String filepath) {
+ assertTrue(new File(filepath).exists());
+ }
+
+ /** Wait for the delayed write operation completes. */
+ private void waitForMs(long ms) {
+ try {
+ Thread.sleep(ms);
+ } catch (final InterruptedException e) {
+ fail("Thread was interrupted");
+ }
+ }
+
+ @Test
+ public void testWriteIpConfigToApexFilePathAndRead() throws Exception {
+ // Write the config file to the apex file path, pretend the config file exits and
+ // check if IP config should be read from apex file path.
+ mApexConfigFile = new File(mApexTestDir.getPath(), "test.txt");
+ mEthernetConfigStore.write("eth0", APEX_IP_CONFIG, mApexConfigFile.getPath());
+ waitForMs(50);
+
+ mEthernetConfigStore.read(mApexTestDir.getPath(), mLegacyTestDir.getPath(), "/test.txt");
+ final ArrayMap<String, IpConfiguration> ipConfigurations =
+ mEthernetConfigStore.getIpConfigurations();
+ assertEquals(APEX_IP_CONFIG, ipConfigurations.get("eth0"));
+
+ mApexConfigFile.delete();
+ }
+
+ @Test
+ public void testWriteIpConfigToLegacyFilePathAndRead() throws Exception {
+ // Write the config file to the legacy file path, pretend the config file exits and
+ // check if IP config should be read from legacy file path.
+ mLegacyConfigFile = new File(mLegacyTestDir, "test.txt");
+ mEthernetConfigStore.write("0", LEGACY_IP_CONFIG, mLegacyConfigFile.getPath());
+ waitForMs(50);
+
+ mEthernetConfigStore.read(mApexTestDir.getPath(), mLegacyTestDir.getPath(), "/test.txt");
+ final ArrayMap<String, IpConfiguration> ipConfigurations =
+ mEthernetConfigStore.getIpConfigurations();
+ assertEquals(LEGACY_IP_CONFIG, ipConfigurations.get("0"));
+
+ // Check the same config file in apex file path is created.
+ assertConfigFileExist(mApexTestDir.getPath() + "/test.txt");
+
+ final File apexConfigFile = new File(mApexTestDir.getPath() + "/test.txt");
+ apexConfigFile.delete();
+ mLegacyConfigFile.delete();
+ }
+}
diff --git a/tests/unit/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/unit/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
index dfb4fcc..568d40f 100644
--- a/tests/unit/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
+++ b/tests/unit/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java
@@ -32,7 +32,6 @@
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -51,6 +50,7 @@
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkProvider;
+import android.net.NetworkProvider.NetworkOfferCallback;
import android.net.NetworkRequest;
import android.net.StaticIpConfiguration;
import android.net.ip.IpClientCallbacks;
@@ -99,6 +99,7 @@
@Mock private EthernetNetworkAgent mNetworkAgent;
@Mock private InterfaceParams mInterfaceParams;
@Mock private Network mMockNetwork;
+ @Mock private NetworkProvider mNetworkProvider;
@Before
public void setUp() throws Exception {
@@ -112,7 +113,7 @@
private void initEthernetNetworkFactory() {
mLooper = new TestLooper();
mHandler = new Handler(mLooper.getLooper());
- mNetFactory = new EthernetNetworkFactory(mHandler, mContext, mDeps);
+ mNetFactory = new EthernetNetworkFactory(mHandler, mContext, mNetworkProvider, mDeps);
}
private void setupNetworkAgentMock() {
@@ -239,9 +240,16 @@
mNetFactory.addInterface(iface, HW_ADDR, ipConfig,
createInterfaceCapsBuilder(transportType).build());
assertTrue(mNetFactory.updateInterfaceLinkState(iface, true, NULL_LISTENER));
+
+ ArgumentCaptor<NetworkOfferCallback> captor = ArgumentCaptor.forClass(
+ NetworkOfferCallback.class);
+ verify(mNetworkProvider).registerNetworkOffer(any(), any(), any(), captor.capture());
+ captor.getValue().onNetworkNeeded(createDefaultRequest());
+
verifyStart(ipConfig);
clearInvocations(mDeps);
clearInvocations(mIpClient);
+ clearInvocations(mNetworkProvider);
}
// creates a provisioned interface
@@ -281,29 +289,15 @@
// To create an unprovisioned interface, provision and then "stop" it, i.e. stop its
// NetworkAgent and IpClient. One way this can be done is by provisioning an interface and
// then calling onNetworkUnwanted.
- createAndVerifyProvisionedInterface(iface);
-
- mNetworkAgent.getCallbacks().onNetworkUnwanted();
- mLooper.dispatchAll();
- verifyStop();
+ mNetFactory.addInterface(iface, HW_ADDR, createDefaultIpConfig(),
+ createInterfaceCapsBuilder(NetworkCapabilities.TRANSPORT_ETHERNET).build());
+ assertTrue(mNetFactory.updateInterfaceLinkState(iface, true, NULL_LISTENER));
clearInvocations(mIpClient);
clearInvocations(mNetworkAgent);
}
@Test
- public void testAcceptRequest() throws Exception {
- initEthernetNetworkFactory();
- createInterfaceUndergoingProvisioning(TEST_IFACE);
- assertTrue(mNetFactory.acceptRequest(createDefaultRequest()));
-
- NetworkRequest wifiRequest = createDefaultRequestBuilder()
- .removeTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build();
- assertFalse(mNetFactory.acceptRequest(wifiRequest));
- }
-
- @Test
public void testUpdateInterfaceLinkStateForActiveProvisioningInterface() throws Exception {
initEthernetNetworkFactory();
createInterfaceUndergoingProvisioning(TEST_IFACE);
@@ -378,36 +372,6 @@
}
@Test
- public void testNeedNetworkForOnProvisionedInterface() throws Exception {
- initEthernetNetworkFactory();
- createAndVerifyProvisionedInterface(TEST_IFACE);
- mNetFactory.needNetworkFor(createDefaultRequest());
- verify(mIpClient, never()).startProvisioning(any());
- }
-
- @Test
- public void testNeedNetworkForOnUnprovisionedInterface() throws Exception {
- initEthernetNetworkFactory();
- createUnprovisionedInterface(TEST_IFACE);
- mNetFactory.needNetworkFor(createDefaultRequest());
- verify(mIpClient).startProvisioning(any());
-
- triggerOnProvisioningSuccess();
- verifyNetworkAgentRegistersAndConnects();
- }
-
- @Test
- public void testNeedNetworkForOnInterfaceUndergoingProvisioning() throws Exception {
- initEthernetNetworkFactory();
- createInterfaceUndergoingProvisioning(TEST_IFACE);
- mNetFactory.needNetworkFor(createDefaultRequest());
- verify(mIpClient, never()).startProvisioning(any());
-
- triggerOnProvisioningSuccess();
- verifyNetworkAgentRegistersAndConnects();
- }
-
- @Test
public void testProvisioningLoss() throws Exception {
initEthernetNetworkFactory();
when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams);
@@ -441,31 +405,6 @@
}
@Test
- public void testIpClientIsNotStartedWhenLinkIsDown() throws Exception {
- initEthernetNetworkFactory();
- createUnprovisionedInterface(TEST_IFACE);
- mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER);
-
- mNetFactory.needNetworkFor(createDefaultRequest());
-
- verify(mDeps, never()).makeIpClient(any(), any(), any());
-
- // BUG(b/191854824): requesting a network with a specifier (Android Auto use case) should
- // not start an IpClient when the link is down, but fixing this may make matters worse by
- // tiggering b/197548738.
- NetworkRequest specificNetRequest = new NetworkRequest.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
- .setNetworkSpecifier(new EthernetNetworkSpecifier(TEST_IFACE))
- .build();
- mNetFactory.needNetworkFor(specificNetRequest);
- mNetFactory.releaseNetworkFor(specificNetRequest);
-
- mNetFactory.updateInterfaceLinkState(TEST_IFACE, true, NULL_LISTENER);
- // TODO: change to once when b/191854824 is fixed.
- verify(mDeps, times(2)).makeIpClient(any(), eq(TEST_IFACE), any());
- }
-
- @Test
public void testLinkPropertiesChanged() throws Exception {
initEthernetNetworkFactory();
createAndVerifyProvisionedInterface(TEST_IFACE);
diff --git a/tests/unit/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/unit/java/com/android/server/ethernet/EthernetServiceImplTest.java
index dd1f1ed..aff824c 100644
--- a/tests/unit/java/com/android/server/ethernet/EthernetServiceImplTest.java
+++ b/tests/unit/java/com/android/server/ethernet/EthernetServiceImplTest.java
@@ -20,7 +20,6 @@
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;
@@ -35,8 +34,8 @@
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.Handler;
@@ -111,18 +110,18 @@
}
@Test
- public void testConnectNetworkRejectsWhenEthNotStarted() {
+ public void testEnableInterfaceRejectsWhenEthNotStarted() {
mEthernetServiceImpl.mStarted.set(false);
assertThrows(IllegalStateException.class, () -> {
- mEthernetServiceImpl.connectNetwork("" /* iface */, null /* listener */);
+ mEthernetServiceImpl.enableInterface("" /* iface */, null /* listener */);
});
}
@Test
- public void testDisconnectNetworkRejectsWhenEthNotStarted() {
+ public void testDisableInterfaceRejectsWhenEthNotStarted() {
mEthernetServiceImpl.mStarted.set(false);
assertThrows(IllegalStateException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork("" /* iface */, null /* listener */);
+ mEthernetServiceImpl.disableInterface("" /* iface */, null /* listener */);
});
}
@@ -134,16 +133,16 @@
}
@Test
- public void testConnectNetworkRejectsNullIface() {
+ public void testEnableInterfaceRejectsNullIface() {
assertThrows(NullPointerException.class, () -> {
- mEthernetServiceImpl.connectNetwork(null /* iface */, NULL_LISTENER);
+ mEthernetServiceImpl.enableInterface(null /* iface */, NULL_LISTENER);
});
}
@Test
- public void testDisconnectNetworkRejectsNullIface() {
+ public void testDisableInterfaceRejectsNullIface() {
assertThrows(NullPointerException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork(null /* iface */, NULL_LISTENER);
+ mEthernetServiceImpl.disableInterface(null /* iface */, NULL_LISTENER);
});
}
@@ -165,22 +164,6 @@
eq(UPDATE_REQUEST_WITHOUT_CAPABILITIES.getNetworkCapabilities()), isNull());
}
- @Test
- public void testConnectNetworkRejectsWithoutAutomotiveFeature() {
- toggleAutomotiveFeature(false);
- assertThrows(UnsupportedOperationException.class, () -> {
- mEthernetServiceImpl.connectNetwork("" /* iface */, NULL_LISTENER);
- });
- }
-
- @Test
- public void testDisconnectNetworkRejectsWithoutAutomotiveFeature() {
- toggleAutomotiveFeature(false);
- assertThrows(UnsupportedOperationException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork("" /* iface */, NULL_LISTENER);
- });
- }
-
private void denyManageEthPermission() {
doThrow(new SecurityException("")).when(mContext)
.enforceCallingOrSelfPermission(
@@ -202,18 +185,18 @@
}
@Test
- public void testConnectNetworkRejectsWithoutManageEthPermission() {
+ public void testEnableInterfaceRejectsWithoutManageEthPermission() {
denyManageEthPermission();
assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER);
+ mEthernetServiceImpl.enableInterface(TEST_IFACE, NULL_LISTENER);
});
}
@Test
- public void testDisconnectNetworkRejectsWithoutManageEthPermission() {
+ public void testDisableInterfaceRejectsWithoutManageEthPermission() {
denyManageEthPermission();
assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER);
+ mEthernetServiceImpl.disableInterface(TEST_IFACE, NULL_LISTENER);
});
}
@@ -231,20 +214,20 @@
}
@Test
- public void testConnectNetworkRejectsTestRequestWithoutTestPermission() {
+ public void testEnableInterfaceRejectsTestRequestWithoutTestPermission() {
enableTestInterface();
denyManageTestNetworksPermission();
assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER);
+ mEthernetServiceImpl.enableInterface(TEST_IFACE, NULL_LISTENER);
});
}
@Test
- public void testDisconnectNetworkRejectsTestRequestWithoutTestPermission() {
+ public void testDisableInterfaceRejectsTestRequestWithoutTestPermission() {
enableTestInterface();
denyManageTestNetworksPermission();
assertThrows(SecurityException.class, () -> {
- mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER);
+ mEthernetServiceImpl.disableInterface(TEST_IFACE, NULL_LISTENER);
});
}
@@ -258,15 +241,15 @@
}
@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));
}
@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));
}
@Test
@@ -324,23 +307,23 @@
}
@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));
}
@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) {
diff --git a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
index b1831c4..ca988b6 100644
--- a/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
+++ b/tests/unit/java/com/android/server/ethernet/EthernetTrackerTest.java
@@ -29,22 +29,23 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
-import android.content.res.Resources;
import android.net.EthernetManager;
-import android.net.InetAddresses;
-import android.net.INetworkInterfaceOutcomeReceiver;
import android.net.IEthernetServiceListener;
import android.net.INetd;
+import android.net.INetworkInterfaceOutcomeReceiver;
+import android.net.InetAddresses;
+import android.net.InterfaceConfigurationParcel;
import android.net.IpConfiguration;
import android.net.IpConfiguration.IpAssignment;
import android.net.IpConfiguration.ProxySettings;
-import android.net.InterfaceConfigurationParcel;
import android.net.LinkAddress;
import android.net.NetworkCapabilities;
import android.net.StaticIpConfiguration;
@@ -54,13 +55,13 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.connectivity.resources.R;
import com.android.testutils.HandlerUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -351,8 +352,8 @@
}
@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 */),
@@ -360,8 +361,8 @@
}
@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 */),
@@ -410,18 +411,24 @@
IpConfiguration configuration) { }
}
+ private InterfaceConfigurationParcel createMockedIfaceParcel(final String ifname,
+ final String hwAddr) {
+ final InterfaceConfigurationParcel ifaceParcel = new InterfaceConfigurationParcel();
+ ifaceParcel.ifName = ifname;
+ ifaceParcel.hwAddr = hwAddr;
+ ifaceParcel.flags = new String[] {INetd.IF_STATE_UP};
+ return ifaceParcel;
+ }
+
@Test
public void testListenEthernetStateChange() throws Exception {
- final String testIface = "testtap123";
- final String testHwAddr = "11:22:33:44:55:66";
- final InterfaceConfigurationParcel ifaceParcel = new InterfaceConfigurationParcel();
- ifaceParcel.ifName = testIface;
- ifaceParcel.hwAddr = testHwAddr;
- ifaceParcel.flags = new String[] {INetd.IF_STATE_UP};
-
tracker.setIncludeTestInterfaces(true);
waitForIdle();
+ final String testIface = "testtap123";
+ final String testHwAddr = "11:22:33:44:55:66";
+ final InterfaceConfigurationParcel ifaceParcel = createMockedIfaceParcel(testIface,
+ testHwAddr);
when(mNetd.interfaceGetList()).thenReturn(new String[] {testIface});
when(mNetd.interfaceGetCfg(eq(testIface))).thenReturn(ifaceParcel);
doReturn(new String[] {testIface}).when(mFactory).getAvailableInterfaces(anyBoolean());
@@ -453,4 +460,43 @@
verify(listener).onInterfaceStateChanged(eq(testIface), eq(EthernetManager.STATE_LINK_UP),
anyInt(), any());
}
+
+ @Test
+ public void testListenEthernetStateChange_unsolicitedEventListener() throws Exception {
+ when(mNetd.interfaceGetList()).thenReturn(new String[] {});
+ doReturn(new String[] {}).when(mFactory).getAvailableInterfaces(anyBoolean());
+
+ tracker.setIncludeTestInterfaces(true);
+ tracker.start();
+
+ final ArgumentCaptor<EthernetTracker.InterfaceObserver> captor =
+ ArgumentCaptor.forClass(EthernetTracker.InterfaceObserver.class);
+ verify(mNetd, timeout(TIMEOUT_MS)).registerUnsolicitedEventListener(captor.capture());
+ final EthernetTracker.InterfaceObserver observer = captor.getValue();
+
+ tracker.setEthernetEnabled(false);
+ waitForIdle();
+ reset(mFactory);
+ reset(mNetd);
+
+ final String testIface = "testtap1";
+ observer.onInterfaceAdded(testIface);
+ verify(mFactory, never()).addInterface(eq(testIface), anyString(), any(), any());
+ observer.onInterfaceRemoved(testIface);
+ verify(mFactory, never()).removeInterface(eq(testIface));
+
+ final String testHwAddr = "11:22:33:44:55:66";
+ final InterfaceConfigurationParcel testIfaceParce =
+ createMockedIfaceParcel(testIface, testHwAddr);
+ when(mNetd.interfaceGetList()).thenReturn(new String[] {testIface});
+ when(mNetd.interfaceGetCfg(eq(testIface))).thenReturn(testIfaceParce);
+ doReturn(new String[] {testIface}).when(mFactory).getAvailableInterfaces(anyBoolean());
+ tracker.setEthernetEnabled(true);
+ waitForIdle();
+ reset(mFactory);
+
+ final String testIface2 = "testtap2";
+ observer.onInterfaceRemoved(testIface2);
+ verify(mFactory, timeout(TIMEOUT_MS)).removeInterface(eq(testIface2));
+ }
}
diff --git a/tools/Android.bp b/tools/Android.bp
deleted file mode 100644
index 27f9b75..0000000
--- a/tools/Android.bp
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// 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 {
- // See: http://go/android-license-faq
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-// Build tool used to generate jarjar rules for all classes in a jar, except those that are
-// API, UnsupportedAppUsage or otherwise excluded.
-python_binary_host {
- name: "jarjar-rules-generator",
- srcs: [
- "gen_jarjar.py",
- ],
- main: "gen_jarjar.py",
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- },
- },
- visibility: ["//packages/modules/Connectivity:__subpackages__"],
-}
-
-genrule_defaults {
- name: "jarjar-rules-combine-defaults",
- // Concat files with a line break in the middle
- cmd: "for src in $(in); do cat $${src}; echo; done > $(out)",
- defaults_visibility: ["//packages/modules/Connectivity:__subpackages__"],
-}
diff --git a/tools/gen_jarjar.py b/tools/gen_jarjar.py
deleted file mode 100755
index 285bf6f..0000000
--- a/tools/gen_jarjar.py
+++ /dev/null
@@ -1,168 +0,0 @@
-#
-# 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.
-
-""" This script generates jarjar rule files to add a jarjar prefix to all classes, except those
-that are API, unsupported API or otherwise excluded."""
-
-import argparse
-import io
-import re
-import subprocess
-from xml import sax
-from xml.sax.handler import ContentHandler
-from zipfile import ZipFile
-
-
-def parse_arguments(argv):
- parser = argparse.ArgumentParser()
- parser.add_argument(
- '--jars', nargs='+',
- help='Path to pre-jarjar JAR. Can be followed by multiple space-separated paths.')
- parser.add_argument(
- '--prefix', required=True,
- help='Package prefix to use for jarjared classes, '
- 'for example "com.android.connectivity" (does not end with a dot).')
- parser.add_argument(
- '--output', required=True, help='Path to output jarjar rules file.')
- parser.add_argument(
- '--apistubs', nargs='*', default=[],
- help='Path to API stubs jar. Classes that are API will not be jarjared. Can be followed by '
- 'multiple space-separated paths.')
- parser.add_argument(
- '--unsupportedapi', nargs='*', default=[],
- help='Path to UnsupportedAppUsage hidden API .txt lists. '
- 'Classes that have UnsupportedAppUsage API will not be jarjared. Can be followed by '
- 'multiple space-separated paths.')
- parser.add_argument(
- '--excludes', nargs='*', default=[],
- help='Path to files listing classes that should not be jarjared. Can be followed by '
- 'multiple space-separated paths. '
- 'Each file should contain one full-match regex per line. Empty lines or lines '
- 'starting with "#" are ignored.')
- parser.add_argument(
- '--dexdump', default='dexdump', help='Path to dexdump binary.')
- return parser.parse_args(argv)
-
-
-class DumpHandler(ContentHandler):
- def __init__(self):
- super().__init__()
- self._current_package = None
- self.classes = []
-
- def startElement(self, name, attrs):
- if name == 'package':
- attr_name = attrs.getValue('name')
- assert attr_name != '', '<package> element missing name'
- assert self._current_package is None, f'Found nested package tags for {attr_name}'
- self._current_package = attr_name
- elif name == 'class':
- attr_name = attrs.getValue('name')
- assert attr_name != '', '<class> element missing name'
- self.classes.append(self._current_package + '.' + attr_name)
-
- def endElement(self, name):
- if name == 'package':
- self._current_package = None
-
-
-def _list_toplevel_dex_classes(jar, dexdump):
- """List all classes in a dexed .jar file that are not inner classes."""
- # Empty jars do net get a classes.dex: return an empty set for them
- with ZipFile(jar, 'r') as zip_file:
- if not zip_file.namelist():
- return set()
- cmd = [dexdump, '-l', 'xml', '-e', jar]
- dump = subprocess.run(cmd, check=True, text=True, stdout=subprocess.PIPE)
- handler = DumpHandler()
- xml_parser = sax.make_parser()
- xml_parser.setContentHandler(handler)
- xml_parser.parse(io.StringIO(dump.stdout))
- return set([_get_toplevel_class(c) for c in handler.classes])
-
-
-def _list_jar_classes(jar):
- with ZipFile(jar, 'r') as zip:
- files = zip.namelist()
- assert 'classes.dex' not in files, f'Jar file {jar} is dexed, ' \
- 'expected an intermediate zip of .class files'
- class_len = len('.class')
- return [f.replace('/', '.')[:-class_len] for f in files
- if f.endswith('.class') and not f.endswith('/package-info.class')]
-
-
-def _list_hiddenapi_classes(txt_file):
- out = set()
- with open(txt_file, 'r') as f:
- for line in f:
- if not line.strip():
- continue
- assert line.startswith('L') and ';' in line, f'Class name not recognized: {line}'
- clazz = line.replace('/', '.').split(';')[0][1:]
- out.add(_get_toplevel_class(clazz))
- return out
-
-
-def _get_toplevel_class(clazz):
- """Return the name of the toplevel (not an inner class) enclosing class of the given class."""
- if '$' not in clazz:
- return clazz
- return clazz.split('$')[0]
-
-
-def _get_excludes(path):
- out = []
- with open(path, 'r') as f:
- for line in f:
- stripped = line.strip()
- if not stripped or stripped.startswith('#'):
- continue
- out.append(re.compile(stripped))
- return out
-
-
-def make_jarjar_rules(args):
- excluded_classes = set()
- for apistubs_file in args.apistubs:
- excluded_classes.update(_list_toplevel_dex_classes(apistubs_file, args.dexdump))
-
- for unsupportedapi_file in args.unsupportedapi:
- excluded_classes.update(_list_hiddenapi_classes(unsupportedapi_file))
-
- exclude_regexes = []
- for exclude_file in args.excludes:
- exclude_regexes.extend(_get_excludes(exclude_file))
-
- with open(args.output, 'w') as outfile:
- for jar in args.jars:
- jar_classes = _list_jar_classes(jar)
- jar_classes.sort()
- for clazz in jar_classes:
- if (_get_toplevel_class(clazz) not in excluded_classes and
- not any(r.fullmatch(clazz) for r in exclude_regexes)):
- outfile.write(f'rule {clazz} {args.prefix}.@0\n')
- # Also include jarjar rules for unit tests of the class, so the package matches
- outfile.write(f'rule {clazz}Test {args.prefix}.@0\n')
- outfile.write(f'rule {clazz}Test$* {args.prefix}.@0\n')
-
-
-def _main():
- # Pass in None to use argv
- args = parse_arguments(None)
- make_jarjar_rules(args)
-
-
-if __name__ == '__main__':
- _main()