no message

This commit is contained in:
gem
2025-02-18 15:21:31 +08:00
commit 2d133e56d7
1980 changed files with 465595 additions and 0 deletions

View File

@@ -0,0 +1,80 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "platform/java/jni/JniHelper.h"
#if CC_PLATFORM == CC_PLATFORM_ANDROID
#include <android/keycodes.h>
#include <android/log.h>
#elif CC_PLATFORM == CC_PLATFORM_OHOS
#include <hilog/log.h>
#endif
#include <jni.h>
#include "engine/EngineEvents.h"
#include "platform/java/jni/glue/JniNativeGlue.h"
#include "platform/java/modules/SystemWindow.h"
namespace {
struct cc::KeyboardEvent keyboardEvent;
// key values in web, refer to http://docs.cocos.com/creator/api/en/enums/KEY.html
#if CC_PLATFORM == CC_PLATFORM_ANDROID
ccstd::unordered_map<int, int> keyCodeMap = {
{AKEYCODE_BACK, 6},
{AKEYCODE_ENTER, 13},
{AKEYCODE_MENU, 18},
{AKEYCODE_DPAD_UP, 1003},
{AKEYCODE_DPAD_DOWN, 1004},
{AKEYCODE_DPAD_LEFT, 1000},
{AKEYCODE_DPAD_RIGHT, 1001},
{AKEYCODE_DPAD_CENTER, 1005}};
#elif CC_PLATFORM == CC_PLATFORM_OHOS
ccstd::unordered_map<int, int> keyCodeMap = {};
#endif
//NOLINTNEXTLINE
static void dispatchKeyCodeEvent(int keyCode, cc::KeyboardEvent &event) {
if (keyCodeMap.count(keyCode) > 0) {
keyCode = keyCodeMap[keyCode];
} else {
keyCode = 0;
}
event.windowId = cc::ISystemWindow::mainWindowId;
event.key = keyCode;
cc::events::Keyboard::broadcast(event);
}
} // namespace
extern "C" {
//NOLINTNEXTLINE
JNIEXPORT void JNICALL Java_com_cocos_lib_CocosKeyCodeHandler_handleKeyDown(JNIEnv *env, jobject obj, jint keyCode) {
keyboardEvent.action = cc::KeyboardEvent::Action::PRESS;
dispatchKeyCodeEvent(keyCode, keyboardEvent);
}
//NOLINTNEXTLINE
JNIEXPORT void JNICALL Java_com_cocos_lib_CocosKeyCodeHandler_handleKeyUp(JNIEnv *env, jobject obj, jint keyCode) {
keyboardEvent.action = cc::KeyboardEvent::Action::RELEASE;
dispatchKeyCodeEvent(keyCode, keyboardEvent);
}
}

View File

@@ -0,0 +1,67 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include <jni.h>
#include "engine/EngineEvents.h"
#include "platform/interfaces/modules/Device.h"
#include "platform/java/jni/JniHelper.h"
#include "platform/java/jni/glue/JniNativeGlue.h"
#include "platform/java/modules/SystemWindow.h"
extern "C" {
// NOLINTNEXTLINE
JNIEXPORT void JNICALL Java_com_cocos_lib_CocosOrientationHelper_nativeOnOrientationChanged(JNIEnv *env, jclass thiz, jint rotation) {
int orientation;
switch (rotation) {
case 0: // ROTATION_0
orientation = (int)cc::Device::Orientation::PORTRAIT;
case 1: // ROTATION_90
orientation = (int)cc::Device::Orientation::LANDSCAPE_RIGHT;
case 2: // ROTATION_180
orientation = (int)cc::Device::Orientation::PORTRAIT_UPSIDE_DOWN;
case 3: // ROTATION_270
orientation = (int)cc::Device::Orientation::LANDSCAPE_LEFT;
}
// run callbacks in game thread?
cc::events::Orientation::broadcast(orientation);
}
JNIEXPORT void JNICALL Java_com_cocos_lib_CocosAbilitySlice_onOrientationChangedNative(JNIEnv *env, jobject obj, jint orientation, jint width, jint height) { //NOLINT JNI function name
static jint pOrientation = 0;
static jint pWidth = 0;
static jint pHeight = 0;
if (pOrientation != orientation || pWidth != width || pHeight != height) {
cc::WindowEvent ev;
// TODO(qgh):The windows ID needs to be passed down from the jave, which is currently using the main window.
ev.windowId = cc::ISystemWindow::mainWindowId;
ev.type = cc::WindowEvent::Type::SIZE_CHANGED;
ev.width = width;
ev.height = height;
cc::events::WindowEvent::broadcast(ev);
pOrientation = orientation;
pHeight = height;
pWidth = width;
}
}
}

View File

@@ -0,0 +1,100 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include <jni.h>
#include "engine/EngineEvents.h"
#include "platform/java/jni/JniHelper.h"
#include "platform/java/jni/glue/JniNativeGlue.h"
#include "platform/java/modules/SystemWindow.h"
#include "platform/java/modules/SystemWindowManager.h"
namespace {
cc::TouchEvent touchEvent;
}
extern "C" {
//NOLINTNEXTLINE
JNIEXPORT void JNICALL Java_com_cocos_lib_CocosTouchHandler_handleActionDown(JNIEnv *env, jobject obj, jint id,
jfloat x, jfloat y) {
// TODO(qgh):The windows ID needs to be passed down from the jave, which is currently using the main window.
touchEvent.windowId = cc::ISystemWindow::mainWindowId;
touchEvent.type = cc::TouchEvent::Type::BEGAN;
touchEvent.touches.emplace_back(x, y, id);
cc::events::Touch::broadcast(touchEvent);
touchEvent.touches.clear();
}
//NOLINTNEXTLINE
JNIEXPORT void JNICALL Java_com_cocos_lib_CocosTouchHandler_handleActionUp(JNIEnv *env, jobject obj, jint id, jfloat x,
jfloat y) {
touchEvent.windowId = cc::ISystemWindow::mainWindowId;
touchEvent.type = cc::TouchEvent::Type::ENDED;
touchEvent.touches.emplace_back(x, y, id);
cc::events::Touch::broadcast(touchEvent);
touchEvent.touches.clear();
}
//NOLINTNEXTLINE
JNIEXPORT void JNICALL Java_com_cocos_lib_CocosTouchHandler_handleActionMove(JNIEnv *env, jobject obj,
jintArray ids,
jfloatArray xs,
jfloatArray ys) {
touchEvent.type = cc::TouchEvent::Type::MOVED;
touchEvent.windowId = cc::ISystemWindow::mainWindowId;
int size = env->GetArrayLength(ids);
jint id[size];
jfloat x[size];
jfloat y[size];
env->GetIntArrayRegion(ids, 0, size, id);
env->GetFloatArrayRegion(xs, 0, size, x);
env->GetFloatArrayRegion(ys, 0, size, y);
for (int i = 0; i < size; i++) {
touchEvent.touches.emplace_back(x[i], y[i], id[i]);
}
cc::events::Touch::broadcast(touchEvent);
touchEvent.touches.clear();
}
//NOLINTNEXTLINE
JNIEXPORT void JNICALL Java_com_cocos_lib_CocosTouchHandler_handleActionCancel(JNIEnv *env, jobject obj,
jintArray ids,
jfloatArray xs,
jfloatArray ys) {
touchEvent.type = cc::TouchEvent::Type::CANCELLED;
touchEvent.windowId = cc::ISystemWindow::mainWindowId;
int size = env->GetArrayLength(ids);
jint id[size];
jfloat x[size];
jfloat y[size];
env->GetIntArrayRegion(ids, 0, size, id);
env->GetFloatArrayRegion(xs, 0, size, x);
env->GetFloatArrayRegion(ys, 0, size, y);
for (int i = 0; i < size; i++) {
touchEvent.touches.emplace_back(x[i], y[i], id[i]);
}
cc::events::Touch::broadcast(touchEvent);
touchEvent.touches.clear();
}
}

