From 771b570ddc9ab4e087ca9470a8e4f86f6ea5e564 Mon Sep 17 00:00:00 2001 From: Brett Chabot Date: Wed, 18 Sep 2024 21:43:24 +0000 Subject: Also support setJniMethodFormat in hwui. Idfb9e0900957e3a13bde10ba9626dd9b6ff4ac99 added support for binding to a native methods that have been renamed by a fixed pattern to jni_wrappers.h. This commit copies the identical logic to graphics_jni_helpers.h And also refactors the existing logic to avoid a memory leak. Flag: EXEMPT: Only changes the behavior on host-side test. Bug: 323057854 Test: m libandroid_runtime Merged-In: I1a25389f7c6eb3270a32d858ee114ddadbc72a65 Change-Id: I232e1ca8ecf2faff2af692624a51188ed317e297 --- libs/hwui/jni/graphics_jni_helpers.h | 45 +++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'libs/hwui') diff --git a/libs/hwui/jni/graphics_jni_helpers.h b/libs/hwui/jni/graphics_jni_helpers.h index 78db54acc9e5..91db134af18f 100644 --- a/libs/hwui/jni/graphics_jni_helpers.h +++ b/libs/hwui/jni/graphics_jni_helpers.h @@ -80,9 +80,52 @@ static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) { return static_cast(res); } +// Inline variable that specifies the method binding format. +// The expected format is 'XX${method}XX', where ${method} represents the original method name. +// This variable is shared across all translation units. This is treated as a global variable as +// per C++ 17. +inline std::string jniMethodFormat; + +inline static void setJniMethodFormat(std::string value) { + jniMethodFormat = value; +} + +// Register the native methods, potenially applying the jniMethodFormat if it has been set. +static inline int jniRegisterMaybeRenamedNativeMethods(JNIEnv* env, const char* className, + const JNINativeMethod* gMethods, + int numMethods) { + if (jniMethodFormat.empty()) { + return jniRegisterNativeMethods(env, className, gMethods, numMethods); + } + + // Make a copy of gMethods with reformatted method names. + JNINativeMethod* modifiedMethods = new JNINativeMethod[numMethods]; + LOG_ALWAYS_FATAL_IF(!modifiedMethods, "Failed to allocate a copy of the JNI methods"); + + size_t methodNamePos = jniMethodFormat.find("${method}"); + LOG_ALWAYS_FATAL_IF(methodNamePos == std::string::npos, + "Invalid jniMethodFormat: could not find '${method}' in pattern"); + + for (int i = 0; i < numMethods; i++) { + modifiedMethods[i] = gMethods[i]; + std::string modifiedName = jniMethodFormat; + modifiedName.replace(methodNamePos, 9, gMethods[i].name); + char* modifiedNameChars = new char[modifiedName.length() + 1]; + LOG_ALWAYS_FATAL_IF(!modifiedNameChars, "Failed to allocate the new method name"); + std::strcpy(modifiedNameChars, modifiedName.c_str()); + modifiedMethods[i].name = modifiedNameChars; + } + int res = jniRegisterNativeMethods(env, className, modifiedMethods, numMethods); + for (int i = 0; i < numMethods; i++) { + delete[] modifiedMethods[i].name; + } + delete[] modifiedMethods; + return res; +} + static inline int RegisterMethodsOrDie(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { - int res = jniRegisterNativeMethods(env, className, gMethods, numMethods); + int res = jniRegisterMaybeRenamedNativeMethods(env, className, gMethods, numMethods); LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods."); return res; } -- cgit v1.2.3-59-g8ed1b