From 3d50059bbcc4700495ce5178ac54c051672d45b7 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Sun, 21 Mar 2021 14:30:38 +0000 Subject: [PATCH] Add NDK API for getprocnetwork The API is the getter couterpart for setprocnetwork. Use it in NetworkUtils so that the NDK API can be the source of truth for the process network. Bug: 171540887 Test: atest CtsNetTestCases Tests in change I311b58585033c2ca50ce5477ea9cd94b6f127507 Change-Id: Ie8f68cf1fa57deddb63324c1abf3d6fd5b0ef500 --- core/jni/Android.bp | 1 + native/android/libandroid.map.txt | 3 ++- native/android/libandroid_net.map.txt | 2 ++ native/android/net.c | 24 ++++++++++++++++--- packages/Connectivity/framework/Android.bp | 2 ++ .../jni/android_net_NetworkUtils.cpp | 20 +++++++++++----- .../src/android/net/NetworkUtils.java | 15 ++++++++++-- 7 files changed, 55 insertions(+), 12 deletions(-) diff --git a/core/jni/Android.bp b/core/jni/Android.bp index f49a834a96e03..f1fa5dbcbbdc5 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -238,6 +238,7 @@ cc_library_shared { "android.hardware.camera.device@3.2", "media_permission-aidl-cpp", "libandroidicu", + "libandroid_net", "libbpf_android", "libnetdbpf", "libnetdutils", diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt index b01878b3070b5..85513cad489cb 100644 --- a/native/android/libandroid.map.txt +++ b/native/android/libandroid.map.txt @@ -285,6 +285,7 @@ LIBANDROID { ATrace_endAsyncSection; # introduced=29 ATrace_setCounter; # introduced=29 android_getaddrinfofornetwork; # introduced=23 + android_getprocnetwork; # introduced=31 android_setprocnetwork; # introduced=23 android_setsocknetwork; # introduced=23 android_res_cancel; # introduced=29 @@ -309,4 +310,4 @@ LIBANDROID_PLATFORM { ASurfaceControlStats_getAcquireTime*; ASurfaceControlStats_getFrameNumber*; }; -} LIBANDROID; \ No newline at end of file +} LIBANDROID; diff --git a/native/android/libandroid_net.map.txt b/native/android/libandroid_net.map.txt index 8d4e9009cc569..cc8dd727408f1 100644 --- a/native/android/libandroid_net.map.txt +++ b/native/android/libandroid_net.map.txt @@ -14,6 +14,8 @@ LIBANDROID_NET { android_res_nquery; # llndk android_res_nresult; # llndk android_res_nsend; # llndk + # These functions have been part of the NDK since API 31. + android_getprocnetwork; # llndk local: *; }; diff --git a/native/android/net.c b/native/android/net.c index a8104fc230417..d4b888845b27c 100644 --- a/native/android/net.c +++ b/native/android/net.c @@ -22,12 +22,13 @@ #include #include +// This value MUST be kept in sync with the corresponding value in +// the android.net.Network#getNetworkHandle() implementation. +static const uint32_t kHandleMagic = 0xcafed00d; +static const uint32_t kHandleMagicSize = 32; static int getnetidfromhandle(net_handle_t handle, unsigned *netid) { static const uint32_t k32BitMask = 0xffffffff; - // This value MUST be kept in sync with the corresponding value in - // the android.net.Network#getNetworkHandle() implementation. - static const uint32_t kHandleMagic = 0xcafed00d; // Check for minimum acceptable version of the API in the low bits. if (handle != NETWORK_UNSPECIFIED && @@ -41,6 +42,12 @@ static int getnetidfromhandle(net_handle_t handle, unsigned *netid) { return 1; } +static net_handle_t gethandlefromnetid(unsigned netid) { + if (netid == NETID_UNSET) { + return NETWORK_UNSPECIFIED; + } + return (((net_handle_t) netid) << kHandleMagicSize) | kHandleMagic; +} int android_setsocknetwork(net_handle_t network, int fd) { unsigned netid; @@ -72,6 +79,17 @@ int android_setprocnetwork(net_handle_t network) { return rval; } +int android_getprocnetwork(net_handle_t *network) { + if (network == NULL) { + errno = EINVAL; + return -1; + } + + unsigned netid = getNetworkForProcess(); + *network = gethandlefromnetid(netid); + return 0; +} + int android_getaddrinfofornetwork(net_handle_t network, const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { diff --git a/packages/Connectivity/framework/Android.bp b/packages/Connectivity/framework/Android.bp index 657d5a3d2eae7..3553c1f053109 100644 --- a/packages/Connectivity/framework/Android.bp +++ b/packages/Connectivity/framework/Android.bp @@ -128,6 +128,7 @@ cc_library_static { srcs: [ "jni/android_net_NetworkUtils.cpp", ], + shared_libs: ["libandroid_net"], apex_available: [ "//apex_available:platform", "com.android.tethering", @@ -140,6 +141,7 @@ cc_library_shared { srcs: [ "jni/onload.cpp", ], + shared_libs: ["libandroid"], static_libs: ["libconnectivityframeworkutils"], apex_available: [ "//apex_available:platform", diff --git a/packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp b/packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp index 19ffe77c1fa20..89b058af69ea4 100644 --- a/packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp +++ b/packages/Connectivity/framework/jni/android_net_NetworkUtils.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -122,14 +123,21 @@ static void android_net_utils_detachBPFFilter(JNIEnv *env, jobject clazz, jobjec } } -static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId) +static jboolean android_net_utils_bindProcessToNetworkHandle(JNIEnv *env, jobject thiz, + jlong netHandle) { - return (jboolean) !setNetworkForProcess(netId); + return (jboolean) !android_setprocnetwork(netHandle); } -static jint android_net_utils_getBoundNetworkForProcess(JNIEnv *env, jobject thiz) +static jlong android_net_utils_getBoundNetworkHandleForProcess(JNIEnv *env, jobject thiz) { - return getNetworkForProcess(); + net_handle_t network; + if (android_getprocnetwork(&network) != 0) { + jniThrowExceptionFmt(env, "java/lang/IllegalStateException", + "android_getprocnetwork(): %s", strerror(errno)); + return NETWORK_UNSPECIFIED; + } + return (jlong) network; } static jboolean android_net_utils_bindProcessToNetworkForHostResolution(JNIEnv *env, jobject thiz, @@ -283,8 +291,8 @@ static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, j // clang-format off static const JNINativeMethod gNetworkUtilMethods[] = { /* name, signature, funcPtr */ - { "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork }, - { "getBoundNetworkForProcess", "()I", (void*) android_net_utils_getBoundNetworkForProcess }, + { "bindProcessToNetworkHandle", "(J)Z", (void*) android_net_utils_bindProcessToNetworkHandle }, + { "getBoundNetworkHandleForProcess", "()J", (void*) android_net_utils_getBoundNetworkHandleForProcess }, { "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution }, { "bindSocketToNetwork", "(Ljava/io/FileDescriptor;I)I", (void*) android_net_utils_bindSocketToNetwork }, { "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess }, diff --git a/packages/Connectivity/framework/src/android/net/NetworkUtils.java b/packages/Connectivity/framework/src/android/net/NetworkUtils.java index c0f262815b0c5..4c61d4089d6e3 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkUtils.java +++ b/packages/Connectivity/framework/src/android/net/NetworkUtils.java @@ -16,6 +16,8 @@ package android.net; +import static android.net.ConnectivityManager.NETID_UNSET; + import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.system.ErrnoException; @@ -55,6 +57,8 @@ public class NetworkUtils { */ public static native void detachBPFFilter(FileDescriptor fd) throws SocketException; + private static native boolean bindProcessToNetworkHandle(long netHandle); + /** * Binds the current process to the network designated by {@code netId}. All sockets created * in the future (and not explicitly bound via a bound {@link SocketFactory} (see @@ -63,13 +67,20 @@ public class NetworkUtils { * is by design so an application doesn't accidentally use sockets it thinks are still bound to * a particular {@code Network}. Passing NETID_UNSET clears the binding. */ - public native static boolean bindProcessToNetwork(int netId); + public static boolean bindProcessToNetwork(int netId) { + return bindProcessToNetworkHandle(new Network(netId).getNetworkHandle()); + } + + private static native long getBoundNetworkHandleForProcess(); /** * Return the netId last passed to {@link #bindProcessToNetwork}, or NETID_UNSET if * {@link #unbindProcessToNetwork} has been called since {@link #bindProcessToNetwork}. */ - public native static int getBoundNetworkForProcess(); + public static int getBoundNetworkForProcess() { + final long netHandle = getBoundNetworkHandleForProcess(); + return netHandle == 0L ? NETID_UNSET : Network.fromNetworkHandle(netHandle).getNetId(); + } /** * Binds host resolutions performed by this process to the network designated by {@code netId}.