1/*
2 * Copyright (C) 2024 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
16#include "test_runner.h"
17
18#include <dlfcn.h>
19#include <memory>
20#include <string_view>
21
22#include "napi/native_api.h"
23#include "napi/native_node_api.h"
24
25#include <base/containers/array_view.h>
26
27#include <core/intf_engine.h>
28#include <core/ecs/intf_system_graph_loader.h>
29#include <core/engine_info.h>
30#include <core/implementation_uids.h>
31#include <core/io/intf_file_manager.h>
32#include <core/namespace.h>
33#include <core/os/intf_platform.h>
34#include <core/plugin/intf_plugin_register.h>
35#include <core/property/intf_property_handle.h>
36
37#include <meta/interface/intf_meta_object_lib.h>
38#include <meta/interface/intf_task_queue_registry.h>
39#include <meta/interface/intf_task_queue.h>
40#include <meta/interface/intf_object.h>
41#include <meta/interface/intf_object_registry.h>
42#include <meta/interface/intf_task_queue.h>
43#include <meta/base/shared_ptr.h>
44#include <meta/base/interface_macros.h>
45#include <meta/api/make_callback.h>
46#include <meta/ext/object.h>
47
48#include <scene_plugin/namespace.h>
49#include <scene_plugin/interface/intf_scene.h>
50#include <scene_plugin/interface/intf_ecs_scene.h>
51#include <scene_plugin/interface/intf_mesh.h>
52#include <scene_plugin/interface/intf_material.h>
53#include <scene_plugin/api/scene_uid.h>
54
55#include "ability.h"
56#include "data_ability_helper.h"
57#include "napi_base_context.h"
58
59#include <render/implementation_uids.h>
60#include <render/gles/intf_device_gles.h>
61#include <render/intf_renderer.h>
62#include <render/intf_render_context.h>
63
64#include "3d_widget_adapter_log.h"
65#include "ohos/texture_layer.h"
66
67CORE_BEGIN_NAMESPACE()
68IPluginRegister& (*GetPluginRegister) () = nullptr;
69
70void (*CreatePluginRegistry) (
71    const struct PlatformCreateInfo& platformCreateInfo) = nullptr;
72
73bool (*IsDebugBuild) () = nullptr;
74
75BASE_NS::string_view (*GetVersion) () = nullptr;
76CORE_END_NAMESPACE()
77
78META_BEGIN_NAMESPACE()
79OHOS::Render3D::HapInfo GetHapInfo()
80{
81    std::shared_ptr<OHOS::AbilityRuntime::ApplicationContext> context =
82        OHOS::AbilityRuntime::ApplicationContext::GetApplicationContext();
83    if (!context) {
84        WIDGET_LOGE("Failed to get application context.");
85        return {};
86    }
87    auto resourceManager = context->GetResourceManager();
88    if (!resourceManager) {
89        WIDGET_LOGE("Failed to get resource manager.");
90        return {};
91    }
92    OHOS::Render3D::HapInfo hapInfo;
93    hapInfo.bundleName_ = resourceManager->bundleInfo.first;
94    hapInfo.moduleName_ = resourceManager->bundleInfo.second;
95
96    // hapPath
97    std::string hapPath = context->GetBundleCodeDir();
98    hapInfo.hapPath_ = hapPath + "/" + hapInfo.moduleName_ + ".hap";
99    WIDGET_LOGD("bundle %s, module %s, hapPath %s",
100        hapInfo.bundleName_.c_str(),
101        hapInfo.moduleName_.c_str(),
102        hapInfo.hapPath_.c_str());
103
104    return hapInfo;
105}
106
107using IntfPtr = META_NS::SharedPtrIInterface;
108using IntfWeakPtr = META_NS::WeakPtrIInterface;
109
110struct EngineInstance {
111    void *libHandle = nullptr;
112    BASE_NS::shared_ptr<RENDER_NS::IRenderContext> renderContext;
113    BASE_NS::shared_ptr<CORE_NS::IEngine> engine;
114};
115
116static EngineInstance g_engineInstance;
117
118META_NS::ITaskQueue::Ptr engineThread;
119META_NS::ITaskQueue::Ptr ioThread;
120
121static constexpr BASE_NS::Uid ENGINE_THREAD { "2070e705-d061-40e4-bfb7-90fad2c280af" };
122static constexpr BASE_NS::Uid APP_THREAD { "b2e8cef3-453a-4651-b564-5190f8b5190d" };
123static constexpr BASE_NS::Uid IO_QUEUE { "be88e9a0-9cd8-45ab-be48-937953dc258f" };
124
125OHOS::Render3D::HapInfo hapInfo;
126
127template<typename T>
128bool LoadFunc(T &fn, const char *fName, void* handle)
129{
130    fn = reinterpret_cast<T>(dlsym(handle, fName));
131    if (fn == nullptr) {
132        WIDGET_LOGE("%s open %s", __func__, dlerror());
133        return false;
134    }
135    return true;
136}
137
138
139bool LoadEngineLib()
140{
141    if (g_engineInstance.libHandle != nullptr) {
142        WIDGET_LOGD("%s, already loaded", __func__);
143        return true;
144    }
145
146    #define TO_STRING(name) #name
147    #define LIB_NAME(name) TO_STRING(name)
148    constexpr std::string_view lib { "/system/lib/libAGPDLL.z.so" };
149    g_engineInstance.libHandle = dlopen(lib.data(), RTLD_LAZY);
150
151    if (g_engineInstance.libHandle == nullptr) {
152        WIDGET_LOGE("%s, open lib fail %s", __func__, dlerror());
153        return false;
154    }
155    #undef TO_STRING
156    #undef LIB_NAME
157
158    if (!(LOAD_FUNC(CORE_NS::CreatePluginRegistry,
159        "_ZN4Core20CreatePluginRegistryERKNS_18PlatformCreateInfoE")
160        && LOAD_FUNC(CORE_NS::GetPluginRegister, "_ZN4Core17GetPluginRegisterEv")
161        && LOAD_FUNC(CORE_NS::IsDebugBuild, "_ZN4Core12IsDebugBuildEv")
162        && LOAD_FUNC(CORE_NS::GetVersion, "_ZN4Core13GetVersionRevEv"))) {
163        return false;
164    }
165    #undef LOAD_FUNC
166
167    return true;
168}
169
170bool LoadPlugins(const CORE_NS::PlatformCreateInfo& platformCreateInfo)
171{
172    WIDGET_LOGD("LoadPlugins Begin lgp");
173    if (g_engineInstance.engine) {
174        return true;
175    }
176    if (!LoadEngineLib()) {
177        return false;
178    }
179    WIDGET_LOGD("load engine success!");
180    const BASE_NS::Uid DefaultPluginList[] { SCENE_NS::UID_SCENE_PLUGIN };
181
182    CORE_NS::CreatePluginRegistry(platformCreateInfo);
183    if (!CORE_NS::GetPluginRegister().LoadPlugins(DefaultPluginList)) {
184        WIDGET_LOGE("fail to load scene widget plugin");
185        return false;
186    }
187    WIDGET_LOGD("load plugin success");
188    return true;
189}
190
191bool InitEngine(CORE_NS::PlatformCreateInfo platformCreateInfo)
192{
193    if (g_engineInstance.engine) {
194        return true;
195    }
196    auto& tr = META_NS::GetTaskQueueRegistry();
197    auto& obr = META_NS::GetObjectRegistry();
198
199    engineThread = tr.GetTaskQueue(ENGINE_THREAD);
200    if (!engineThread) {
201        engineThread = obr.Create<META_NS::ITaskQueue>(META_NS::ClassId::ThreadedTaskQueue);
202        tr.RegisterTaskQueue(engineThread, ENGINE_THREAD);
203    }
204    ioThread = tr.GetTaskQueue(IO_QUEUE);
205    if (!ioThread) {
206        ioThread = obr.Create<META_NS::ITaskQueue>(META_NS::ClassId::ThreadedTaskQueue);
207        tr.RegisterTaskQueue(ioThread, IO_QUEUE);
208    }
209    return true;
210}
211
212bool LoadPluginsAndInit()
213{
214    WIDGET_LOGD("scene adapter loadPlugins");
215    hapInfo = GetHapInfo();
216
217    #define TO_STRING(name) #name
218    #define PLATFORM_PATH_NAME(name) TO_STRING(name)
219    CORE_NS::PlatformCreateInfo platformCreateInfo {
220        PLATFORM_PATH_NAME(PLATFORM_CORE_ROOT_PATH),
221        PLATFORM_PATH_NAME(PLATFORM_APP_ROOT_PATH),
222        PLATFORM_PATH_NAME(PLATFORM_APP_PLUGIN_PATH),
223        hapInfo.hapPath_.c_str(),
224        hapInfo.bundleName_.c_str(),
225        hapInfo.moduleName_.c_str()
226    };
227    #undef TO_STRING
228    #undef PLATFORM_PATH_NAME
229    if (!LoadPlugins(platformCreateInfo)) {
230        return false;
231    }
232
233    if (!InitEngine(platformCreateInfo)) {
234        return false;
235    }
236
237    return true;
238}
239
240void SetTest()
241{
242    LoadPluginsAndInit();
243    RegisterTestTypes();
244}
245
246void ResetTest()
247{
248    g_engineInstance.engine.reset();
249}
250META_END_NAMESPACE()
251
252