View File

@@ -0,0 +1,447 @@
/****************************************************************************
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "platform/java/jni/JniHelper.h"
#if ANDROID
#include <android/log.h>
#else
#include "cocos/base/Log.h"
#endif
#include <pthread.h>
#include <cstring>
#include "base/UTF8.h"
#define CC_CACHE_CLASS_ID 0
#if ANDROID
#define LOG_TAG "JniHelper"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#else
#define LOGD(...) CC_LOG_DEBUG(__VA_ARGS__)
#define LOGE(...) CC_LOG_ERROR(__VA_ARGS__)
#endif
namespace {
pthread_key_t g_key; // NOLINT(readability-identifier-naming)
class JClassWrapper final {
public:
explicit JClassWrapper(jclass kls) {
if (kls) {
_globalKls = static_cast<jclass>(cc::JniHelper::getEnv()->NewGlobalRef(static_cast<jobject>(kls)));
}
}
~JClassWrapper() {
if (_globalKls) {
cc::JniHelper::getEnv()->DeleteGlobalRef(_globalKls);
}
_globalKls = nullptr;
}
jclass operator*() const {
return _globalKls;
}
private:
jclass _globalKls = {};
};
#if CC_CACHE_CLASS_ID
ccstd::unordered_map<const char *, JClassWrapper> _cachedJClasses;
#endif
}; // namespace
jclass _getClassID(const char *className) { // NOLINT
if (nullptr == className) {
return nullptr;
}
#if CC_CACHE_CLASS_ID
auto it = _cachedJClasses.find(className);
if (it != _cachedJClasses.end()) {
return *it->second;
}
#endif
JNIEnv *env = cc::JniHelper::getEnv();
jstring jstrClassName = env->NewStringUTF(className);
auto *klassObj = static_cast<jclass>(env->CallObjectMethod(cc::JniHelper::classloader,
cc::JniHelper::loadclassMethodMethodId,
jstrClassName));
if (nullptr == klassObj || env->ExceptionCheck()) {
LOGE("Classloader failed to find class of %s", className);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
}
env->ExceptionClear();
klassObj = nullptr;
}
ccDeleteLocalRef(env, jstrClassName);
// LOGE("1. delete 0x%p", jstrClassName);
#if CC_CACHE_CLASS_ID
if (klassObj) {
_cachedJClasses.emplace(className, klassObj);
}
#endif
return klassObj;
}
void cbDetachCurrentThread(void * /*a*/) {
cc::JniHelper::getJavaVM()->DetachCurrentThread();
}
namespace cc {
jmethodID JniHelper::loadclassMethodMethodId = nullptr;
jobject JniHelper::classloader = nullptr;
std::function<void()> JniHelper::classloaderCallback = nullptr;
jobject JniHelper::sContext = nullptr;
JavaVM *JniHelper::sJavaVM = nullptr;
JavaVM *JniHelper::getJavaVM() {
pthread_t thisthread = pthread_self();
LOGD("JniHelper::getJavaVM(), pthread_self() = %ld", thisthread);
return JniHelper::sJavaVM;
}
void JniHelper::init(JNIEnv *env, jobject context) {
env->GetJavaVM(&JniHelper::sJavaVM);
JniHelper::sContext = context;
pthread_key_create(&g_key, cbDetachCurrentThread);
auto ok = JniHelper::setClassLoaderFrom(context);
CC_ASSERT(ok);
}
void JniHelper::onDestroy() {
if (JniHelper::sJavaVM) {
if (JniHelper::sContext) {
cc::JniHelper::getEnv()->DeleteGlobalRef(JniHelper::sContext);
JniHelper::sContext = nullptr;
}
LOGD("JniHelper::onDestroy");
}
}
JNIEnv *JniHelper::cacheEnv() {
JavaVM *jvm = JniHelper::sJavaVM;
JNIEnv *env = nullptr;
// get jni environment
jint ret = jvm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4);
switch (ret) {
case JNI_OK:
// Success!
pthread_setspecific(g_key, env);
return env;
case JNI_EDETACHED:
// Thread not attached
#if CC_PLATFORM == CC_PLATFORM_ANDROID
if (jvm->AttachCurrentThread(&env, nullptr) < 0) {
#else
if (jvm->AttachCurrentThread(reinterpret_cast<void **>(&env), nullptr) < 0) {
#endif
LOGE("Failed to get the environment using AttachCurrentThread()");
return nullptr;
} else {
// Success : Attached and obtained JNIEnv!
pthread_setspecific(g_key, env);
return env;
}
case JNI_EVERSION:
// Cannot recover from this error
LOGE("JNI interface version 1.4 not supported");
default:
LOGE("Failed to get the environment using GetEnv()");
return nullptr;
}
}
JNIEnv *JniHelper::getEnv() {
auto *env = static_cast<JNIEnv *>(pthread_getspecific(g_key));
if (env == nullptr) {
env = JniHelper::cacheEnv();
}
return env;
}
jobject JniHelper::getContext() {
return sContext;
}
jobject JniHelper::getActivity() {
// TODO(cjh): In normal mode, sContext is Activity itself, but in surface-less mode, we need to
// returns nullptr.
return sContext;
}
#if CC_PLATFORM == CC_PLATFORM_OHOS
bool JniHelper::setClassLoaderFrom(jobject contextInstance) {
if (!JniHelper::classloader) {
JniMethodInfo getclassloaderMethod;
if (!JniHelper::getMethodInfoDefaultClassLoader(getclassloaderMethod,
"ohos/app/AbilityContext",
"getClassloader", // typo ?
"()Ljava/lang/ClassLoader;")) {
return false;
}
jobject klassLoader = cc::JniHelper::getEnv()->CallObjectMethod(contextInstance,
getclassloaderMethod.methodID);
if (nullptr == klassLoader) {
return false;
}
JniMethodInfo loadClass;
if (!JniHelper::getMethodInfoDefaultClassLoader(loadClass,
"java/lang/ClassLoader",
"loadClass",
"(Ljava/lang/String;)Ljava/lang/Class;")) {
return false;
}
JniHelper::classloader = cc::JniHelper::getEnv()->NewGlobalRef(klassLoader);
JniHelper::loadclassMethodMethodId = loadClass.methodID;
}
JniHelper::sContext = cc::JniHelper::getEnv()->NewGlobalRef(contextInstance);
if (JniHelper::classloaderCallback != nullptr) {
JniHelper::classloaderCallback();
}
return true;
}
#elif CC_PLATFORM == CC_PLATFORM_ANDROID
bool JniHelper::setClassLoaderFrom(jobject contextInstance) {
if (!JniHelper::classloader) {
JniMethodInfo getClassloaderMethod;
if (!JniHelper::getMethodInfoDefaultClassLoader(getClassloaderMethod,
"android/content/Context",
"getClassLoader",
"()Ljava/lang/ClassLoader;")) {
return false;
}
jobject classLoader = cc::JniHelper::getEnv()->CallObjectMethod(contextInstance,
getClassloaderMethod.methodID);
if (nullptr == classLoader) {
return false;
}
JniMethodInfo loadClass;
if (!JniHelper::getMethodInfoDefaultClassLoader(loadClass,
"java/lang/ClassLoader",
"loadClass",
"(Ljava/lang/String;)Ljava/lang/Class;")) {
return false;
}
JniHelper::classloader = cc::JniHelper::getEnv()->NewGlobalRef(classLoader);
JniHelper::loadclassMethodMethodId = loadClass.methodID;
}
JniHelper::sContext = cc::JniHelper::getEnv()->NewGlobalRef(contextInstance);
if (JniHelper::classloaderCallback != nullptr) {
JniHelper::classloaderCallback();
}
return true;
}
#endif
bool JniHelper::getStaticMethodInfo(JniMethodInfo &methodinfo,
const char *className,
const char *methodName,
const char *paramCode) {
if ((nullptr == className) ||
(nullptr == methodName) ||
(nullptr == paramCode)) {
return false;
}
JNIEnv *env = JniHelper::getEnv();
if (!env) {
LOGE("Failed to get JNIEnv");
return false;
}
jclass classID = _getClassID(className);
if (!classID) {
LOGE("Failed to find class %s", className);
env->ExceptionClear();
return false;
}
jmethodID methodID = env->GetStaticMethodID(classID, methodName, paramCode);
if (!methodID) {
LOGE("Failed to find static method id of %s", methodName);
env->ExceptionClear();
return false;
}
methodinfo.classID = classID;
methodinfo.env = env;
methodinfo.methodID = methodID;
return true;
}
//NOLINTNEXTLINE
bool JniHelper::getMethodInfoDefaultClassLoader(JniMethodInfo &methodinfo,
const char *className,
const char *methodName,
const char *paramCode) {
if ((nullptr == className) ||
(nullptr == methodName) ||
(nullptr == paramCode)) {
return false;
}
JNIEnv *env = JniHelper::getEnv();
if (!env) {
return false;
}
jclass classID = env->FindClass(className);
if (!classID) {
LOGE("Failed to find class %s", className);
env->ExceptionClear();
return false;
}
jmethodID methodID = env->GetMethodID(classID, methodName, paramCode);
if (!methodID) {
LOGE("Failed to find method id of %s", methodName);
env->ExceptionClear();
return false;
}
methodinfo.classID = classID;
methodinfo.env = env;
methodinfo.methodID = methodID;
return true;
}
bool JniHelper::getMethodInfo(JniMethodInfo &methodinfo,
const char *className,
const char *methodName,
const char *paramCode) {
if ((nullptr == className) ||
(nullptr == methodName) ||
(nullptr == paramCode)) {
return false;
}
JNIEnv *env = JniHelper::getEnv();
if (!env) {
return false;
}
jclass classID = _getClassID(className);
if (!classID) {
LOGE("Failed to find class %s", className);
env->ExceptionClear();
return false;
}
jmethodID methodID = env->GetMethodID(classID, methodName, paramCode);
if (!methodID) {
LOGE("Failed to find method id of %s", methodName);
env->ExceptionClear();
return false;
}
methodinfo.classID = classID;
methodinfo.env = env;
methodinfo.methodID = methodID;
return true;
}
ccstd::string JniHelper::jstring2string(jstring jstr) {
if (jstr == nullptr) {
return "";
}
JNIEnv *env = JniHelper::getEnv();
if (!env) {
return "";
}
ccstd::string strValue = cc::StringUtils::getStringUTFCharsJNI(env, jstr);
return strValue;
}
jstring JniHelper::convert(JniHelper::LocalRefMapType *localRefs, cc::JniMethodInfo *t, const char *x) {
jstring ret = nullptr;
if (x) {
ret = cc::StringUtils::newStringUTFJNI(t->env, x);
}
(*localRefs)[t->env].push_back(ret);
return ret;
}
jstring JniHelper::convert(JniHelper::LocalRefMapType *localRefs, cc::JniMethodInfo *t, const ccstd::string &x) {
return convert(localRefs, t, x.c_str());
}
jobject JniHelper::convert(JniHelper::LocalRefMapType *localRefs, cc::JniMethodInfo *t, const std::vector<std::string> &x) {
jclass stringClass = _getClassID("java/lang/String");
jobjectArray ret = t->env->NewObjectArray(x.size(), stringClass, nullptr);
for (auto i = 0; i < x.size(); i++) {
jstring jstr = cc::StringUtils::newStringUTFJNI(t->env, x[i]);
t->env->SetObjectArrayElement(ret, i, jstr);
t->env->DeleteLocalRef(jstr);
}
(*localRefs)[t->env].push_back(ret);
return ret;
}
void JniHelper::deleteLocalRefs(JNIEnv *env, JniHelper::LocalRefMapType *localRefs) {
if (!env) {
return;
}
for (const auto &ref : (*localRefs)[env]) {
ccDeleteLocalRef(env, ref);
// LOGE("2. delete 0x%p", ref);
}
(*localRefs)[env].clear();
}
void JniHelper::reportError(const ccstd::string &className, const ccstd::string &methodName, const ccstd::string &signature) {
LOGE("Failed to find static java method. Class name: %s, method name: %s, signature: %s ", className.c_str(), methodName.c_str(), signature.c_str());
}
} //namespace cc

