1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "../manager/plugin_manager.h"
16 #include "common/common.h"
17 #include "xcomponent_lifecycle_test.h"
18 #include "render/EGLRender.h"
19 #include <arkui/native_node.h>
20 #include <arkui/native_node_napi.h>
21 #include "napi/native_api.h"
22 #include <arkui/native_interface.h>
23 #include <hilog/log.h>
24 #include <ace/xcomponent/native_interface_xcomponent.h>
25 #include <unordered_map>
26 #include <string>
27
28 namespace ArkUICapiTest {
29 static std::unordered_map<OH_ArkUI_SurfaceHolder*, EGLRender*> Renders;
30 static ArkUI_NativeNodeAPI_1* nodeAPI;
31 ArkUI_NodeHandle xcomponent_ = nullptr;
32 ArkUI_NodeContentHandle nodeContentHandle_ = nullptr;
33 OH_ArkUI_SurfaceHolder* holder_ = nullptr;
34 OH_ArkUI_SurfaceCallback* callback_;
35 OH_ArkUI_SurfaceCallback* tempCallback_;
36 uint64_t width_ = 0;
37 uint64_t height_ = 0;
38
value2String(napi_env env,napi_value value)39 static std::string value2String(napi_env env, napi_value value){
40 size_t stringSize = 0;
41 napi_get_value_string_utf8(env, value, nullptr, 0, &stringSize);
42 std::string valueString;
43 valueString.resize(stringSize);
44 napi_get_value_string_utf8(env, value, &valueString[0], stringSize+1, &stringSize);
45 return valueString;
46 }
47
onEvent(ArkUI_NodeEvent * event)48 void onEvent(ArkUI_NodeEvent* event) {
49 auto eventType = OH_ArkUI_NodeEvent_GetEventType(event);
50 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "wds on event");
51 if (eventType == NODE_TOUCH_EVENT) {
52 auto *uiInputEvent = OH_ArkUI_NodeEvent_GetInputEvent(event);
53 float x = OH_ArkUI_PointerEvent_GetX(uiInputEvent);
54 float y = OH_ArkUI_PointerEvent_GetY(uiInputEvent);
55 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "wds on touch");
56 }
57 };
58
OnSurfaceCreatedCB(OH_ArkUI_SurfaceHolder * holder)59 void OnSurfaceCreatedCB(OH_ArkUI_SurfaceHolder* holder)
60 {
61 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "CYC_OnSurfaceCreatedCB holder %{public}p", holder);
62 void* window = (void*)OH_ArkUI_XComponent_GetNativeWindow(holder_);
63 auto render = Renders[holder_];
64 if (window && render) {
65 render->SetUpEGLContext(window, 0);
66 int32_t width;
67 int32_t height;
68 auto *nativeWindow = reinterpret_cast<OHNativeWindow *>(window);
69 OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, GET_BUFFER_GEOMETRY,&width, &height);
70 render->SetEGLWindowSize(width, height);
71 }
72 }
73
OnSurfaceChangedCB(OH_ArkUI_SurfaceHolder * holder,uint64_t width,uint64_t height)74 void OnSurfaceChangedCB(OH_ArkUI_SurfaceHolder* holder, uint64_t width, uint64_t height)
75 {
76 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "CYC_OnSurfaceChangedCB width %{public}d height %{public}d", width, height);
77 width_ = width;
78 height_ = height;
79 auto render = Renders[holder_];
80 if (render != nullptr) {
81 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "CYC_OnSurfaceChangedCB 1");
82 render->SetEGLWindowSize(width, height);
83 render->DrawStar();
84 }
85 }
86
OnSurfaceDestroyedCB(OH_ArkUI_SurfaceHolder * holder)87 void OnSurfaceDestroyedCB(OH_ArkUI_SurfaceHolder* holder)
88 {
89 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "CYC_OnSurfaceDestroyedCB");
90 }
91
removeSurfaceCallback(napi_env env,napi_callback_info info)92 napi_value XComponentLifeCycleTest::removeSurfaceCallback(napi_env env, napi_callback_info info) {
93 auto status = OH_ArkUI_SurfaceHolder_RemoveSurfaceCallback(holder_, callback_);
94 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_removeSurfaceCallback status %{public}d", status);
95
96 napi_value statusCode;
97 napi_status ret = napi_create_int32(env, status, &(statusCode));
98
99 return statusCode;
100 }
101
setUserData(napi_env env,napi_callback_info info)102 napi_value XComponentLifeCycleTest::setUserData(napi_env env, napi_callback_info info) {
103 auto status = OH_ArkUI_SurfaceHolder_SetUserData(holder_, new std::string("Hello World"));
104 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_setUserData status %{public}d data %{public}s", status, "Hello World");
105 return nullptr;
106 }
107
getUserData(napi_env env,napi_callback_info info)108 napi_value XComponentLifeCycleTest::getUserData(napi_env env, napi_callback_info info) {
109 napi_value napiStr;
110 std::string* data = (std::string*)OH_ArkUI_SurfaceHolder_GetUserData(holder_);
111 if (data) {
112 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_getUserData data %{public}s", data->c_str());
113 napi_create_string_latin1(env, data->c_str(), data->size(), &napiStr);
114 return napiStr;
115 }
116 return nullptr;
117 }
118
CreateNodeHandlePre()119 ArkUI_NodeHandle CreateNodeHandlePre() {
120 ArkUI_NodeHandle handle = nodeAPI->createNode(ARKUI_NODE_XCOMPONENT_TEXTURE);
121 //获取SurfaceHolder
122 holder_ = OH_ArkUI_SurfaceHolder_Create(handle);
123 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_CreateNodeHandlePre create surface holder %{public}p", holder_);
124 callback_ = OH_ArkUI_SurfaceCallback_Create();
125
126 OH_ArkUI_SurfaceCallback_SetSurfaceCreatedEvent(callback_, OnSurfaceCreatedCB);
127 OH_ArkUI_SurfaceCallback_SetSurfaceChangedEvent(callback_, OnSurfaceChangedCB);
128 OH_ArkUI_SurfaceCallback_SetSurfaceDestroyedEvent(callback_, OnSurfaceDestroyedCB);
129
130 //往SurfaceHolder里添加callback
131 if (holder_) {
132 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_preCreate get holder");
133 OH_ArkUI_SurfaceHolder_AddSurfaceCallback(holder_, callback_);
134 if (!Renders.count(holder_)) {
135 Renders[holder_] = new EGLRender();
136 auto render = Renders[holder_];
137 }
138 }
139 // 设置AutoInitial为false
140 if (OH_ArkUI_XComponent_SetAutoInitialize(handle, false) != ARKUI_ERROR_CODE_NO_ERROR) {
141 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "CYC_SetAutoInitialize failed.");
142 }
143
144 // 获取isINitialized的值
145 bool isInitialized = false;
146 if (OH_ArkUI_XComponent_IsInitialized(handle, &isInitialized) != ARKUI_ERROR_CODE_NO_ERROR) {
147 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "GetIsInitialized failed.");
148 } else {
149 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "GetIsInitialized = %{public}d", isInitialized);
150 }
151
152 //添加事件监听,返回成功码 0
153 auto ret = nodeAPI->addNodeEventReceiver(handle, onEvent);
154 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_addNodeEventReceiver ret=%{public}d", ret);
155
156 // 用C接口注册touch事件,返回成功码 0
157 ret = nodeAPI->registerNodeEvent(handle, NODE_TOUCH_EVENT, 0, nullptr);
158 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_registerNodeEvent ret=%{public}d", ret);
159 ArkUI_NumberValue value[] = {{.i32 = static_cast<int>(true)}};
160 ArkUI_AttributeItem item = {value, 1};
161 auto ec = nodeAPI->setAttribute(handle, NODE_XCOMPONENT_ENABLE_ANALYZER, &item);
162 // 返回错误码
163 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_set attribute ret=%{public}d", ec);
164 xcomponent_ = handle;
165 return handle;
166 }
167
CreateNodeHandle(const std::string & tag)168 ArkUI_NodeHandle CreateNodeHandle(const std::string &tag) {
169 ArkUI_NodeHandle handle = nodeAPI->createNode(ARKUI_NODE_XCOMPONENT);
170
171 //获取SurfaceHolder
172 holder_ = OH_ArkUI_SurfaceHolder_Create(handle);
173 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_CreateNodeHandle create surface holder %{public}p", holder_);
174
175 OHNativeWindow* window = OH_ArkUI_XComponent_GetNativeWindow(holder_);
176 if (window) {
177 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_GetNativeWindow success");
178 }
179
180 callback_ = OH_ArkUI_SurfaceCallback_Create();
181 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_CreateNodeHandle callback_ %{public}p", callback_);
182
183 OH_ArkUI_SurfaceCallback_SetSurfaceCreatedEvent(callback_, OnSurfaceCreatedCB);
184 OH_ArkUI_SurfaceCallback_SetSurfaceChangedEvent(callback_, OnSurfaceChangedCB);
185 OH_ArkUI_SurfaceCallback_SetSurfaceDestroyedEvent(callback_, OnSurfaceDestroyedCB);
186 //往SurfaceHolder里添加callback
187 if (holder_) {
188 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_CreateNodeHandle get holder");
189 OH_ArkUI_SurfaceHolder_AddSurfaceCallback(holder_, callback_);
190 if (!Renders.count(holder_)) {
191 Renders[holder_] = new EGLRender();
192 auto render = Renders[holder_];
193 }
194 }
195 //设置AutoInitial为false
196 if (OH_ArkUI_XComponent_SetAutoInitialize(handle, true) != ARKUI_ERROR_CODE_NO_ERROR) {
197 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "CYC_SetAutoInitialize failed.");
198 }
199 // //获取isINitialized的值
200 bool isInitialized = false;
201 if (OH_ArkUI_XComponent_IsInitialized(handle, &isInitialized) != ARKUI_ERROR_CODE_NO_ERROR) {
202 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "GetIsInitialized failed.");
203 } else {
204 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "GetIsInitialized = %{public}d", isInitialized);
205 }
206
207 ArkUI_NumberValue value[] = {{.i32 = static_cast<int>(true)}};
208 ArkUI_AttributeItem item = {value, 1};
209 auto ec = nodeAPI->setAttribute(handle, NODE_XCOMPONENT_ENABLE_ANALYZER, &item);
210 ArkUI_NumberValue value1[] = {{.u32 = 0x12345678}};
211 ArkUI_AttributeItem item1 = {value1, 1};
212 nodeAPI->setAttribute(handle, NODE_BACKGROUND_COLOR, &item1);
213 // 返回错误码
214 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_set attribute ret=%{public}d", ec);
215 xcomponent_ = handle;
216 return handle;
217 }
218
createNativeNode(napi_env env,napi_callback_info info)219 napi_value XComponentLifeCycleTest::createNativeNode(napi_env env, napi_callback_info info)
220 {
221 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "createNativeNode", "createNativeNode");
222 size_t argCnt = 3;
223 napi_value args[3] = { nullptr, nullptr, nullptr};
224 napi_get_cb_info(env, info, &argCnt, args, nullptr, nullptr);
225
226 if (argCnt != 3) {
227 napi_throw_type_error(env, NULL, "Wrong number of arguments");
228 return nullptr;
229 }
230
231 nodeContentHandle_ = nullptr;
232 OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &nodeContentHandle_);
233 nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1*> (
234 OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1")
235 );
236
237 std::string tag = value2String(env, args[1]);
238 if (tag == "preCreate") {
239 xcomponent_ = CreateNodeHandlePre();
240 } else {
241 xcomponent_ = CreateNodeHandle("cyc");
242 }
243 return nullptr;
244 }
245
initialize(napi_env env,napi_callback_info info)246 napi_value XComponentLifeCycleTest::initialize(napi_env env, napi_callback_info info) {
247 auto status = OH_ArkUI_XComponent_Initialize(xcomponent_);
248 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "CYC_Initialize. Code: %{public}d", status);
249
250 napi_value statusCode;
251 napi_status ret = napi_create_int32(env, status, &(statusCode));
252
253 return statusCode;
254 }
255
finalize(napi_env env,napi_callback_info info)256 napi_value XComponentLifeCycleTest::finalize(napi_env env, napi_callback_info info) {
257 auto status = OH_ArkUI_XComponent_Finalize(xcomponent_);
258 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "CYC_Finalize. Code: %{public}d", status);
259
260 napi_value statusCode;
261 napi_status ret = napi_create_int32(env, status, &(statusCode));
262
263 return statusCode;
264 }
265
attachToMainTree(napi_env env,napi_callback_info info)266 napi_value XComponentLifeCycleTest::attachToMainTree(napi_env env, napi_callback_info info) {
267 OH_ArkUI_NodeContent_AddNode(nodeContentHandle_, xcomponent_);
268 return nullptr;
269 }
270
detachFromMainTree(napi_env env,napi_callback_info info)271 napi_value XComponentLifeCycleTest::detachFromMainTree(napi_env env, napi_callback_info info) {
272 OH_ArkUI_NodeContent_RemoveNode(nodeContentHandle_, xcomponent_);
273 return nullptr;
274 }
275
dispose(napi_env env,napi_callback_info info)276 napi_value XComponentLifeCycleTest::dispose(napi_env env, napi_callback_info info) {
277 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "CYC_CNode dispose");
278 OH_ArkUI_NodeContent_RemoveNode(nodeContentHandle_, xcomponent_);
279 nodeAPI->disposeNode(xcomponent_);
280 xcomponent_ = nullptr;
281 if (holder_) {
282 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "jyy CYC_SurfaceHolder dispose");
283 OH_ArkUI_SurfaceHolder_Dispose(holder_);
284 }
285 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onbind", "CYC_dispose callback_ %{public}p", callback_);
286 if (callback_) {
287 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "CYC_SurfaceCallback dispose 2");
288 OH_ArkUI_SurfaceCallback_Dispose(callback_);
289 }
290 if (tempCallback_) {
291 OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "XComponent_Native", "CYC_SurfaceCallback dispose");
292 OH_ArkUI_SurfaceCallback_Dispose(tempCallback_);
293 }
294 return nullptr;
295 }
296
297 } // ArkUICapiTest
298