From f250ade6fa1741371bf5d65aebe16a0c1226b514 Mon Sep 17 00:00:00 2001 From: Mark Chien Date: Mon, 4 Aug 2025 10:56:38 +0000 Subject: [PATCH] Move #nativeWaitForService into CommonConnectivityJni AServiceManager_waitForService sytem APIs currently only callable via dlsym(): b/376759605. When built with sdk_version current, the NDK stubs for "sdk" variants only include NDK APIs, excluding #systemapi APIs. Flag: EXEMPT Mechanical refactors Test: atest ServiceManagerWrapperIntegrationTest Change-Id: I48f690d771c7905e79e463617ded772f753cc854 --- service/Android.bp | 3 +- ...m_android_server_ServiceManagerWrapper.cpp | 54 ------------------- service/jni/onload.cpp | 11 ++-- .../android/server/ServiceManagerWrapper.java | 46 ---------------- .../module/util/CommonConnectivityJni.java | 14 +++++ .../native/commonconnectivityjni/Android.bp | 1 + ..._net_module_util_CommonConnectivityJni.cpp | 29 ++++++++++ .../ServiceManagerWrapperIntegrationTest.kt | 6 +-- .../ThreadNetworkControllerService.java | 4 +- 9 files changed, 53 insertions(+), 115 deletions(-) delete mode 100644 service/jni/com_android_server_ServiceManagerWrapper.cpp delete mode 100644 service/src/com/android/server/ServiceManagerWrapper.java diff --git a/service/Android.bp b/service/Android.bp index 01370dc036..8db355e4e6 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -107,6 +107,7 @@ cc_library_shared { ], min_sdk_version: "30", shared_libs: [ + "libbinder_ndk", "liblog", "libnativehelper", ], @@ -136,7 +137,6 @@ cc_library_shared { srcs: [ ":services.connectivity-netstats-jni-sources", "jni/com_android_server_connectivity_ClatCoordinator.cpp", - "jni/com_android_server_ServiceManagerWrapper.cpp", "jni/onload.cpp", ], header_libs: [ @@ -154,7 +154,6 @@ cc_library_shared { ], shared_libs: [ "libbase", - "libbinder_ndk", "libcutils", "libnetdutils", "liblog", diff --git a/service/jni/com_android_server_ServiceManagerWrapper.cpp b/service/jni/com_android_server_ServiceManagerWrapper.cpp deleted file mode 100644 index 0e32726aff..0000000000 --- a/service/jni/com_android_server_ServiceManagerWrapper.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2023 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 -#include -#include "nativehelper/JNIHelp.h" -#include -#include - -namespace android { -static jobject com_android_server_ServiceManagerWrapper_waitForService( - JNIEnv* env, jobject clazz, jstring serviceName) { - ScopedUtfChars name(env, serviceName); - -// AServiceManager_waitForService is available on only 31+, but it's still safe for Thread -// service because it's enabled on only 34+ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" - return AIBinder_toJavaBinder(env, AServiceManager_waitForService(name.c_str())); -#pragma clang diagnostic pop -} - -/* - * JNI registration. - */ - -static const JNINativeMethod gMethods[] = { - /* name, signature, funcPtr */ - {"nativeWaitForService", - "(Ljava/lang/String;)Landroid/os/IBinder;", - (void*)com_android_server_ServiceManagerWrapper_waitForService}, -}; - -int register_com_android_server_ServiceManagerWrapper(JNIEnv* env) { - return jniRegisterNativeMethods(env, - "android/net/connectivity/com/android/server/ServiceManagerWrapper", - gMethods, NELEM(gMethods)); -} - -}; // namespace android diff --git a/service/jni/onload.cpp b/service/jni/onload.cpp index f87470d05c..2e25e52b0f 100644 --- a/service/jni/onload.cpp +++ b/service/jni/onload.cpp @@ -21,10 +21,9 @@ namespace android { -int register_com_android_server_connectivity_ClatCoordinator(JNIEnv* env); -int register_android_server_net_NetworkStatsFactory(JNIEnv* env); -int register_android_server_net_NetworkStatsService(JNIEnv* env); -int register_com_android_server_ServiceManagerWrapper(JNIEnv* env); +int register_com_android_server_connectivity_ClatCoordinator(JNIEnv *env); +int register_android_server_net_NetworkStatsFactory(JNIEnv *env); +int register_android_server_net_NetworkStatsService(JNIEnv *env); int register_com_android_net_module_util_ServiceConnectivityJni(JNIEnv *env, char const *class_name); @@ -35,10 +34,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { return JNI_ERR; } - if (register_com_android_server_ServiceManagerWrapper(env) < 0) { - return JNI_ERR; - } - if (android::modules::sdklevel::IsAtLeastT()) { if (register_com_android_server_connectivity_ClatCoordinator(env) < 0) { return JNI_ERR; diff --git a/service/src/com/android/server/ServiceManagerWrapper.java b/service/src/com/android/server/ServiceManagerWrapper.java deleted file mode 100644 index 6d99f333e5..0000000000 --- a/service/src/com/android/server/ServiceManagerWrapper.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import android.annotation.RequiresApi; -import android.os.IBinder; -import android.os.Build; -import android.os.ServiceManager; - -/** Provides a way to access {@link ServiceManager#waitForService} API. */ -@RequiresApi(Build.VERSION_CODES.S) -public final class ServiceManagerWrapper { - static { - System.loadLibrary("service-connectivity"); - } - - private ServiceManagerWrapper() {} - - /** - * Returns the specified service from the service manager. - * - * If the service is not running, service manager will attempt to start it, and this function - * will wait for it to be ready. - * - * @return {@code null} only if there are permission problems or fatal errors - */ - public static IBinder waitForService(String serviceName) { - return nativeWaitForService(serviceName); - } - - private static native IBinder nativeWaitForService(String serviceName); -} diff --git a/staticlibs/device/com/android/net/module/util/CommonConnectivityJni.java b/staticlibs/device/com/android/net/module/util/CommonConnectivityJni.java index 644aac394c..493b0c0925 100644 --- a/staticlibs/device/com/android/net/module/util/CommonConnectivityJni.java +++ b/staticlibs/device/com/android/net/module/util/CommonConnectivityJni.java @@ -16,6 +16,9 @@ package com.android.net.module.util; +import android.annotation.RequiresApi; +import android.os.Build; +import android.os.IBinder; import android.system.ErrnoException; /** @@ -48,4 +51,15 @@ public class CommonConnectivityJni { * @throws ErrnoException if setting expiration time is failed. */ public static native void setTimerFdTime(int fd, long timeMs) throws ErrnoException; + + /** + * Returns the specified service from the service manager. + * + * If the service is not running, service manager will attempt to start it, and this function + * will wait for it to be ready. + * + * @return {@code null} only if there are permission problems or fatal errors + */ + @RequiresApi(Build.VERSION_CODES.S) + public static native IBinder waitForService(String serviceName); } diff --git a/staticlibs/native/commonconnectivityjni/Android.bp b/staticlibs/native/commonconnectivityjni/Android.bp index 79465e6164..679883f04a 100644 --- a/staticlibs/native/commonconnectivityjni/Android.bp +++ b/staticlibs/native/commonconnectivityjni/Android.bp @@ -26,6 +26,7 @@ cc_library_static { "jni_headers", ], shared_libs: [ + "libbinder_ndk", "liblog", "libnativehelper_compat_libc++", ], diff --git a/staticlibs/native/commonconnectivityjni/com_android_net_module_util_CommonConnectivityJni.cpp b/staticlibs/native/commonconnectivityjni/com_android_net_module_util_CommonConnectivityJni.cpp index 557e55866d..092e42e452 100644 --- a/staticlibs/native/commonconnectivityjni/com_android_net_module_util_CommonConnectivityJni.cpp +++ b/staticlibs/native/commonconnectivityjni/com_android_net_module_util_CommonConnectivityJni.cpp @@ -13,12 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define LOG_TAG "CommonConnectivityJni" + +#include #include +#include +#include #include +#include #define MSEC_PER_SEC 1000 #define NSEC_PER_MSEC 1000000 +#define LIBBINDER_NDK_PATH "libbinder_ndk.so" namespace android { @@ -51,6 +58,26 @@ static void setTimerFdTime(JNIEnv *env, jclass clazz, jint tfd, } } +using waitForServiceFunc = AIBinder *(*)(const char *instance); + +static jobject ServiceManagerWrapper_waitForService(JNIEnv *env, jobject clazz, + jstring serviceName) { + // AServiceManager_waitForService system APIs currently only callable via + // dlsym(): b/376759605. When built with sdk_version current, the NDK stubs + // for "sdk" variants only include NDK APIs, excluding #systemapi APIs. + // TODO: AServiceManager_waitForService requires SDK version 31. + // Remove this after dropping mainline support for R. + auto waitForService = (waitForServiceFunc)dlsym(RTLD_DEFAULT, "AServiceManager_waitForService"); + if (waitForService == nullptr) { + __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, + "Failed to look up AServiceManager_waitForService"); + return nullptr; + } + + ScopedUtfChars name(env, serviceName); + return AIBinder_toJavaBinder(env, waitForService(name.c_str())); +} + //------------------------------------------------------------------------------ /* @@ -60,6 +87,8 @@ static const JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ {"createTimerFd", "()I", (void *)createTimerFd}, {"setTimerFdTime", "(IJ)V", (void *)setTimerFdTime}, + {"waitForService", "(Ljava/lang/String;)Landroid/os/IBinder;", + (void *)ServiceManagerWrapper_waitForService}, }; int register_CommonConnectivityJni(JNIEnv *env, char const *class_name) { diff --git a/tests/integration/src/com/android/server/net/integrationtests/ServiceManagerWrapperIntegrationTest.kt b/tests/integration/src/com/android/server/net/integrationtests/ServiceManagerWrapperIntegrationTest.kt index 7e00ed2b3f..e2e07d7a3c 100644 --- a/tests/integration/src/com/android/server/net/integrationtests/ServiceManagerWrapperIntegrationTest.kt +++ b/tests/integration/src/com/android/server/net/integrationtests/ServiceManagerWrapperIntegrationTest.kt @@ -18,7 +18,7 @@ package com.android.server.net.integrationtests import android.content.Context import android.os.Build -import com.android.server.ServiceManagerWrapper +import com.android.net.module.util.CommonConnectivityJni import com.android.testutils.ConnectivityModuleTest import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.DevSdkIgnoreRunner @@ -26,13 +26,13 @@ import kotlin.test.assertNotNull import org.junit.Test import org.junit.runner.RunWith -/** Integration tests for {@link ServiceManagerWrapper}. */ +/** Integration tests for {@link CommonConnectivityJni}. */ @RunWith(DevSdkIgnoreRunner::class) @IgnoreUpTo(Build.VERSION_CODES.S) @ConnectivityModuleTest class ServiceManagerWrapperIntegrationTest { @Test fun testWaitForService_successFullyRetrievesConnectivityServiceBinder() { - assertNotNull(ServiceManagerWrapper.waitForService(Context.CONNECTIVITY_SERVICE)) + assertNotNull(CommonConnectivityJni.waitForService(Context.CONNECTIVITY_SERVICE)) } } diff --git a/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java b/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java index e99c88ee46..b040498070 100644 --- a/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java +++ b/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java @@ -123,10 +123,10 @@ import android.util.SparseArray; import com.android.connectivity.resources.R; import com.android.internal.annotations.VisibleForTesting; +import com.android.net.module.util.CommonConnectivityJni; import com.android.net.module.util.IIpv4PrefixRequest; import com.android.net.module.util.RoutingCoordinatorManager; import com.android.net.module.util.SharedLog; -import com.android.server.ServiceManagerWrapper; import com.android.server.connectivity.ConnectivityResources; import com.android.server.connectivity.MockableSystemProperties; import com.android.server.thread.openthread.BackboneRouterState; @@ -292,7 +292,7 @@ final class ThreadNetworkControllerService extends IThreadNetworkController.Stub handler, new MockableSystemProperties(), networkProvider, - () -> IOtDaemon.Stub.asInterface(ServiceManagerWrapper.waitForService("ot_daemon")), + () -> IOtDaemon.Stub.asInterface(CommonConnectivityJni.waitForService("ot_daemon")), connectivityManager, routingCoordinatorManager, new TunInterfaceController(TUN_IF_NAME),