View File

@@ -0,0 +1,556 @@
/****************************************************************************
Copyright (c) 2010-2012 cc-x.org
Copyright (c) 2013-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <jni.h>
#include <functional>
#include "base/Log.h"
#include "base/Macros.h"
#include "base/std/container/string.h"
#include "base/std/container/unordered_map.h"
#include "base/std/container/vector.h"
#include "math/Vec3.h"
// The macro must be used this way to find the native method. The principle is not well understood.
#define JNI_METHOD2(CLASS2, FUNC2) Java_##CLASS2##_##FUNC2
#define JNI_METHOD1(CLASS1, FUNC1) JNI_METHOD2(CLASS1, FUNC1)
// ccDeleteLocalRef with classid produces warning??
#if 0
#define ccDeleteLocalRef(jenv, ref) \
do { \
jenv->DeleteLocalRef(ref); \
CC_LOG_DEBUG("deleteLocalRef file: %s, func: %s, line: %d", __FILE__, __FUNCTION__, __LINE__); \
} while (0)
#else
#define ccDeleteLocalRef(jenv, ref) jenv->DeleteLocalRef(ref); // NOLINT
#endif
#define CLEAR_EXCEPTON(env) \
do { \
if (env->ExceptionCheck()) { \
env->ExceptionDescribe(); \
env->ExceptionClear(); \
} \
} while (false)
struct android_app;
namespace cc {
using JniMethodInfo = struct JniMethodInfo_ { // NOLINT(readability-identifier-naming)
JNIEnv *env;
jclass classID;
jmethodID methodID;
};
class CC_DLL JniHelper {
public:
using LocalRefMapType = ccstd::unordered_map<JNIEnv *, ccstd::vector<jobject>>;
static JavaVM *getJavaVM();
static JNIEnv *getEnv();
static jobject getActivity();
static jobject getContext();
static void init(JNIEnv *env, jobject context);
static void onDestroy();
// NOLINTNEXTLINE
static bool getStaticMethodInfo(JniMethodInfo &methodInfo,
const char *className,
const char *methodName,
const char *paramCode);
// NOLINTNEXTLINE
static bool getMethodInfo(JniMethodInfo &methodInfo,
const char *className,
const char *methodName,
const char *paramCode);
static ccstd::string jstring2string(jstring str);
static jmethodID loadclassMethodMethodId;
static jobject classloader;
static std::function<void()> classloaderCallback;
template <typename... Ts>
static jobject newObject(const ccstd::string &className, Ts... xs) {
jobject ret = nullptr;
static const char *methodName = "<init>";
cc::JniMethodInfo t;
ccstd::string signature = "(" + ccstd::string(getJNISignature(xs...)) + ")V";
if (cc::JniHelper::getMethodInfo(t, className.c_str(), methodName, signature.c_str())) {
LocalRefMapType localRefs;
ret = t.env->NewObject(t.classID, t.methodID, convert(&localRefs, &t, xs)...);
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
deleteLocalRefs(t.env, &localRefs);
} else {
reportError(className, methodName, signature);
}
return ret;
}
template <typename... Ts>
static void callObjectVoidMethod(jobject object,
const ccstd::string &className,
const ccstd::string &methodName,
Ts... xs) {
cc::JniMethodInfo t;
ccstd::string signature = "(" + ccstd::string(getJNISignature(xs...)) + ")V";
if (cc::JniHelper::getMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
LocalRefMapType localRefs;
t.env->CallVoidMethod(object, t.methodID, convert(&localRefs, &t, xs)...);
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
CLEAR_EXCEPTON(t.env);
deleteLocalRefs(t.env, &localRefs);
} else {
reportError(className, methodName, signature);
}
}
template <typename... Ts>
static float callObjectFloatMethod(jobject object,
const ccstd::string &className,
const ccstd::string &methodName,
Ts... xs) {
float ret = 0.0F;
cc::JniMethodInfo t;
ccstd::string signature = "(" + ccstd::string(getJNISignature(xs...)) + ")F";
if (cc::JniHelper::getMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
LocalRefMapType localRefs;
ret = t.env->CallFloatMethod(object, t.methodID, convert(&localRefs, &t, xs)...);
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
CLEAR_EXCEPTON(t.env);
deleteLocalRefs(t.env, &localRefs);
} else {
reportError(className, methodName, signature);
}
return ret;
}
template <typename... Ts>
static jlong callObjectLongMethod(jobject object,
const std::string &className,
const std::string &methodName,
Ts... xs) {
jlong ret = 0;
cc::JniMethodInfo t;
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")J";
if (cc::JniHelper::getMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
LocalRefMapType localRefs;
ret = t.env->CallLongMethod(object, t.methodID, convert(&localRefs, &t, xs)...);
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
CLEAR_EXCEPTON(t.env);
deleteLocalRefs(t.env, &localRefs);
} else {
reportError(className, methodName, signature);
}
return ret;
}
template <typename... Ts>
static jbyteArray callObjectByteArrayMethod(jobject object,
const ccstd::string &className,
const ccstd::string &methodName,
Ts... xs) {
jbyteArray ret = nullptr;
cc::JniMethodInfo t;
ccstd::string signature = "(" + ccstd::string(getJNISignature(xs...)) + ")[B";
if (cc::JniHelper::getMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
LocalRefMapType localRefs;
ret = static_cast<jbyteArray>(t.env->CallObjectMethod(object, t.methodID, convert(&localRefs, &t, xs)...));
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
CLEAR_EXCEPTON(t.env);
deleteLocalRefs(t.env, &localRefs);
} else {
reportError(className, methodName, signature);
}
return ret;
}
template <typename... Ts>
static void callStaticVoidMethod(const ccstd::string &className,
const ccstd::string &methodName,
Ts... xs) {
cc::JniMethodInfo t;
ccstd::string signature = "(" + ccstd::string(getJNISignature(xs...)) + ")V";
if (cc::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
LocalRefMapType localRefs;
t.env->CallStaticVoidMethod(t.classID, t.methodID, convert(&localRefs, &t, xs)...);
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
CLEAR_EXCEPTON(t.env);
deleteLocalRefs(t.env, &localRefs);
} else {
reportError(className, methodName, signature);
}
}
template <typename... Ts>
static bool callStaticBooleanMethod(const ccstd::string &className,
const ccstd::string &methodName,
Ts... xs) {
jboolean jret = JNI_FALSE;
cc::JniMethodInfo t;
ccstd::string signature = "(" + ccstd::string(getJNISignature(xs...)) + ")Z";
if (cc::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
LocalRefMapType localRefs;
jret = t.env->CallStaticBooleanMethod(t.classID, t.methodID, convert(&localRefs, &t, xs)...);
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
CLEAR_EXCEPTON(t.env);
deleteLocalRefs(t.env, &localRefs);
} else {
reportError(className, methodName, signature);
}
return (jret == JNI_TRUE);
}
template <typename... Ts>
static int callStaticIntMethod(const ccstd::string &className,
const ccstd::string &methodName,
Ts... xs) {
jint ret = 0;
cc::JniMethodInfo t;
ccstd::string signature = "(" + ccstd::string(getJNISignature(xs...)) + ")I";
if (cc::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
LocalRefMapType localRefs;
ret = t.env->CallStaticIntMethod(t.classID, t.methodID, convert(&localRefs, &t, xs)...);
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
CLEAR_EXCEPTON(t.env);
deleteLocalRefs(t.env, &localRefs);
} else {
reportError(className, methodName, signature);
}
return ret;
}
template <typename... Ts>
static float callStaticFloatMethod(const ccstd::string &className,
const ccstd::string &methodName,
Ts... xs) {
jfloat ret = 0.0;
cc::JniMethodInfo t;
ccstd::string signature = "(" + ccstd::string(getJNISignature(xs...)) + ")F";
if (cc::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
LocalRefMapType localRefs;
ret = t.env->CallStaticFloatMethod(t.classID, t.methodID, convert(&localRefs, &t, xs)...);
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
CLEAR_EXCEPTON(t.env);
deleteLocalRefs(t.env, &localRefs);
} else {
reportError(className, methodName, signature);
}
return ret;
}
template <typename... Ts>
static float *callStaticFloatArrayMethod(const ccstd::string &className,
const ccstd::string &methodName,
Ts... xs) {
static float ret[32];
cc::JniMethodInfo t;
ccstd::string signature = "(" + ccstd::string(getJNISignature(xs...)) + ")[F";
if (cc::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
LocalRefMapType localRefs;
auto *array = static_cast<jfloatArray>(t.env->CallStaticObjectMethod(t.classID, t.methodID, convert(&localRefs, &t, xs)...));
CLEAR_EXCEPTON(t.env);
jsize len = t.env->GetArrayLength(array);
if (len <= 32) {
jfloat *elems = t.env->GetFloatArrayElements(array, nullptr);
if (elems) {
memcpy(ret, elems, sizeof(float) * len);
t.env->ReleaseFloatArrayElements(array, elems, 0);
};
}
CLEAR_EXCEPTON(t.env);
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
ccDeleteLocalRef(t.env, array);
deleteLocalRefs(t.env, &localRefs);
return &ret[0];
}
reportError(className, methodName, signature);
return nullptr;
}
template <typename... Ts>
static Vec3 callStaticVec3Method(const ccstd::string &className,
const ccstd::string &methodName,
Ts... xs) {
Vec3 ret;
cc::JniMethodInfo t;
ccstd::string signature = "(" + ccstd::string(getJNISignature(xs...)) + ")[F";
if (cc::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
LocalRefMapType localRefs;
auto *array = static_cast<jfloatArray>(t.env->CallStaticObjectMethod(t.classID, t.methodID, convert(&localRefs, &t, xs)...));
CLEAR_EXCEPTON(t.env);
jsize len = t.env->GetArrayLength(array);
if (len == 3) {
jfloat *elems = t.env->GetFloatArrayElements(array, nullptr);
ret.x = elems[0];
ret.y = elems[1];
ret.z = elems[2];
t.env->ReleaseFloatArrayElements(array, elems, 0);
}
CLEAR_EXCEPTON(t.env);
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
ccDeleteLocalRef(t.env, array);
deleteLocalRefs(t.env, &localRefs);
} else {
reportError(className, methodName, signature);
}
return ret;
}
template <typename... Ts>
static double callStaticDoubleMethod(const ccstd::string &className,
const ccstd::string &methodName,
Ts... xs) {
jdouble ret = 0.0;
cc::JniMethodInfo t;
ccstd::string signature = "(" + ccstd::string(getJNISignature(xs...)) + ")D";
if (cc::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
LocalRefMapType localRefs;
ret = t.env->CallStaticDoubleMethod(t.classID, t.methodID, convert(&localRefs, &t, xs)...);
CLEAR_EXCEPTON(t.env);
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
deleteLocalRefs(t.env, &localRefs);
} else {
reportError(className, methodName, signature);
}
return ret;
}
template <typename... Ts>
static ccstd::string callStaticStringMethod(const ccstd::string &className,
const ccstd::string &methodName,
Ts... xs) {
ccstd::string ret;
cc::JniMethodInfo t;
ccstd::string signature = "(" + ccstd::string(getJNISignature(xs...)) + ")Ljava/lang/String;";
if (cc::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
LocalRefMapType localRefs;
auto *jret = static_cast<jstring>(t.env->CallStaticObjectMethod(t.classID, t.methodID, convert(&localRefs, &t, xs)...));
CLEAR_EXCEPTON(t.env);
ret = cc::JniHelper::jstring2string(jret);
ccDeleteLocalRef(t.env, jret);
#ifndef __OHOS__
ccDeleteLocalRef(t.env, t.classID);
#endif
deleteLocalRefs(t.env, &localRefs);
} else {
reportError(className, methodName, signature);
}
return ret;
}
static bool setClassLoaderFrom(jobject contextInstance);
private:
static jobject sContext;
static JavaVM *sJavaVM;
static JNIEnv *cacheEnv();
// NOLINTNEXTLINE
static bool getMethodInfoDefaultClassLoader(JniMethodInfo &methodinfo,
const char *className,
const char *methodName,
const char *paramCode);
static jstring convert(LocalRefMapType *localRefs, cc::JniMethodInfo *t, const char *x);
static jstring convert(LocalRefMapType *localRefs, cc::JniMethodInfo *t, const ccstd::string &x);
static jobject convert(LocalRefMapType *localRefs, cc::JniMethodInfo *t, const std::vector<std::string> &x);
template <typename T>
static T convert(LocalRefMapType * /*localRefs*/, cc::JniMethodInfo * /*t*/, T x) {
return x;
}
template <typename T>
static jobject convert(LocalRefMapType *localRefs, cc::JniMethodInfo *t, std::pair<T *, size_t> data) {
jobject ret = nullptr;
#define JNI_SET_TYPED_ARRAY(lowercase, camelCase) \
j##lowercase##Array array = t->env->New##camelCase##Array(data.second); \
t->env->Set##camelCase##ArrayRegion(array, 0, data.second, reinterpret_cast<const j##lowercase *>(data.first)); \
if (array) { \
(*localRefs)[t->env].push_back(array); \
} \
ret = static_cast<jobject>(array);
using U = typename std::remove_cv<typename std::remove_pointer<T>::type>::type;
if (sizeof(U) == 1) {
JNI_SET_TYPED_ARRAY(byte, Byte)
} else if (sizeof(U) == 4 && std::is_integral<U>::value) {
JNI_SET_TYPED_ARRAY(int, Int)
} else if (sizeof(U) == 8 && std::is_integral<U>::value) {
JNI_SET_TYPED_ARRAY(long, Long);
} else if (sizeof(U) == 4 && std::is_floating_point<U>::value) {
JNI_SET_TYPED_ARRAY(float, Float);
} else if (sizeof(U) == 8 && std::is_floating_point<U>::value) {
JNI_SET_TYPED_ARRAY(double, Double);
}
#undef JNI_SET_TYPED_ARRAY
return ret;
}
template <typename T, typename A>
static typename std::enable_if<std::is_arithmetic<T>::value, jobject>::type convert(LocalRefMapType *localRefs, cc::JniMethodInfo *t, const std::vector<T, A> &data) {
jobject ret = nullptr;
#define JNI_SET_TYPED_ARRAY(lowercase, camelCase) \
j##lowercase##Array array = t->env->New##camelCase##Array(data.size()); \
t->env->Set##camelCase##ArrayRegion(array, 0, data.size(), reinterpret_cast<const j##lowercase *>(data.data())); \
if (array) { \
(*localRefs)[t->env].push_back(array); \
} \
ret = static_cast<jobject>(array);
if (sizeof(T) == 1) {
JNI_SET_TYPED_ARRAY(byte, Byte)
} else if (sizeof(T) == 4 && std::is_integral<T>::value) {
JNI_SET_TYPED_ARRAY(int, Int)
} else if (sizeof(T) == 8 && std::is_integral<T>::value) {
JNI_SET_TYPED_ARRAY(long, Long);
} else if (sizeof(T) == 4 && std::is_floating_point<T>::value) {
JNI_SET_TYPED_ARRAY(float, Float);
} else if (sizeof(T) == 8 && std::is_floating_point<T>::value) {
JNI_SET_TYPED_ARRAY(double, Double);
}
#undef JNI_SET_TYPED_ARRAY
return ret;
}
static void deleteLocalRefs(JNIEnv *env, LocalRefMapType *localRefs);
static ccstd::string getJNISignature() {
return "";
}
static ccstd::string getJNISignature(bool /*unused*/) {
return "Z";
}
static ccstd::string getJNISignature(char /*unused*/) {
return "C";
}
static ccstd::string getJNISignature(unsigned char /*unused*/) {
return "B"; // same as jbyte
}
static ccstd::string getJNISignature(int16_t /*unused*/) {
return "S";
}
static ccstd::string getJNISignature(int32_t /*unused*/) {
return "I";
}
static ccstd::string getJNISignature(int64_t /*unused*/) {
return "J";
}
static ccstd::string getJNISignature(float /*unused*/) {
return "F";
}
static ccstd::string getJNISignature(double /*unused*/) {
return "D";
}
static ccstd::string getJNISignature(jbyteArray /*unused*/) {
return "[B";
}
static ccstd::string getJNISignature(jintArray /*unused*/) {
return "[I";
}
static ccstd::string getJNISignature(const char * /*unused*/) {
return "Ljava/lang/String;";
}
static ccstd::string getJNISignature(const ccstd::string & /*unused*/) {
return "Ljava/lang/String;";
}
template <typename T>
static ccstd::string getJNISignature(T x) {
// This template should never be instantiated
static_assert(sizeof(x) == 0, "Unsupported argument type");
return "";
}
template <typename T>
static std::string getJNISignature(std::pair<T *, size_t> /*x*/) {
typename std::remove_pointer<typename std::remove_cv<T>::type>::type m;
return std::string("[") + getJNISignature(m);
}
template <typename T, typename A>
static std::string getJNISignature(const std::vector<T, A> & /*x*/) {
T m;
return std::string("[") + getJNISignature(m);
}
template <typename T, typename... Ts>
static ccstd::string getJNISignature(T x, Ts... xs) {
return getJNISignature(x) + getJNISignature(xs...);
}
static void reportError(const ccstd::string &className, const ccstd::string &methodName, const ccstd::string &signature);
};
} // namespace cc

