diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp index 76c5d5c21b..bb40935ebe 100644 --- a/Tethering/apex/Android.bp +++ b/Tethering/apex/Android.bp @@ -105,6 +105,12 @@ android_app_certificate { 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/framework-t/Android.bp b/framework-t/Android.bp index 1e508a04bd..8c32ded49e 100644 --- a/framework-t/Android.bp +++ b/framework-t/Android.bp @@ -103,7 +103,7 @@ java_sdk_library { // 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: ":connectivity-jarjar-rules", + jarjar_rules: ":framework-connectivity-jarjar-rules", permitted_packages: [ "android.app.usage", "android.net", diff --git a/framework/Android.bp b/framework/Android.bp index d7de43920d..c8b64c711a 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -111,6 +111,7 @@ java_library { // 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__"] } @@ -119,7 +120,7 @@ java_sdk_library { name: "framework-connectivity", defaults: ["framework-connectivity-defaults"], installable: true, - jarjar_rules: ":connectivity-jarjar-rules", + jarjar_rules: ":framework-connectivity-jarjar-rules", permitted_packages: ["android.net"], impl_library_visibility: [ "//packages/modules/Connectivity/Tethering/apex", @@ -222,3 +223,35 @@ gensrcs { ], 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 new file mode 100644 index 0000000000..1311765535 --- /dev/null +++ b/framework/jarjar-excludes.txt @@ -0,0 +1,25 @@ +# 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 7478b3e73d..857ece5e6f 100644 --- a/framework/jni/android_net_NetworkUtils.cpp +++ b/framework/jni/android_net_NetworkUtils.cpp @@ -232,7 +232,8 @@ static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, j return NULL; } - jclass class_TcpRepairWindow = env->FindClass("android/net/TcpRepairWindow"); + jclass class_TcpRepairWindow = env->FindClass( + "android/net/connectivity/android/net/TcpRepairWindow"); jmethodID ctor = env->GetMethodID(class_TcpRepairWindow, "", "(IIIIII)V"); return env->NewObject(class_TcpRepairWindow, ctor, trw.snd_wl1, trw.snd_wnd, trw.max_window, @@ -253,7 +254,7 @@ static const JNINativeMethod gNetworkUtilMethods[] = { { "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/TcpRepairWindow;", (void*) android_net_utils_getTcpRepairWindow }, + { "getTcpRepairWindow", "(Ljava/io/FileDescriptor;)Landroid/net/connectivity/android/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 79009e8d62..e64d2ae246 100644 --- a/framework/src/android/net/DnsResolverServiceManager.java +++ b/framework/src/android/net/DnsResolverServiceManager.java @@ -29,7 +29,7 @@ public class DnsResolverServiceManager { private final IBinder mResolver; - DnsResolverServiceManager(IBinder resolver) { + public DnsResolverServiceManager(IBinder resolver) { mResolver = resolver; } diff --git a/framework/src/android/net/NattSocketKeepalive.java b/framework/src/android/net/NattSocketKeepalive.java index a15d165e65..56cc923801 100644 --- a/framework/src/android/net/NattSocketKeepalive.java +++ b/framework/src/android/net/NattSocketKeepalive.java @@ -33,7 +33,7 @@ public final class NattSocketKeepalive extends SocketKeepalive { @NonNull private final InetAddress mDestination; private final int mResourceId; - NattSocketKeepalive(@NonNull IConnectivityManager service, + public NattSocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network, @NonNull ParcelFileDescriptor pfd, int resourceId, @@ -48,7 +48,7 @@ public final class NattSocketKeepalive extends SocketKeepalive { } @Override - void startImpl(int intervalSec) { + protected void startImpl(int intervalSec) { mExecutor.execute(() -> { try { mService.startNattKeepaliveWithFd(mNetwork, mPfd, mResourceId, @@ -62,7 +62,7 @@ public final class NattSocketKeepalive extends SocketKeepalive { } @Override - void stopImpl() { + protected 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 de0fc243b4..cfceddd8b2 100644 --- a/framework/src/android/net/QosCallbackConnection.java +++ b/framework/src/android/net/QosCallbackConnection.java @@ -35,7 +35,7 @@ import java.util.concurrent.Executor; * * @hide */ -class QosCallbackConnection extends android.net.IQosCallback.Stub { +public class QosCallbackConnection extends android.net.IQosCallback.Stub { @NonNull private final ConnectivityManager mConnectivityManager; @Nullable private volatile QosCallback mCallback; @@ -56,7 +56,7 @@ class QosCallbackConnection extends android.net.IQosCallback.Stub { * {@link Executor} must run callback sequentially, otherwise the order of * callbacks cannot be guaranteed. */ - QosCallbackConnection(@NonNull final ConnectivityManager connectivityManager, + public QosCallbackConnection(@NonNull final ConnectivityManager connectivityManager, @NonNull final QosCallback callback, @NonNull final Executor executor) { mConnectivityManager = Objects.requireNonNull(connectivityManager, @@ -142,7 +142,7 @@ class QosCallbackConnection extends android.net.IQosCallback.Stub { * There are no synchronization guarantees on exactly when the callback will stop receiving * messages. */ - void stopReceivingMessages() { + public void stopReceivingMessages() { mCallback = null; } } diff --git a/framework/src/android/net/QosCallbackException.java b/framework/src/android/net/QosCallbackException.java index b80cff415e..9e5d98a519 100644 --- a/framework/src/android/net/QosCallbackException.java +++ b/framework/src/android/net/QosCallbackException.java @@ -85,7 +85,7 @@ public final class QosCallbackException extends Exception { * {@hide} */ @NonNull - static QosCallbackException createException(@ExceptionType final int type) { + public 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 b432644f70..01dc4bbabd 100644 --- a/framework/src/android/net/QosFilter.java +++ b/framework/src/android/net/QosFilter.java @@ -33,13 +33,15 @@ import java.net.InetAddress; @SystemApi public abstract class QosFilter { - /** - * 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() { + /** @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()); + } } /** diff --git a/framework/src/android/net/QosSocketInfo.java b/framework/src/android/net/QosSocketInfo.java index 49ac22b0a2..da9b356050 100644 --- a/framework/src/android/net/QosSocketInfo.java +++ b/framework/src/android/net/QosSocketInfo.java @@ -73,9 +73,10 @@ public final class QosSocketInfo implements Parcelable { * The parcel file descriptor wrapped around the socket's file descriptor. * * @return the parcel file descriptor of the socket + * @hide */ @NonNull - ParcelFileDescriptor getParcelFileDescriptor() { + public ParcelFileDescriptor getParcelFileDescriptor() { return mParcelFileDescriptor; } diff --git a/framework/src/android/net/SocketKeepalive.java b/framework/src/android/net/SocketKeepalive.java index f6cae72516..57cf5e3782 100644 --- a/framework/src/android/net/SocketKeepalive.java +++ b/framework/src/android/net/SocketKeepalive.java @@ -52,7 +52,8 @@ import java.util.concurrent.Executor; * request. If it does, it MUST support at least 3 concurrent keepalive slots. */ public abstract class SocketKeepalive implements AutoCloseable { - static final String TAG = "SocketKeepalive"; + /** @hide */ + protected static final String TAG = "SocketKeepalive"; /** * Success. It indicates there is no error. @@ -215,15 +216,22 @@ public abstract class SocketKeepalive implements AutoCloseable { } } - @NonNull final IConnectivityManager mService; - @NonNull final Network mNetwork; - @NonNull final ParcelFileDescriptor mPfd; - @NonNull final Executor mExecutor; - @NonNull final ISocketKeepaliveCallback mCallback; + /** @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; // TODO: remove slot since mCallback could be used to identify which keepalive to stop. - @Nullable Integer mSlot; + /** @hide */ + @Nullable protected Integer mSlot; - SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network, + /** @hide */ + public SocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network, @NonNull ParcelFileDescriptor pfd, @NonNull Executor executor, @NonNull Callback callback) { mService = service; @@ -303,7 +311,8 @@ public abstract class SocketKeepalive implements AutoCloseable { startImpl(intervalSec); } - abstract void startImpl(int intervalSec); + /** @hide */ + protected abstract void startImpl(int intervalSec); /** * Requests that keepalive be stopped. The application must wait for {@link Callback#onStopped} @@ -313,7 +322,8 @@ public abstract class SocketKeepalive implements AutoCloseable { stopImpl(); } - abstract void stopImpl(); + /** @hide */ + protected 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 d89814d49b..7131784f78 100644 --- a/framework/src/android/net/TcpSocketKeepalive.java +++ b/framework/src/android/net/TcpSocketKeepalive.java @@ -24,9 +24,9 @@ import android.util.Log; import java.util.concurrent.Executor; /** @hide */ -final class TcpSocketKeepalive extends SocketKeepalive { +public final class TcpSocketKeepalive extends SocketKeepalive { - TcpSocketKeepalive(@NonNull IConnectivityManager service, + public TcpSocketKeepalive(@NonNull IConnectivityManager service, @NonNull Network network, @NonNull ParcelFileDescriptor pfd, @NonNull Executor executor, @@ -50,7 +50,7 @@ final class TcpSocketKeepalive extends SocketKeepalive { * acknowledgement. */ @Override - void startImpl(int intervalSec) { + protected void startImpl(int intervalSec) { mExecutor.execute(() -> { try { mService.startTcpKeepalive(mNetwork, mPfd, intervalSec, mCallback); @@ -62,7 +62,7 @@ final class TcpSocketKeepalive extends SocketKeepalive { } @Override - void stopImpl() { + protected void stopImpl() { mExecutor.execute(() -> { try { if (mSlot != null) { diff --git a/service/Android.bp b/service/Android.bp index 91b9d1c42b..0393c795b3 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -224,9 +224,15 @@ java_library { lint: { strict_updatability_linting: true }, } -filegroup { +genrule { name: "connectivity-jarjar-rules", - srcs: ["jarjar-rules.txt"], + defaults: ["jarjar-rules-combine-defaults"], + srcs: [ + ":framework-connectivity-jarjar-rules", + ":service-connectivity-jarjar-gen", + ":service-nearby-jarjar-gen", + ], + out: ["connectivity-jarjar-rules.txt"], visibility: ["//packages/modules/Connectivity:__subpackages__"], } @@ -237,3 +243,45 @@ filegroup { 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 new file mode 100644 index 0000000000..b0d6763f78 --- /dev/null +++ b/service/jarjar-excludes.txt @@ -0,0 +1,9 @@ +# 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 deleted file mode 100644 index c7223fcf37..0000000000 --- a/service/jarjar-rules.txt +++ /dev/null @@ -1,123 +0,0 @@ -# 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/proguard.flags b/service/proguard.flags index 94397ab5f1..557ba59d98 100644 --- a/service/proguard.flags +++ b/service/proguard.flags @@ -2,8 +2,6 @@ # 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. @@ -15,4 +13,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.connectivity.com.google.protobuf.MessageLite { ; } +-keepclassmembers class * extends com.android.server.nearby.com.google.protobuf.MessageLite { ; } diff --git a/tests/common/Android.bp b/tests/common/Android.bp index 509e881a8b..efea0f91cc 100644 --- a/tests/common/Android.bp +++ b/tests/common/Android.bp @@ -23,7 +23,7 @@ package { java_library { name: "FrameworksNetCommonTests", - defaults: ["framework-connectivity-test-defaults"], + defaults: ["framework-connectivity-internal-test-defaults"], srcs: [ "java/**/*.java", "java/**/*.kt", @@ -49,6 +49,7 @@ java_library { // 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", @@ -56,8 +57,6 @@ genrule { ":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"], } @@ -84,7 +83,7 @@ android_test { target_sdk_version: "31", test_suites: ["general-tests", "mts-tethering"], defaults: [ - "framework-connectivity-test-defaults", + "framework-connectivity-internal-test-defaults", "FrameworksNetTests-jni-defaults", "libnetworkstackutilsjni_deps", ], @@ -140,6 +139,30 @@ java_defaults { ], } +// 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/integration/Android.bp b/tests/integration/Android.bp index 97c1265f6e..e3d80a06db 100644 --- a/tests/integration/Android.bp +++ b/tests/integration/Android.bp @@ -21,7 +21,7 @@ package { android_test { name: "FrameworksNetIntegrationTests", - defaults: ["framework-connectivity-test-defaults"], + defaults: ["framework-connectivity-internal-test-defaults"], platform_apis: true, certificate: "platform", srcs: [ @@ -71,8 +71,12 @@ java_library { "net-tests-utils", ], libs: [ - "service-connectivity", + "service-connectivity-pre-jarjar", "services.core", "services.net", ], + visibility: [ + "//packages/modules/Connectivity/tests/integration", + "//packages/modules/Connectivity/tests/unit", + ], } diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp index 5b926de36d..5a7208cf2b 100644 --- a/tests/unit/Android.bp +++ b/tests/unit/Android.bp @@ -108,7 +108,7 @@ java_defaults { name: "FrameworksNetTestsDefaults", min_sdk_version: "30", defaults: [ - "framework-connectivity-test-defaults", + "framework-connectivity-internal-test-defaults", ], srcs: [ "java/**/*.java", diff --git a/tools/Android.bp b/tools/Android.bp new file mode 100644 index 0000000000..27f9b759e1 --- /dev/null +++ b/tools/Android.bp @@ -0,0 +1,46 @@ +// +// 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 new file mode 100755 index 0000000000..6fdf3f4261 --- /dev/null +++ b/tools/gen_jarjar.py @@ -0,0 +1,166 @@ +# +# 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.') + 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 != '', ' 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 != '', ' 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()