Autogenerate connectivity jarjar rules
Jarjar rules are hard to keep in sync with code, and hard to maintain manually as the distinction between what should and should not be jarjared is not always clear. This results in unsafe binaries that are manually maintained, and developer frustration when something fails due to incorrect jarjar rules. Autogenerate jarjar rules at build time instead. This is achieved by introducing a jarjar-rules-generator python-based library, which scans pre-jarjar intermediate artifacts, and outputs jarjar rules for every class to put it in a package specific to the module. The only exceptions are: - Classes that are API (module-lib API is the largest API surface of the module) - Classes that have unsupportedappusage symbols - Classes that are excluded manually (for example, because they have hardcoded external references, like for ConnectivityServiceInitializer in SystemServer). This change causes all classes in framework-connectivity(-t) and service-connectivity to be jarjared into android.net.connectivity, but still avoids jarjaring classes in com.android.server as before, to keep it small. For many classes this differs from the original jarjar rule. Notes on implementation: - connectivity-jarjar-rules now has a subset framework-connectivity-jarjar-rules containing only the rules necessary for framework-connectivity. This is necessary because framework-connectivity cannot depend on rules generated based on service-connectivity, as there would be a dependency cycle (service-connectivity depends on framework-connectivity); Soong even crashes with a stack overflow. - framework-wifi.stubs.module_lib is added to framework-connectivity-pre-jarjar as it is necessary to build it (it is already in impl_only_libs in the defaults). It is unclear why framework-connectivity-pre-jarjar could build before that (possibly because it was only used as "lib" ?) - Fix package-private visibility; for example NattSocketKeepalive, TcpSocketKeepalive are not API so should be jarjared, but are used by ConnectivityManager which is not jarjared, so they are not in the same package after the change. Package-private members in the former 2 need to be public to be accessible. Changes in this commit are all that is needed, as demonstrated by followup commits that move the classes to a different package without further changes, and that enforce that no class in an API package gets jarjared. - framework-connectivity-internal-test-defaults is separated from framework-connectivity-test-defaults, for unit tests that need to access internal jarjared classes. Such tests need to use the jarjar rules themselves too, so this is only appropriate for connectivity internal unit tests. Test: atest ConnectivityCoverageTests CtsNetTestCases Bug: 217129444 Change-Id: Ied17c3955ea2fda130089265d02908937ad8af1e
This commit is contained in:
@@ -105,6 +105,12 @@ android_app_certificate {
|
|||||||
certificate: "com.android.tethering",
|
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.
|
// Encapsulate the contributions made by the com.android.tethering to the bootclasspath.
|
||||||
bootclasspath_fragment {
|
bootclasspath_fragment {
|
||||||
name: "com.android.tethering-bootclasspath-fragment",
|
name: "com.android.tethering-bootclasspath-fragment",
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ java_sdk_library {
|
|||||||
// Do not add static_libs to this library: put them in framework-connectivity instead.
|
// 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
|
// The jarjar rules are only so that references to jarjared utils in
|
||||||
// framework-connectivity-pre-jarjar match at runtime.
|
// framework-connectivity-pre-jarjar match at runtime.
|
||||||
jarjar_rules: ":connectivity-jarjar-rules",
|
jarjar_rules: ":framework-connectivity-jarjar-rules",
|
||||||
permitted_packages: [
|
permitted_packages: [
|
||||||
"android.app.usage",
|
"android.app.usage",
|
||||||
"android.net",
|
"android.net",
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ java_library {
|
|||||||
// because the tethering stubs depend on the connectivity stubs (e.g.,
|
// because the tethering stubs depend on the connectivity stubs (e.g.,
|
||||||
// TetheringRequest depends on LinkAddress).
|
// TetheringRequest depends on LinkAddress).
|
||||||
"framework-tethering.stubs.module_lib",
|
"framework-tethering.stubs.module_lib",
|
||||||
|
"framework-wifi.stubs.module_lib",
|
||||||
],
|
],
|
||||||
visibility: ["//packages/modules/Connectivity:__subpackages__"]
|
visibility: ["//packages/modules/Connectivity:__subpackages__"]
|
||||||
}
|
}
|
||||||
@@ -119,7 +120,7 @@ java_sdk_library {
|
|||||||
name: "framework-connectivity",
|
name: "framework-connectivity",
|
||||||
defaults: ["framework-connectivity-defaults"],
|
defaults: ["framework-connectivity-defaults"],
|
||||||
installable: true,
|
installable: true,
|
||||||
jarjar_rules: ":connectivity-jarjar-rules",
|
jarjar_rules: ":framework-connectivity-jarjar-rules",
|
||||||
permitted_packages: ["android.net"],
|
permitted_packages: ["android.net"],
|
||||||
impl_library_visibility: [
|
impl_library_visibility: [
|
||||||
"//packages/modules/Connectivity/Tethering/apex",
|
"//packages/modules/Connectivity/Tethering/apex",
|
||||||
@@ -222,3 +223,35 @@ gensrcs {
|
|||||||
],
|
],
|
||||||
output_extension: "srcjar",
|
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",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|||||||
25
framework/jarjar-excludes.txt
Normal file
25
framework/jarjar-excludes.txt
Normal file
@@ -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\..+
|
||||||
@@ -232,7 +232,8 @@ static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, j
|
|||||||
return NULL;
|
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, "<init>", "(IIIIII)V");
|
jmethodID ctor = env->GetMethodID(class_TcpRepairWindow, "<init>", "(IIIIII)V");
|
||||||
|
|
||||||
return env->NewObject(class_TcpRepairWindow, ctor, trw.snd_wl1, trw.snd_wnd, trw.max_window,
|
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 },
|
{ "bindSocketToNetworkHandle", "(Ljava/io/FileDescriptor;J)I", (void*) android_net_utils_bindSocketToNetworkHandle },
|
||||||
{ "attachDropAllBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDropAllBPFFilter },
|
{ "attachDropAllBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDropAllBPFFilter },
|
||||||
{ "detachBPFFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_detachBPFFilter },
|
{ "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 },
|
{ "resNetworkSend", "(J[BII)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkSend },
|
||||||
{ "resNetworkQuery", "(JLjava/lang/String;III)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkQuery },
|
{ "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 },
|
{ "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult },
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public class DnsResolverServiceManager {
|
|||||||
|
|
||||||
private final IBinder mResolver;
|
private final IBinder mResolver;
|
||||||
|
|
||||||
DnsResolverServiceManager(IBinder resolver) {
|
public DnsResolverServiceManager(IBinder resolver) {
|
||||||
mResolver = resolver;
|
mResolver = resolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public final class NattSocketKeepalive extends SocketKeepalive {
|
|||||||
@NonNull private final InetAddress mDestination;
|
@NonNull private final InetAddress mDestination;
|
||||||
private final int mResourceId;
|
private final int mResourceId;
|
||||||
|
|
||||||
NattSocketKeepalive(@NonNull IConnectivityManager service,
|
public NattSocketKeepalive(@NonNull IConnectivityManager service,
|
||||||
@NonNull Network network,
|
@NonNull Network network,
|
||||||
@NonNull ParcelFileDescriptor pfd,
|
@NonNull ParcelFileDescriptor pfd,
|
||||||
int resourceId,
|
int resourceId,
|
||||||
@@ -48,7 +48,7 @@ public final class NattSocketKeepalive extends SocketKeepalive {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void startImpl(int intervalSec) {
|
protected void startImpl(int intervalSec) {
|
||||||
mExecutor.execute(() -> {
|
mExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
mService.startNattKeepaliveWithFd(mNetwork, mPfd, mResourceId,
|
mService.startNattKeepaliveWithFd(mNetwork, mPfd, mResourceId,
|
||||||
@@ -62,7 +62,7 @@ public final class NattSocketKeepalive extends SocketKeepalive {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void stopImpl() {
|
protected void stopImpl() {
|
||||||
mExecutor.execute(() -> {
|
mExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
if (mSlot != null) {
|
if (mSlot != null) {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import java.util.concurrent.Executor;
|
|||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
class QosCallbackConnection extends android.net.IQosCallback.Stub {
|
public class QosCallbackConnection extends android.net.IQosCallback.Stub {
|
||||||
|
|
||||||
@NonNull private final ConnectivityManager mConnectivityManager;
|
@NonNull private final ConnectivityManager mConnectivityManager;
|
||||||
@Nullable private volatile QosCallback mCallback;
|
@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
|
* {@link Executor} must run callback sequentially, otherwise the order of
|
||||||
* callbacks cannot be guaranteed.
|
* callbacks cannot be guaranteed.
|
||||||
*/
|
*/
|
||||||
QosCallbackConnection(@NonNull final ConnectivityManager connectivityManager,
|
public QosCallbackConnection(@NonNull final ConnectivityManager connectivityManager,
|
||||||
@NonNull final QosCallback callback,
|
@NonNull final QosCallback callback,
|
||||||
@NonNull final Executor executor) {
|
@NonNull final Executor executor) {
|
||||||
mConnectivityManager = Objects.requireNonNull(connectivityManager,
|
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
|
* There are no synchronization guarantees on exactly when the callback will stop receiving
|
||||||
* messages.
|
* messages.
|
||||||
*/
|
*/
|
||||||
void stopReceivingMessages() {
|
public void stopReceivingMessages() {
|
||||||
mCallback = null;
|
mCallback = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public final class QosCallbackException extends Exception {
|
|||||||
* {@hide}
|
* {@hide}
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
static QosCallbackException createException(@ExceptionType final int type) {
|
public static QosCallbackException createException(@ExceptionType final int type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case EX_TYPE_FILTER_NETWORK_RELEASED:
|
case EX_TYPE_FILTER_NETWORK_RELEASED:
|
||||||
return new QosCallbackException(new NetworkReleasedException());
|
return new QosCallbackException(new NetworkReleasedException());
|
||||||
|
|||||||
@@ -33,13 +33,15 @@ import java.net.InetAddress;
|
|||||||
@SystemApi
|
@SystemApi
|
||||||
public abstract class QosFilter {
|
public abstract class QosFilter {
|
||||||
|
|
||||||
/**
|
/** @hide */
|
||||||
* The constructor is kept hidden from outside this package to ensure that all derived types
|
protected QosFilter() {
|
||||||
* are known and properly handled when being passed to and from {@link NetworkAgent}.
|
// Ensure that all derived types are known, and known to be properly handled when being
|
||||||
*
|
// passed to and from NetworkAgent.
|
||||||
* @hide
|
// For now the only known derived type is QosSocketFilter.
|
||||||
*/
|
if (!(this instanceof QosSocketFilter)) {
|
||||||
QosFilter() {
|
throw new UnsupportedOperationException(
|
||||||
|
"Unsupported QosFilter type: " + this.getClass().getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -73,9 +73,10 @@ public final class QosSocketInfo implements Parcelable {
|
|||||||
* The parcel file descriptor wrapped around the socket's file descriptor.
|
* The parcel file descriptor wrapped around the socket's file descriptor.
|
||||||
*
|
*
|
||||||
* @return the parcel file descriptor of the socket
|
* @return the parcel file descriptor of the socket
|
||||||
|
* @hide
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
ParcelFileDescriptor getParcelFileDescriptor() {
|
public ParcelFileDescriptor getParcelFileDescriptor() {
|
||||||
return mParcelFileDescriptor;
|
return mParcelFileDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,8 @@ import java.util.concurrent.Executor;
|
|||||||
* request. If it does, it MUST support at least 3 concurrent keepalive slots.
|
* request. If it does, it MUST support at least 3 concurrent keepalive slots.
|
||||||
*/
|
*/
|
||||||
public abstract class SocketKeepalive implements AutoCloseable {
|
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.
|
* Success. It indicates there is no error.
|
||||||
@@ -215,15 +216,22 @@ public abstract class SocketKeepalive implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull final IConnectivityManager mService;
|
/** @hide */
|
||||||
@NonNull final Network mNetwork;
|
@NonNull protected final IConnectivityManager mService;
|
||||||
@NonNull final ParcelFileDescriptor mPfd;
|
/** @hide */
|
||||||
@NonNull final Executor mExecutor;
|
@NonNull protected final Network mNetwork;
|
||||||
@NonNull final ISocketKeepaliveCallback mCallback;
|
/** @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.
|
// 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 ParcelFileDescriptor pfd,
|
||||||
@NonNull Executor executor, @NonNull Callback callback) {
|
@NonNull Executor executor, @NonNull Callback callback) {
|
||||||
mService = service;
|
mService = service;
|
||||||
@@ -303,7 +311,8 @@ public abstract class SocketKeepalive implements AutoCloseable {
|
|||||||
startImpl(intervalSec);
|
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}
|
* Requests that keepalive be stopped. The application must wait for {@link Callback#onStopped}
|
||||||
@@ -313,7 +322,8 @@ public abstract class SocketKeepalive implements AutoCloseable {
|
|||||||
stopImpl();
|
stopImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract void stopImpl();
|
/** @hide */
|
||||||
|
protected abstract void stopImpl();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactivate this {@link SocketKeepalive} and free allocated resources. The instance won't be
|
* Deactivate this {@link SocketKeepalive} and free allocated resources. The instance won't be
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ import android.util.Log;
|
|||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
/** @hide */
|
/** @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 Network network,
|
||||||
@NonNull ParcelFileDescriptor pfd,
|
@NonNull ParcelFileDescriptor pfd,
|
||||||
@NonNull Executor executor,
|
@NonNull Executor executor,
|
||||||
@@ -50,7 +50,7 @@ final class TcpSocketKeepalive extends SocketKeepalive {
|
|||||||
* acknowledgement.
|
* acknowledgement.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void startImpl(int intervalSec) {
|
protected void startImpl(int intervalSec) {
|
||||||
mExecutor.execute(() -> {
|
mExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
mService.startTcpKeepalive(mNetwork, mPfd, intervalSec, mCallback);
|
mService.startTcpKeepalive(mNetwork, mPfd, intervalSec, mCallback);
|
||||||
@@ -62,7 +62,7 @@ final class TcpSocketKeepalive extends SocketKeepalive {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void stopImpl() {
|
protected void stopImpl() {
|
||||||
mExecutor.execute(() -> {
|
mExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
if (mSlot != null) {
|
if (mSlot != null) {
|
||||||
|
|||||||
@@ -224,9 +224,15 @@ java_library {
|
|||||||
lint: { strict_updatability_linting: true },
|
lint: { strict_updatability_linting: true },
|
||||||
}
|
}
|
||||||
|
|
||||||
filegroup {
|
genrule {
|
||||||
name: "connectivity-jarjar-rules",
|
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__"],
|
visibility: ["//packages/modules/Connectivity:__subpackages__"],
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,3 +243,45 @@ filegroup {
|
|||||||
srcs: ["src/com/android/server/BpfNetMaps.java"],
|
srcs: ["src/com/android/server/BpfNetMaps.java"],
|
||||||
visibility: ["//packages/modules/Connectivity:__subpackages__"],
|
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"],
|
||||||
|
}
|
||||||
|
|||||||
9
service/jarjar-excludes.txt
Normal file
9
service/jarjar-excludes.txt
Normal file
@@ -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\..+
|
||||||
@@ -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)
|
|
||||||
@@ -2,8 +2,6 @@
|
|||||||
# TODO: instead of keeping everything, consider listing only "entry points"
|
# TODO: instead of keeping everything, consider listing only "entry points"
|
||||||
# (service loader, JNI registered methods, etc) and letting the optimizer do its job
|
# (service loader, JNI registered methods, etc) and letting the optimizer do its job
|
||||||
-keep class android.net.** { *; }
|
-keep class android.net.** { *; }
|
||||||
-keep class com.android.connectivity.** { *; }
|
|
||||||
-keep class com.android.net.** { *; }
|
|
||||||
-keep class !com.android.server.nearby.**,com.android.server.** { *; }
|
-keep class !com.android.server.nearby.**,com.android.server.** { *; }
|
||||||
|
|
||||||
# Prevent proguard from stripping out any nearby-service and fast-pair-lite-protos fields.
|
# 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
|
# This replicates the base proguard rule used by the build by default
|
||||||
# (proguard_basic_keeps.flags), but needs to be specified here because the
|
# (proguard_basic_keeps.flags), but needs to be specified here because the
|
||||||
# com.google.protobuf package is jarjared to the below package.
|
# com.google.protobuf package is jarjared to the below package.
|
||||||
-keepclassmembers class * extends com.android.connectivity.com.google.protobuf.MessageLite { <fields>; }
|
-keepclassmembers class * extends com.android.server.nearby.com.google.protobuf.MessageLite { <fields>; }
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ package {
|
|||||||
|
|
||||||
java_library {
|
java_library {
|
||||||
name: "FrameworksNetCommonTests",
|
name: "FrameworksNetCommonTests",
|
||||||
defaults: ["framework-connectivity-test-defaults"],
|
defaults: ["framework-connectivity-internal-test-defaults"],
|
||||||
srcs: [
|
srcs: [
|
||||||
"java/**/*.java",
|
"java/**/*.java",
|
||||||
"java/**/*.kt",
|
"java/**/*.kt",
|
||||||
@@ -49,6 +49,7 @@ java_library {
|
|||||||
// jarjar stops at the first matching rule, so order of concatenation affects the output.
|
// jarjar stops at the first matching rule, so order of concatenation affects the output.
|
||||||
genrule {
|
genrule {
|
||||||
name: "ConnectivityCoverageJarJarRules",
|
name: "ConnectivityCoverageJarJarRules",
|
||||||
|
defaults: ["jarjar-rules-combine-defaults"],
|
||||||
srcs: [
|
srcs: [
|
||||||
"tethering-jni-jarjar-rules.txt",
|
"tethering-jni-jarjar-rules.txt",
|
||||||
":connectivity-jarjar-rules",
|
":connectivity-jarjar-rules",
|
||||||
@@ -56,8 +57,6 @@ genrule {
|
|||||||
":NetworkStackJarJarRules",
|
":NetworkStackJarJarRules",
|
||||||
],
|
],
|
||||||
out: ["jarjar-rules-connectivity-coverage.txt"],
|
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"],
|
visibility: ["//visibility:private"],
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +83,7 @@ android_test {
|
|||||||
target_sdk_version: "31",
|
target_sdk_version: "31",
|
||||||
test_suites: ["general-tests", "mts-tethering"],
|
test_suites: ["general-tests", "mts-tethering"],
|
||||||
defaults: [
|
defaults: [
|
||||||
"framework-connectivity-test-defaults",
|
"framework-connectivity-internal-test-defaults",
|
||||||
"FrameworksNetTests-jni-defaults",
|
"FrameworksNetTests-jni-defaults",
|
||||||
"libnetworkstackutilsjni_deps",
|
"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.
|
// Defaults for tests that want to run in mainline-presubmit.
|
||||||
// Not widely used because many of our tests have AndroidTest.xml files and
|
// Not widely used because many of our tests have AndroidTest.xml files and
|
||||||
// use the mainline-param config-descriptor metadata in AndroidTest.xml.
|
// use the mainline-param config-descriptor metadata in AndroidTest.xml.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ package {
|
|||||||
|
|
||||||
android_test {
|
android_test {
|
||||||
name: "FrameworksNetIntegrationTests",
|
name: "FrameworksNetIntegrationTests",
|
||||||
defaults: ["framework-connectivity-test-defaults"],
|
defaults: ["framework-connectivity-internal-test-defaults"],
|
||||||
platform_apis: true,
|
platform_apis: true,
|
||||||
certificate: "platform",
|
certificate: "platform",
|
||||||
srcs: [
|
srcs: [
|
||||||
@@ -71,8 +71,12 @@ java_library {
|
|||||||
"net-tests-utils",
|
"net-tests-utils",
|
||||||
],
|
],
|
||||||
libs: [
|
libs: [
|
||||||
"service-connectivity",
|
"service-connectivity-pre-jarjar",
|
||||||
"services.core",
|
"services.core",
|
||||||
"services.net",
|
"services.net",
|
||||||
],
|
],
|
||||||
|
visibility: [
|
||||||
|
"//packages/modules/Connectivity/tests/integration",
|
||||||
|
"//packages/modules/Connectivity/tests/unit",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ java_defaults {
|
|||||||
name: "FrameworksNetTestsDefaults",
|
name: "FrameworksNetTestsDefaults",
|
||||||
min_sdk_version: "30",
|
min_sdk_version: "30",
|
||||||
defaults: [
|
defaults: [
|
||||||
"framework-connectivity-test-defaults",
|
"framework-connectivity-internal-test-defaults",
|
||||||
],
|
],
|
||||||
srcs: [
|
srcs: [
|
||||||
"java/**/*.java",
|
"java/**/*.java",
|
||||||
|
|||||||
46
tools/Android.bp
Normal file
46
tools/Android.bp
Normal file
@@ -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__"],
|
||||||
|
}
|
||||||
166
tools/gen_jarjar.py
Executable file
166
tools/gen_jarjar.py
Executable file
@@ -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 != '', '<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()
|
||||||
Reference in New Issue
Block a user