View File

@@ -0,0 +1,172 @@
/****************************************************************************
Copyright (c) 2018-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "JniImp.h"
#if CC_PLATFORM == CC_PLATFORM_ANDROID
#include <android/log.h>
#else
#include <hilog/log.h>
#endif
#include <jni.h>
#include "JniHelper.h"
#include "cocos/audio/include/AudioEngine.h"
#ifndef JCLS_HELPER
#define JCLS_HELPER "com/cocos/lib/CocosHelper"
#endif
#ifndef JCLS_SENSOR
#define JCLS_SENSOR "com/cocos/lib/CocosSensorHandler"
#endif
#ifndef COM_AUDIOFOCUS_CLASS_NAME
#define COM_AUDIOFOCUS_CLASS_NAME com_cocos_lib_CocosAudioFocusManager
#endif
#define JNI_AUDIO(FUNC) JNI_METHOD1(COM_AUDIOFOCUS_CLASS_NAME, FUNC)
/***********************************************************
* Functions invoke from cpp to Java.
***********************************************************/
namespace cc {
ccstd::string getObbFilePathJNI() {
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getObbFilePath");
}
int getObbAssetFileDescriptorJNI(const ccstd::string &path, int64_t *startOffset, int64_t *size) {
JniMethodInfo methodInfo;
int fd = 0;
if (JniHelper::getStaticMethodInfo(methodInfo, JCLS_HELPER, "getObbAssetFileDescriptor", "(Ljava/lang/String;)[J")) {
jstring stringArg = methodInfo.env->NewStringUTF(path.c_str());
auto *newArray = static_cast<jlongArray>(methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, stringArg));
jsize theArrayLen = methodInfo.env->GetArrayLength(newArray);
if (3 == theArrayLen) {
jboolean copy = JNI_FALSE;
jlong *array = methodInfo.env->GetLongArrayElements(newArray, &copy);
fd = static_cast<int>(array[0]);
*startOffset = array[1];
*size = array[2];
methodInfo.env->ReleaseLongArrayElements(newArray, array, 0);
}
ccDeleteLocalRef(methodInfo.env, methodInfo.classID);
ccDeleteLocalRef(methodInfo.env, stringArg);
}
return fd;
}
ccstd::string getCurrentLanguageJNI() {
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getCurrentLanguage");
}
ccstd::string getCurrentLanguageCodeJNI() {
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getCurrentLanguageCode");
}
ccstd::string getSystemVersionJNI() {
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getSystemVersion");
}
bool openURLJNI(const ccstd::string &url) {
return JniHelper::callStaticBooleanMethod(JCLS_HELPER, "openURL", url);
}
void copyTextToClipboardJNI(const ccstd::string &text) {
JniHelper::callStaticVoidMethod(JCLS_HELPER, "copyTextToClipboard", text);
}
ccstd::string getDeviceModelJNI() {
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getDeviceModel");
}
int getDPIJNI() {
return JniHelper::callStaticIntMethod(JCLS_HELPER, "getDPI");
}
void setVibrateJNI(float duration) {
JniHelper::callStaticVoidMethod(JCLS_HELPER, "vibrate", duration);
}
void setKeepScreenOnJNI(bool isEnabled) {
return JniHelper::callStaticVoidMethod(JCLS_HELPER, "setKeepScreenOn", isEnabled);
}
void finishActivity() {
JniHelper::callStaticVoidMethod(JCLS_HELPER, "finishActivity");
}
int getNetworkTypeJNI() {
return JniHelper::callStaticIntMethod(JCLS_HELPER, "getNetworkType");
}
float *getSafeAreaEdgeJNI() {
return JniHelper::callStaticFloatArrayMethod(JCLS_HELPER, "getSafeArea");
}
int getDeviceRotationJNI() {
return JniHelper::callStaticIntMethod(JCLS_HELPER, "getDeviceRotation");
}
float getBatteryLevelJNI() {
return JniHelper::callStaticFloatMethod(JCLS_HELPER, "getBatteryLevel");
}
void flushTasksOnGameThreadJNI() {
JniHelper::callStaticVoidMethod(JCLS_HELPER,
"flushTasksOnGameThread");
}
void flushTasksOnGameThreadAtForegroundJNI() {
JniHelper::callStaticVoidMethod(JCLS_HELPER,
"flushTasksOnGameThreadAtForeground");
}
void setAccelerometerEnabledJNI(bool isEnabled) {
JniHelper::callStaticVoidMethod(JCLS_SENSOR, "setAccelerometerEnabled", isEnabled);
}
void setAccelerometerIntervalJNI(float interval) {
JniHelper::callStaticVoidMethod(JCLS_SENSOR, "setAccelerometerInterval", interval);
}
float *getDeviceMotionValueJNI() {
return JniHelper::callStaticFloatArrayMethod(JCLS_SENSOR, "getDeviceMotionValue");
}
bool getSupportHPE() {
return JniHelper::callStaticBooleanMethod(JCLS_HELPER, "supportHPE");
}
} // namespace cc
extern "C" {
JNIEXPORT void JNICALL JNI_AUDIO(nativeSetAudioVolumeFactor)(JNIEnv * /*env*/, jclass /* thiz*/, jfloat volumeFactor) {
#if CC_USE_AUDIO
cc::AudioEngine::setVolumeFactor(volumeFactor);
#endif
}
}

