/* * Copyright (C) 2024 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 #include #include #include constexpr const char* kCommonUtils = "com/android/ravenwood/common/RavenwoodCommonUtils"; constexpr const char* kRuntimeEnvController = "android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController"; constexpr const char* kRunnerState = "android/platform/test/ravenwood/RavenwoodRunnerState"; constexpr const char* kRuntimeNative = "com/android/ravenwood/RavenwoodRuntimeNative"; // We have to explicitly decode the string to real UTF-8, because when using GetStringUTFChars // we only get modified UTF-8, which is not the platform string type used in host JVM. struct ScopedRealUtf8Chars { ScopedRealUtf8Chars(JNIEnv* env, jstring s) : valid_(false) { if (s == nullptr) { jniThrowNullPointerException(env); return; } jclass clazz = env->GetObjectClass(s); jmethodID getBytes = env->GetMethodID(clazz, "getBytes", "(Ljava/lang/String;)[B"); ScopedLocalRef utf8(env, env->NewStringUTF("UTF-8")); ScopedLocalRef jbytes(env, (jbyteArray)env->CallObjectMethod(s, getBytes, utf8.get())); ScopedByteArrayRO bytes(env, jbytes.get()); string_.append((const char*)bytes.get(), bytes.size()); valid_ = true; } const char* c_str() const { return valid_ ? string_.c_str() : nullptr; } size_t size() const { return string_.size(); } const char& operator[](size_t n) const { return string_[n]; } private: std::string string_; bool valid_; }; static inline JNIEnv* GetJNIEnvOrDie(JavaVM* vm) { JNIEnv* env = nullptr; vm->GetEnv((void**)&env, JNI_VERSION_1_4); LOG_ALWAYS_FATAL_IF(env == nullptr, "Could not retrieve JNIEnv."); return env; } 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; } 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 inline jclass FindGlobalClassOrDie(JNIEnv* env, const char* class_name) { return MakeGlobalRefOrDie(env, FindClassOrDie(env, class_name)); } static inline jmethodID GetStaticMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name, const char* method_signature) { jmethodID res = env->GetStaticMethodID(clazz, method_name, method_signature); LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static method %s with signature %s", method_name, method_signature); return res; }