From 40330008c3e765ad66444798c85fbdc288fc1c26 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 19 Mar 2021 10:13:40 +0000 Subject: [PATCH] Move NetworkUtils JNI out of core/jni Keep the utilities included via a library, but move them out of core/jni, and prepare a library to package them together with framework-connectivity. Also remove unnecessary dependencies in framework-connectivity. Bug: 171540887 Test: device boots and has connectivity Merged-In: I0b55dfe92f3cb6e848d79ac7953756f39aaa2597 Change-Id: I0b55dfe92f3cb6e848d79ac7953756f39aaa2597 --- framework/Android.bp | 53 +++++++++++++--- .../jni/android_net_NetworkUtils.cpp | 61 ++++++++++++++++--- framework/jni/onload.cpp | 38 ++++++++++++ 3 files changed, 134 insertions(+), 18 deletions(-) rename {core => framework}/jni/android_net_NetworkUtils.cpp (79%) create mode 100644 framework/jni/onload.cpp diff --git a/framework/Android.bp b/framework/Android.bp index 5b33328833..657d5a3d2e 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -100,9 +100,50 @@ java_sdk_library { libs: [ "unsupportedappusage", ], - permitted_packages: [ - "android.net", - "com.android.connectivity.aidl", + permitted_packages: ["android.net"], +} + +cc_defaults { + name: "libframework-connectivity-defaults", + cflags: [ + "-Wall", + "-Werror", + "-Wno-unused-parameter", + "-Wthread-safety", + ], + shared_libs: [ + "libbase", + "liblog", + "libnativehelper", + "libnetd_client", + ], + header_libs: [ + "dnsproxyd_protocol_headers", + ], +} + +cc_library_static { + name: "libconnectivityframeworkutils", + defaults: ["libframework-connectivity-defaults"], + srcs: [ + "jni/android_net_NetworkUtils.cpp", + ], + apex_available: [ + "//apex_available:platform", + "com.android.tethering", + ], +} + +cc_library_shared { + name: "libframework-connectivity-jni", + defaults: ["libframework-connectivity-defaults"], + srcs: [ + "jni/onload.cpp", + ], + static_libs: ["libconnectivityframeworkutils"], + apex_available: [ + "//apex_available:platform", + "com.android.tethering", ], } @@ -124,7 +165,6 @@ java_library { "framework-tethering", "framework-wifi", "unsupportedappusage", - "ServiceConnectivityResources", ], static_libs: [ "framework-connectivity-protos", @@ -133,8 +173,5 @@ java_library { jarjar_rules: "jarjar-rules.txt", apex_available: ["com.android.tethering"], installable: true, - permitted_packages: [ - "android.net", - "com.android.connectivity.aidl", - ], + permitted_packages: ["android.net"], } diff --git a/core/jni/android_net_NetworkUtils.cpp b/framework/jni/android_net_NetworkUtils.cpp similarity index 79% rename from core/jni/android_net_NetworkUtils.cpp rename to framework/jni/android_net_NetworkUtils.cpp index 1cee8955a7..c70309f6ce 100644 --- a/core/jni/android_net_NetworkUtils.cpp +++ b/framework/jni/android_net_NetworkUtils.cpp @@ -36,7 +36,6 @@ #include #include "NetdClient.h" -#include "core_jni_helpers.h" #include "jni.h" extern "C" { @@ -52,6 +51,48 @@ constexpr int MAXPACKETSIZE = 8 * 1024; // FrameworkListener limits the size of commands to 4096 bytes. constexpr int MAXCMDSIZE = 4096; +static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) { + jclass clazz = env->FindClass(class_name); + LOG_ALWAYS_FATAL_IF(clazz == NULL, "Unable to find class %s", class_name); + return clazz; +} + +static inline jmethodID GetMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name, + const char* method_signature) { + jmethodID res = env->GetMethodID(clazz, method_name, method_signature); + LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find method %s with signature %s", method_name, + method_signature); + return res; +} + +template +static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) { + jobject res = env->NewGlobalRef(in); + LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to create global reference."); + return static_cast(res); +} + +static void throwErrnoException(JNIEnv* env, const char* functionName, int error) { + ScopedLocalRef detailMessage(env, env->NewStringUTF(functionName)); + if (detailMessage.get() == NULL) { + // Not really much we can do here. We're probably dead in the water, + // but let's try to stumble on... + env->ExceptionClear(); + } + static jclass errnoExceptionClass = + MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/system/ErrnoException")); + + static jmethodID errnoExceptionCtor = + GetMethodIDOrDie(env, errnoExceptionClass, + "", "(Ljava/lang/String;I)V"); + + jobject exception = env->NewObject(errnoExceptionClass, + errnoExceptionCtor, + detailMessage.get(), + error); + env->Throw(reinterpret_cast(exception)); +} + static void android_net_utils_attachDropAllBPFFilter(JNIEnv *env, jobject clazz, jobject javaFd) { struct sock_filter filter_code[] = { @@ -124,7 +165,7 @@ static jobject android_net_utils_resNetworkQuery(JNIEnv *env, jobject thiz, jint int fd = resNetworkQuery(netId, queryname.data(), ns_class, ns_type, flags); if (fd < 0) { - jniThrowErrnoException(env, "resNetworkQuery", -fd); + throwErrnoException(env, "resNetworkQuery", -fd); return nullptr; } @@ -139,7 +180,7 @@ static jobject android_net_utils_resNetworkSend(JNIEnv *env, jobject thiz, jint int fd = resNetworkSend(netId, data, msgLen, flags); if (fd < 0) { - jniThrowErrnoException(env, "resNetworkSend", -fd); + throwErrnoException(env, "resNetworkSend", -fd); return nullptr; } @@ -154,13 +195,13 @@ static jobject android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz, job int res = resNetworkResult(fd, &rcode, buf.data(), MAXPACKETSIZE); jniSetFileDescriptorOfFD(env, javaFd, -1); if (res < 0) { - jniThrowErrnoException(env, "resNetworkResult", -res); + throwErrnoException(env, "resNetworkResult", -res); return nullptr; } jbyteArray answer = env->NewByteArray(res); if (answer == nullptr) { - jniThrowErrnoException(env, "resNetworkResult", ENOMEM); + throwErrnoException(env, "resNetworkResult", ENOMEM); return nullptr; } else { env->SetByteArrayRegion(answer, 0, res, @@ -182,7 +223,7 @@ static void android_net_utils_resNetworkCancel(JNIEnv *env, jobject thiz, jobjec static jobject android_net_utils_getDnsNetwork(JNIEnv *env, jobject thiz) { unsigned dnsNetId = 0; if (int res = getNetworkForDns(&dnsNetId) < 0) { - jniThrowErrnoException(env, "getDnsNetId", -res); + throwErrnoException(env, "getDnsNetId", -res); return nullptr; } bool privateDnsBypass = dnsNetId & NETID_USE_LOCAL_NAMESERVERS; @@ -207,7 +248,7 @@ static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, j // Obtain the parameters of the TCP repair window. int rc = getsockopt(fd, IPPROTO_TCP, TCP_REPAIR_WINDOW, &trw, &size); if (rc == -1) { - jniThrowErrnoException(env, "getsockopt : TCP_REPAIR_WINDOW", errno); + throwErrnoException(env, "getsockopt : TCP_REPAIR_WINDOW", errno); return NULL; } @@ -218,7 +259,7 @@ static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, j // should be applied to the window size. rc = getsockopt(fd, IPPROTO_TCP, TCP_INFO, &tcpinfo, &tcpinfo_size); if (rc == -1) { - jniThrowErrnoException(env, "getsockopt : TCP_INFO", errno); + throwErrnoException(env, "getsockopt : TCP_INFO", errno); return NULL; } @@ -254,8 +295,8 @@ static const JNINativeMethod gNetworkUtilMethods[] = { int register_android_net_NetworkUtils(JNIEnv* env) { - return RegisterMethodsOrDie(env, NETUTILS_PKG_NAME, gNetworkUtilMethods, - NELEM(gNetworkUtilMethods)); + return jniRegisterNativeMethods(env, NETUTILS_PKG_NAME, gNetworkUtilMethods, + NELEM(gNetworkUtilMethods)); } }; // namespace android diff --git a/framework/jni/onload.cpp b/framework/jni/onload.cpp new file mode 100644 index 0000000000..435f4343ed --- /dev/null +++ b/framework/jni/onload.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 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. + */ + +#include +#include + +namespace android { + +int register_android_net_NetworkUtils(JNIEnv* env); + +extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { + JNIEnv *env; + if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { + ALOGE("GetEnv failed"); + return JNI_ERR; + } + + if (register_android_net_NetworkUtils(env) < 0) { + return JNI_ERR; + } + + return JNI_VERSION_1_6; +} + +}; \ No newline at end of file