View File

@@ -0,0 +1,55 @@
/****************************************************************************
Copyright (c) 2018-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "base/std/container/string.h"
namespace cc {
ccstd::string getObbFilePathJNI();
int getObbAssetFileDescriptorJNI(const ccstd::string &path, int64_t *startOffset, int64_t *size);
ccstd::string getCurrentLanguageJNI();
ccstd::string getCurrentLanguageCodeJNI();
ccstd::string getSystemVersionJNI();
bool openURLJNI(const ccstd::string &url);
void copyTextToClipboardJNI(const ccstd::string &text);
ccstd::string getDeviceModelJNI();
int getDPIJNI();
void setVibrateJNI(float duration);
void setKeepScreenOnJNI(bool isEnabled);
int getNetworkTypeJNI();
float *getSafeAreaEdgeJNI();
int getDeviceRotationJNI();
float getBatteryLevelJNI();
void flushTasksOnGameThreadJNI();
void flushTasksOnGameThreadAtForegroundJNI();
void setAccelerometerEnabledJNI(bool isEnabled);
void setAccelerometerIntervalJNI(float interval);
float *getDeviceMotionValueJNI();
void finishActivity();
/**
* support for High Performance Emulator
*/
bool getSupportHPE();
} // namespace cc

View File

@@ -0,0 +1,298 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "platform/java/jni/glue/JniNativeGlue.h"
#include <functional>
#include <future>
#include "application/ApplicationManager.h"
#include "engine/EngineEvents.h"
#include "platform/BasePlatform.h"
#include "platform/java/jni/JniImp.h"
#include "platform/java/jni/glue/MessagePipe.h"
#include "platform/java/jni/log.h"
#include "platform/java/modules/SystemWindow.h"
#include "platform/java/modules/SystemWindowManager.h"
namespace cc {
JniNativeGlue::~JniNativeGlue() = default;
JniNativeGlue* JniNativeGlue::getInstance() {
static JniNativeGlue jniNativeGlue;
return &jniNativeGlue;
}
void JniNativeGlue::start(int argc, const char** argv) {
_messagePipe = std::make_unique<MessagePipe>();
BasePlatform* platform = cc::BasePlatform::getPlatform();
if (platform->init()) {
LOGV("Platform initialization failed");
}
platform->run(argc, argv);
}
void JniNativeGlue::setWindowHandle(NativeWindowType* window) {
if (_pendingWindow) {
writeCommandSync(JniCommand::JNI_CMD_TERM_WINDOW);
}
_pendingWindow = window;
if (window) {
writeCommandSync(JniCommand::JNI_CMD_INIT_WINDOW);
}
}
void JniNativeGlue::setActivityGetter(std::function<NativeActivity(void)> getter) {
_activityGetter = std::move(getter);
}
void* JniNativeGlue::getActivity() {
return _activityGetter ? _activityGetter() : nullptr;
}
void JniNativeGlue::setEnvGetter(std::function<NativeEnv(void)> getter) {
_envGetter = std::move(getter);
}
void* JniNativeGlue::getEnv() {
return _envGetter ? _envGetter() : nullptr;
}
void JniNativeGlue::setResourceManager(ResourceManagerType* resourceManager) {
_resourceManager = resourceManager;
}
ResourceManagerType* JniNativeGlue::getResourceManager() {
return _resourceManager;
}
NativeWindowType* JniNativeGlue::getWindowHandle() {
return _window;
}
void JniNativeGlue::setSdkVersion(int sdkVersion) {
_sdkVersion = sdkVersion;
}
int JniNativeGlue::getSdkVersion() const {
return _sdkVersion;
}
void JniNativeGlue::setObbPath(const std::string& path) {
_obbPath = path;
}
std::string JniNativeGlue::getObbPath() const {
return _obbPath;
}
void JniNativeGlue::setRunning(bool isRunning) {
_threadPromise.set_value();
_running = isRunning;
}
void JniNativeGlue::waitRunning() {
_threadPromise.get_future().get();
}
bool JniNativeGlue::isRunning() const {
return _running;
}
void JniNativeGlue::flushTasksOnGameThread() const {
// Handle java events send by UI thread. Input events are handled here too.
flushTasksOnGameThreadJNI();
if (_animating) {
flushTasksOnGameThreadAtForegroundJNI();
}
}
void JniNativeGlue::writeCommandAsync(JniCommand cmd) {
CommandMsg msg{.cmd = cmd, .callback = nullptr};
_messagePipe->writeCommand(&msg, sizeof(msg));
}
void JniNativeGlue::writeCommandSync(JniCommand cmd) {
std::promise<void> fu;
CommandMsg msg{.cmd = cmd, .callback = [&fu]() {
fu.set_value();
}};
_messagePipe->writeCommand(&msg, sizeof(msg));
fu.get_future().get();
}
int JniNativeGlue::readCommand(CommandMsg* msg) {
return _messagePipe->readCommand(msg, sizeof(CommandMsg));
}
int JniNativeGlue::readCommandWithTimeout(CommandMsg* cmd, int delayMS) {
return _messagePipe->readCommandWithTimeout(cmd, sizeof(CommandMsg), delayMS);
}
bool JniNativeGlue::isPause() const {
if (!_animating) {
return true;
}
if (_appState == JniCommand::JNI_CMD_PAUSE) {
return true;
}
return false;
}
void JniNativeGlue::onPause() {
writeCommandAsync(JniCommand::JNI_CMD_PAUSE);
}
void JniNativeGlue::onResume() {
writeCommandAsync(JniCommand::JNI_CMD_RESUME);
}
void JniNativeGlue::onLowMemory() {
writeCommandAsync(JniCommand::JNI_CMD_LOW_MEMORY);
}
void JniNativeGlue::execCommand() {
static CommandMsg msg;
static bool runInLowRate{false};
runInLowRate = !_animating || JniCommand::JNI_CMD_PAUSE == _appState;
if (readCommandWithTimeout(&msg, runInLowRate ? 50 : 0) > 0) {
preExecCmd(msg.cmd);
engineHandleCmd(msg.cmd);
postExecCmd(msg.cmd);
if (msg.callback) {
msg.callback();
}
}
}
void JniNativeGlue::preExecCmd(JniCommand cmd) {
switch (cmd) {
case JniCommand::JNI_CMD_INIT_WINDOW: {
LOGV("JNI_CMD_INIT_WINDOW");
_animating = true;
_window = _pendingWindow;
} break;
case JniCommand::JNI_CMD_TERM_WINDOW:
LOGV("JNI_CMD_TERM_WINDOW");
_animating = false;
break;
case JniCommand::JNI_CMD_RESUME:
LOGV("JNI_CMD_RESUME");
_appState = cmd;
break;
case JniCommand::JNI_CMD_PAUSE:
LOGV("JNI_CMD_PAUSE");
_appState = cmd;
break;
default:
break;
}
}
void JniNativeGlue::engineHandleCmd(JniCommand cmd) {
static bool isWindowInitialized = false;
// Handle CMD here if needed.
switch (cmd) {
case JniCommand::JNI_CMD_INIT_WINDOW: {
if (isWindowInitialized) {
return;
}
isWindowInitialized = true;
// cc::CustomEvent event;
// event.name = EVENT_RECREATE_WINDOW;
// event.args->ptrVal = reinterpret_cast<void*>(getWindowHandle());
ISystemWindowInfo info;
info.width = getWidth();
info.height = getHeight();
info.externalHandle = getWindowHandle();
BasePlatform* platform = cc::BasePlatform::getPlatform();
auto* windowMgr = platform->getInterface<SystemWindowManager>();
CC_ASSERT(windowMgr != nullptr);
windowMgr->createWindow(info);
events::WindowRecreated::broadcast(ISystemWindow::mainWindowId);
} break;
case JniCommand::JNI_CMD_TERM_WINDOW: {
events::WindowDestroy::broadcast(ISystemWindow::mainWindowId);
} break;
case JniCommand::JNI_CMD_RESUME: {
events::WindowChanged::broadcast(WindowEvent::Type::SHOW);
} break;
case JniCommand::JNI_CMD_PAUSE: {
events::WindowChanged::broadcast(WindowEvent::Type::HIDDEN);
} break;
case JniCommand::JNI_CMD_DESTROY: {
LOGV("APP_CMD_DESTROY");
events::WindowChanged::broadcast(WindowEvent::Type::CLOSE);
setRunning(false);
} break;
case JniCommand::JNI_CMD_LOW_MEMORY: {
events::LowMemory::broadcast();
break;
}
default:
break;
}
}
void JniNativeGlue::postExecCmd(JniCommand cmd) {
switch (cmd) {
case JniCommand::JNI_CMD_TERM_WINDOW: {
#if CC_PLATFORM == CC_PLATFORM_ANDROID
if (_window) {
ANativeWindow_release(_window);
}
#endif
_window = nullptr;
} break;
default:
break;
}
}
int32_t JniNativeGlue::getWidth() const {
int32_t width = 0;
if (_window) {
#if (CC_PLATFORM == CC_PLATFORM_ANDROID)
width = ANativeWindow_getWidth(_window);
#elif (CC_PLATFORM == CC_PLATFORM_OHOS)
width = NativeLayerHandle(_window, NativeLayerOps::GET_WIDTH);
#endif
}
return width;
}
int32_t JniNativeGlue::getHeight() const {
int32_t height = 0;
if (_window) {
#if (CC_PLATFORM == CC_PLATFORM_ANDROID)
height = ANativeWindow_getHeight(_window);
#elif (CC_PLATFORM == CC_PLATFORM_OHOS)
height = NativeLayerHandle(_window, NativeLayerOps::GET_HEIGHT);
#endif
}
return height;
}
} // namespace cc

