xref: /aosp_15_r20/frameworks/base/ravenwood/runtime-jni/jni_helper.h (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <jni.h>
18 #include <log/log.h>
19 #include <nativehelper/JNIHelp.h>
20 #include <nativehelper/ScopedLocalRef.h>
21 #include <nativehelper/ScopedPrimitiveArray.h>
22 #include <nativehelper/ScopedUtfChars.h>
23 
24 #include <string>
25 
26 constexpr const char* kCommonUtils = "com/android/ravenwood/common/RavenwoodCommonUtils";
27 constexpr const char* kRuntimeEnvController =
28         "android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController";
29 constexpr const char* kRunnerState = "android/platform/test/ravenwood/RavenwoodRunnerState";
30 constexpr const char* kRuntimeNative = "com/android/ravenwood/RavenwoodRuntimeNative";
31 
32 // We have to explicitly decode the string to real UTF-8, because when using GetStringUTFChars
33 // we only get modified UTF-8, which is not the platform string type used in host JVM.
34 struct ScopedRealUtf8Chars {
ScopedRealUtf8CharsScopedRealUtf8Chars35     ScopedRealUtf8Chars(JNIEnv* env, jstring s) : valid_(false) {
36         if (s == nullptr) {
37             jniThrowNullPointerException(env);
38             return;
39         }
40         jclass clazz = env->GetObjectClass(s);
41         jmethodID getBytes = env->GetMethodID(clazz, "getBytes", "(Ljava/lang/String;)[B");
42 
43         ScopedLocalRef<jstring> utf8(env, env->NewStringUTF("UTF-8"));
44         ScopedLocalRef<jbyteArray> jbytes(env,
45                                           (jbyteArray)env->CallObjectMethod(s, getBytes,
46                                                                             utf8.get()));
47 
48         ScopedByteArrayRO bytes(env, jbytes.get());
49         string_.append((const char*)bytes.get(), bytes.size());
50         valid_ = true;
51     }
52 
c_strScopedRealUtf8Chars53     const char* c_str() const {
54         return valid_ ? string_.c_str() : nullptr;
55     }
56 
sizeScopedRealUtf8Chars57     size_t size() const {
58         return string_.size();
59     }
60 
61     const char& operator[](size_t n) const {
62         return string_[n];
63     }
64 
65 private:
66     std::string string_;
67     bool valid_;
68 };
69 
GetJNIEnvOrDie(JavaVM * vm)70 static inline JNIEnv* GetJNIEnvOrDie(JavaVM* vm) {
71     JNIEnv* env = nullptr;
72     vm->GetEnv((void**)&env, JNI_VERSION_1_4);
73     LOG_ALWAYS_FATAL_IF(env == nullptr, "Could not retrieve JNIEnv.");
74     return env;
75 }
76 
FindClassOrDie(JNIEnv * env,const char * class_name)77 static inline jclass FindClassOrDie(JNIEnv* env, const char* class_name) {
78     jclass clazz = env->FindClass(class_name);
79     LOG_ALWAYS_FATAL_IF(clazz == NULL, "Unable to find class %s", class_name);
80     return clazz;
81 }
82 
83 template <typename T>
MakeGlobalRefOrDie(JNIEnv * env,T in)84 static inline T MakeGlobalRefOrDie(JNIEnv* env, T in) {
85     jobject res = env->NewGlobalRef(in);
86     LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to create global reference.");
87     return static_cast<T>(res);
88 }
89 
FindGlobalClassOrDie(JNIEnv * env,const char * class_name)90 static inline jclass FindGlobalClassOrDie(JNIEnv* env, const char* class_name) {
91     return MakeGlobalRefOrDie(env, FindClassOrDie(env, class_name));
92 }
93 
GetStaticMethodIDOrDie(JNIEnv * env,jclass clazz,const char * method_name,const char * method_signature)94 static inline jmethodID GetStaticMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name,
95                                                const char* method_signature) {
96     jmethodID res = env->GetStaticMethodID(clazz, method_name, method_signature);
97     LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static method %s with signature %s",
98                         method_name, method_signature);
99     return res;
100 }
101