OpenCAX/entry/src/main/cpp/NativeEGLOCCT/NativeManager.cpp

380 lines
17 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* 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 "NativeManager.h"
#include <ace/xcomponent/native_interface_xcomponent.h>
#include <cstdint>
#include <cstdio>
#include <hilog/log.h>
#include <string>
#include "arkui/native_node.h"
#include "arkui/native_node_napi.h"
#include "arkui/native_interface.h"
#include "common.h"
#include <map>
#define COLUMN_MARGIN 10
#define XC_WIDTH 800
#define XC_HEIGHT 600
#define ARG_CNT 2
namespace NativeOpenCAX {
// [Start plugin_manager_cpp]
// plugin_manager.cpp
std::unordered_map<std::string, ArkUI_NodeHandle> NativeManager::nodeHandleMap_;
std::unordered_map<void *, OH_ArkUI_SurfaceCallback *> NativeManager::callbackMap_;
std::unordered_map<void *, OH_ArkUI_SurfaceHolder *> NativeManager::surfaceHolderMap_;
ArkUI_AccessibilityProvider *NativeManager::provider_ = nullptr;
ArkUI_NativeNodeAPI_1 *nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1 *>(
OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1"));
// [StartExclude plugin_manager_cpp]
NativeManager NativeManager::pluginManager_;
OH_NativeXComponent_Callback NativeManager::callback_;
ArkUI_NodeHandle xc;
int32_t NativeManager::hasDraw_ = 0;
int32_t NativeManager::hasChangeColor_ = 0;
static std::map<int64_t, std::shared_ptr<NativeRenderThread>> renderThreadMap;
static std::mutex mapMutex;
NativeManager::~NativeManager() {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "~NativeManager");
nativeXComponentMap_.clear();
int64_t id = 0;
std::lock_guard<std::mutex> lock(mapMutex);
if (renderThreadMap.find(id) != renderThreadMap.end()) {
renderThreadMap[id]->stop();
renderThreadMap.erase(id);
}
for (auto iter = pluginManagerMap_.begin(); iter != pluginManagerMap_.end(); ++iter) {
if (iter->second != nullptr) {
delete iter->second;
iter->second = nullptr;
}
}
pluginManagerMap_.clear();
}
// Surface回调事件
//void OnSurfaceCreatedNative(OH_ArkUI_SurfaceHolder *holder) {
// auto window = OH_ArkUI_XComponent_GetNativeWindow(holder); // 获取native window
// auto eglCore = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
// eglCore->EglContextInit(window, 800, 600);
//}
//void OnSurfaceChangedNative(OH_ArkUI_SurfaceHolder *holder, uint64_t width, uint64_t height) {
// EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
// render->UpdateSize(width, height); // 设置绘制区域大小
// //render->Draw(NativeManager::hasDraw_); // 绘制五角星
//}
//void OnSurfaceDestroyedNative(OH_ArkUI_SurfaceHolder *holder) {
// OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onBind", "on destroyed");
// EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
// render->Release(); // 销毁eglSurface相关资源
//}
//void OnSurfaceShowNative(OH_ArkUI_SurfaceHolder *holder) {
// OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on surface show");
//}
//void OnSurfaceHideNative(OH_ArkUI_SurfaceHolder *holder) {
// OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on surface hide");
//}
//void OnFrameCallbackNative(ArkUI_NodeHandle node, uint64_t timestamp, uint64_t targetTimestamp) {
// if (!NativeManager::surfaceHolderMap_.count(node)) {
// return;
// }
// static uint64_t count = 0;
// count++;
// // 在头文件plugin_manager.h中定义FRAME_COUNT的值为50
// if (count % FRAME_COUNT == 0) {
// OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "OnFrameCallback count = %{public}ld", count);
// }
//}
void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) {
// [StartExclude plugin_on_surface_created]
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB");
int32_t ret;
char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
return;
}
std::string id(idStr);
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB id=%{public}s",
id.c_str());
// [EndExclude plugin_on_surface_created]
// 初始化环境与绘制背景
auto *pluginManger = NativeManager::GetInstance();
pluginManger->OnSurfaceCreated(component, window);
}
void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window) {
// [StartExclude plugin_on_surface_changed]
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceChangedCB");
int32_t ret;
char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
return;
}
std::string id(idStr);
// [EndExclude plugin_on_surface_changed]
auto *pluginManger = NativeManager::GetInstance();
// 封装OnSurfaceChanged方法
pluginManger->OnSurfaceChanged(component, window);
}
void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window) {
// [StartExclude plugin_on_surface_destroyed]
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceDestroyedCB");
int32_t ret;
char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
return;
}
std::string id(idStr);
// [EndExclude plugin_on_surface_destroyed]
auto *pluginManger = NativeManager::GetInstance();
pluginManger->OnSurfaceDestroyed(component, window);
}
//NativeManager回调
void NativeManager::OnSurfaceCreated(OH_NativeXComponent *component, void *window) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceCreated");
if (!window) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native",
"ERROR: window is NULL in OnSurfaceCreated!");
return;
}
OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
int64_t id = 0;
std::lock_guard<std::mutex> lock(mapMutex);
if (renderThreadMap.find(id) == renderThreadMap.end()) {
auto renderThread = std::make_shared<NativeRenderThread>();
renderThreadMap[id] = renderThread;
renderThread->start(reinterpret_cast<OHNativeWindow*>(window));
}
}
void NativeManager::OnSurfaceDestroyed(OH_NativeXComponent *component, void *window) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceDestroyed");
int64_t id = 0;
{
std::lock_guard<std::mutex> lock(mapMutex);
if (renderThreadMap.find(id) != renderThreadMap.end()) {
renderThreadMap[id]->stop();
renderThreadMap.erase(id);
}
}
}
void NativeManager::OnSurfaceChanged(OH_NativeXComponent *component, void *window) {
OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
int64_t id = 0;
{
std::lock_guard<std::mutex> lock(mapMutex);
if (renderThreadMap.find(id) != renderThreadMap.end()) {
renderThreadMap[id]->resizeWindow(width_, height_);
}
}
}
void onEvent(ArkUI_NodeEvent *event) {
auto eventType = OH_ArkUI_NodeEvent_GetEventType(event); // 获取组件事件类型
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on event");
if (eventType == NODE_TOUCH_EVENT) {
ArkUI_NodeHandle handle = OH_ArkUI_NodeEvent_GetNodeHandle(event); // 获取触发该事件的组件对象
auto holder = NativeManager::surfaceHolderMap_[handle];
EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on touch");
}
}
static std::string value2String(napi_env env, napi_value value) {
size_t stringSize = 0;
napi_get_value_string_utf8(env, value, nullptr, 0, &stringSize);
std::string valueString;
valueString.resize(stringSize);
napi_get_value_string_utf8(env, value, &valueString[0], stringSize + 1, &stringSize);
return valueString;
}
// XComponent回调事件
NativeManager::NativeManager() {
callback_.OnSurfaceCreated = OnSurfaceCreatedCB;
callback_.OnSurfaceChanged = OnSurfaceChangedCB;
callback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
}
// 创建节点组件
ArkUI_NodeHandle CreateNodeHandle(const std::string &tag) {
// 创建Node也名创建ROW Column等容器
ArkUI_NodeHandle nodeHandel = nodeAPI->createNode(ARKUI_NODE_RELATIVE_CONTAINER);
// 节点默认宽度or高度
ArkUI_NumberValue nodeSizeData[] = {800, 600};
ArkUI_NumberValue nodeMarginData[] = {{.u32 = 15}, {.f32 = 15}};
// ArkUI_AttributeItem
// 参数1:指向数值数组
// 参数2:数组元素个数
// 参数3:属性名(可隐藏)
ArkUI_AttributeItem nodeSizeItem = {nodeSizeData, 2};
ArkUI_AttributeItem nodeMarginItem = {nodeMarginData, 2};
// 设置Node宽度or高度
nodeAPI->setAttribute(nodeHandel, NODE_SIZE, &nodeSizeItem);
nodeAPI->setAttribute(nodeHandel, NODE_MARGIN, &nodeMarginItem);
// 创建XComponent组件
// 组件类型Item
ArkUI_NumberValue comTypeData[] = {ARKUI_XCOMPONENT_TYPE_SURFACE};
ArkUI_AttributeItem comTypeItem = {comTypeData, 1};
// 组件ID Item
ArkUI_AttributeItem comIdItem = {.string = tag.c_str(), .size = 1};
// 组件Surface Size
ArkUI_NumberValue surfaceSizeData[] = {800, 600};
ArkUI_AttributeItem surfaceSizeItem = {surfaceSizeData, 2};
// 创建组件
xc = nodeAPI->createNode(ARKUI_NODE_XCOMPONENT);
// 设置XComponent组件属性
nodeAPI->setAttribute(xc, NODE_XCOMPONENT_TYPE, &comTypeItem);
nodeAPI->setAttribute(xc, NODE_XCOMPONENT_ID, &comIdItem);
nodeAPI->setAttribute(xc, NODE_XCOMPONENT_SURFACE_SIZE, &surfaceSizeItem);
// 焦点设置
ArkUI_NumberValue focusable[] = {1};
focusable[0].i32 = 1;
ArkUI_AttributeItem focusableItem = {focusable, 1};
nodeAPI->setAttribute(xc, NODE_FOCUSABLE, &focusableItem);
// 设置组件Size
nodeAPI->setAttribute(xc, NODE_WIDTH, &surfaceSizeItem);
nodeAPI->setAttribute(xc, NODE_HEIGHT, &surfaceSizeItem);
// 节点ID
ArkUI_AttributeItem nodeIdItem = {.string = "ndkxcomponent", .size = 1};
nodeAPI->setAttribute(xc, NODE_ID, &nodeIdItem);
auto *nativeXComponent = OH_NativeXComponent_GetNativeXComponent(xc);
if (!nativeXComponent) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "GetNativeXComponent error");
return nodeHandel;
}
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeManager", "GetNativeXComponent success");
// 注册XComponent回调函数
OH_NativeXComponent_RegisterCallback(nativeXComponent, &NativeManager::callback_);
// 组件类型
auto comTypeRet = nodeAPI->getAttribute(xc, NODE_XCOMPONENT_TYPE);
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeManager", "com type: %{public}d",
comTypeRet->value[0].i32);
// 组件ID
auto comIdRet = nodeAPI->getAttribute(xc, NODE_XCOMPONENT_ID);
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeManager", "com id: %{public}s", comIdRet->string);
// 增加组件到节点
nodeAPI->addChild(nodeHandel, xc);
return nodeHandel;
}
// Native侧创建Node
napi_value NativeManager::createNativeNode(napi_env env, napi_callback_info info) {
if ((env == nullptr) || (info == nullptr)) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "CreateNativeNode env or info is null");
return nullptr;
}
size_t argCnt = 2;
napi_value args[2] = {nullptr, nullptr};
if (napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr) != napi_ok) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "CreateNativeNode napi_get_cb_info failed");
}
if (argCnt != ARG_CNT) {
napi_throw_type_error(env, NULL, "Wrong number of arguments");
return nullptr;
}
ArkUI_NodeContentHandle _nodeContentHandle = nullptr;
// 获取ArkTS侧创建的NodeContent对象映射到Native侧的
OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &_nodeContentHandle);
// 查询指定的模块接口名
nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1 *>(
OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1"));
// 节点名
std::string node_id = value2String(env, args[1]);
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeManager", "CreateNativeNode_Node_ID:", node_id.c_str());
// 设置用户自定义数据
int32_t ret = OH_ArkUI_NodeContent_SetUserData(_nodeContentHandle, new std::string(node_id));
if (ret != ARKUI_ERROR_CODE_NO_ERROR) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "setUserData failed error=%{public}d", ret);
}
if (nodeAPI != nullptr && nodeAPI->createNode != nullptr && nodeAPI->addChild != nullptr) {
auto nodeContentEvent = [](ArkUI_NodeContentEvent *event) {
// 获取Node连接事件的对应Node的Handle
ArkUI_NodeContentHandle handle = OH_ArkUI_NodeContentEvent_GetNodeContentHandle(event);
// 获取对应Handle的UserData
std::string *userDate = reinterpret_cast<std::string *>(OH_ArkUI_NodeContent_GetUserData(handle));
if (OH_ArkUI_NodeContentEvent_GetEventType(event) == NODE_CONTENT_EVENT_ON_ATTACH_TO_WINDOW) {
ArkUI_NodeHandle testNode;
if (userDate) {
testNode = CreateNodeHandle(*userDate);
delete userDate;
userDate = nullptr;
} else {
testNode = CreateNodeHandle("noUserData");
}
// 向NodeContent中添加子组件
OH_ArkUI_NodeContent_AddNode(handle, testNode);
}
};
OH_ArkUI_NodeContent_RegisterCallback(_nodeContentHandle, nodeContentEvent);
}
return nullptr;
}
//设置期望帧率
napi_value NativeManager::SetFrameRate(napi_env env, napi_callback_info info) {
size_t argc = 4;
napi_value args[4] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
std::string nodeId = value2String(env, args[0]);
auto node = nodeHandleMap_[nodeId];
int32_t min = 0;
napi_get_value_int32(env, args[FIRST_ARG], &min);
int32_t max = 0;
napi_get_value_int32(env, args[SECOND_ARG], &max);
int32_t expected = 0;
napi_get_value_int32(env, args[THIRD_ARG], &expected);
OH_NativeXComponent_ExpectedRateRange range = {.min = min, .max = max, .expected = expected};
OH_ArkUI_XComponent_SetExpectedFrameRateRange(node, range); // 设置期望帧率
return nullptr;
}
napi_value NativeManager::SetNeedSoftKeyboard(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2] = {nullptr};
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
std::string nodeId = value2String(env, args[0]);
ArkUI_NodeHandle node;
if (nodeHandleMap_.find(nodeId) == nodeHandleMap_.end()) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "SetNeedSoftKeyboard", "nodeId not exit error");
return nullptr;
}
node = nodeHandleMap_[nodeId];
bool needSoftKeyboard = false;
napi_get_value_bool(env, args[1], &needSoftKeyboard);
OH_ArkUI_XComponent_SetNeedSoftKeyboard(node, needSoftKeyboard); // 设置是否需要软键盘
return nullptr;
}
napi_value NativeManager::NapiLoadModel(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
std::string path = value2String(env, args[0]);
int64_t id = 0;
{
std::lock_guard<std::mutex> lock(mapMutex);
if (renderThreadMap.find(id) != renderThreadMap.end()) {
renderThreadMap[id]->loadModel(std::string(path));
}
}
return nullptr;
}
} // namespace NativeOpenCAX