View File

@@ -0,0 +1,142 @@
/****************************************************************************
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <functional>
#include <future>
#include <memory>
#include "base/Macros.h"
#include "platform/java/jni/glue/MessagePipe.h"
#if (CC_PLATFORM == CC_PLATFORM_ANDROID)
#include <android/asset_manager.h>
#include <android/native_window.h>
using ResourceManagerType = AAssetManager;
using NativeWindowType = ANativeWindow;
#elif (CC_PLATFORM == CC_PLATFORM_OHOS)
#include <native_layer.h>
#include <rawfile/resource_manager.h>
using ResourceManagerType = ResourceManager;
using NativeWindowType = NativeLayer;
#endif
using NativeActivity = void*; //jobject
using NativeEnv = void*; //jnienv
namespace cc {
class IEventDispatch;
class TouchEvent;
class CC_DLL JniNativeGlue {
public:
enum class JniCommand {
JNI_CMD_TERM_WINDOW = 0,
JNI_CMD_INIT_WINDOW,
JNI_CMD_RESUME,
JNI_CMD_PAUSE,
JNI_CMD_DESTROY,
JNI_CMD_LOW_MEMORY,
JNI_CMD_UNKNOW,
};
virtual ~JniNativeGlue();
static JniNativeGlue* getInstance();
virtual void start(int argc, const char** argv);
void setWindowHandle(NativeWindowType* window);
NativeWindowType* getWindowHandle();
void setActivityGetter(std::function<NativeActivity(void)>);
void* getActivity();
void setEnvGetter(std::function<NativeEnv(void)>);
void* getEnv();
void setResourceManager(ResourceManagerType* resourceManager);
ResourceManagerType* getResourceManager();
void setSdkVersion(int sdkVersion);
int getSdkVersion() const;
void setObbPath(const std::string& path);
std::string getObbPath() const;
bool isRunning() const;
void setRunning(bool isRunning);
void waitRunning();
void flushTasksOnGameThread() const;
struct CommandMsg {
JniCommand cmd;
std::function<void()> callback;
};
void writeCommandAsync(JniCommand cmd);
void writeCommandSync(JniCommand cmd);
int readCommand(CommandMsg* msg);
int readCommandWithTimeout(CommandMsg* cmd, int delayMS);
void onPause();
void onResume();
void onLowMemory();
bool isPause() const;
void execCommand();
int32_t getWidth() const;
int32_t getHeight() const;
bool isAnimating() const { return _animating; }
private:
void preExecCmd(JniCommand cmd);
void engineHandleCmd(JniCommand cmd);
void postExecCmd(JniCommand cmd);
bool _running{false};
int _sdkVersion{0};
bool _animating{false};
std::promise<void> _threadPromise;
std::string _obbPath;
ResourceManagerType* _resourceManager{nullptr};
NativeWindowType* _window{nullptr};
NativeWindowType* _pendingWindow{nullptr};
JniCommand _appState{JniCommand::JNI_CMD_UNKNOW};
IEventDispatch* _eventDispatcher{nullptr};
std::unique_ptr<MessagePipe> _messagePipe{nullptr};
std::function<NativeEnv(void)> _envGetter;
std::function<NativeActivity(void)> _activityGetter;
};
} // namespace cc
#define JNI_NATIVE_GLUE() cc::JniNativeGlue::getInstance()

View File

@@ -0,0 +1,89 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "platform/java/jni/glue/MessagePipe.h"
#include <fcntl.h>
#include <unistd.h>
#include "platform/java/jni/log.h"
//#include <android/log.h>
//#include "platform/android/jni/JniCocosActivity.h"
namespace cc {
MessagePipe::MessagePipe() {
int messagePipe[2] = {0};
if (pipe(messagePipe)) {
LOGV("Can not create pipe: %s", strerror(errno));
}
_pipeRead = messagePipe[0];
_pipeWrite = messagePipe[1];
if (fcntl(_pipeRead, F_SETFL, O_NONBLOCK) < 0) {
LOGV("Can not make pipe read to non blocking mode.");
}
}
MessagePipe::~MessagePipe() {
close(_pipeRead);
close(_pipeWrite);
}
void MessagePipe::writeCommand(int8_t cmd) const {
write(_pipeWrite, &cmd, sizeof(cmd));
}
int MessagePipe::readCommand(int8_t &cmd) const {
return read(_pipeRead, &cmd, sizeof(cmd));
}
int MessagePipe::readCommandWithTimeout(void *msg, int32_t size, int delayMS) {
if (delayMS > 0) {
static fd_set fdSet;
static timeval timeout;
timeout = {delayMS / 1000, (delayMS % 1000) * 1000};
FD_ZERO(&fdSet);
FD_SET(_pipeRead, &fdSet);
auto ret = select(_pipeRead + 1, &fdSet, nullptr, nullptr, &timeout);
if (ret < 0) {
LOGV("failed to run select(..): %s\n", strerror(errno));
return ret;
}
if (ret == 0) {
return 0;
}
}
return readCommand(msg, size);
}
void MessagePipe::writeCommand(void *msg, int32_t size) const {
write(_pipeWrite, msg, size);
}
int MessagePipe::readCommand(void *msg, int32_t size) const {
return read(_pipeRead, msg, size);
}
} // namespace cc

View File

@@ -0,0 +1,48 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <iostream>
#include "base/Macros.h"
namespace cc {
class CC_DLL MessagePipe {
public:
MessagePipe();
~MessagePipe();
void writeCommand(int8_t cmd) const;
int readCommand(int8_t &cmd) const;
void writeCommand(void *msg, int32_t size) const;
int readCommand(void *msg, int32_t size) const;
int readCommandWithTimeout(void *msg, int32_t size, int delayMS);
private:
int _pipeRead = 0;
int _pipeWrite = 0;
};
} // namespace cc

View File

@@ -0,0 +1,37 @@
/****************************************************************************
Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#define JNI_IMP_LOG_TAG "JniImp"
#if (CC_PLATFORM == CC_PLATFORM_ANDROID)
#include <android/log.h>
#define LOGV(...) __android_log_print(ANDROID_LOG_INFO, "CocosActivity JNI", __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, JNI_IMP_LOG_TAG, __VA_ARGS__)
#elif (CC_PLATFORM == CC_PLATFORM_OHOS)
#include <hilog/log.h>
#define LOGV(...) HILOG_INFO(LOG_APP, __VA_ARGS__)
#define LOGD(...)
#endif