• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "cj_environment.h"
17 
18 #include <string>
19 #include <filesystem>
20 #include <mutex>
21 #include "cj_hilog.h"
22 #include "cj_invoker.h"
23 #ifdef __OHOS__
24 #include <dlfcn.h>
25 #endif
26 #include "dynamic_loader.h"
27 #ifdef WITH_EVENT_HANDLER
28 #include "event_handler.h"
29 #endif
30 
31 #ifdef APP_USE_ARM64
32 #define APP_LIB_NAME "arm64"
33 #elif defined(APP_USE_ARM)
34 #define APP_LIB_NAME "arm"
35 #elif defined(APP_USE_X86_64)
36 #define APP_LIB_NAME "x86_64"
37 #elif defined(NAPI_TARGET_ARM64)
38 #define APP_LIB_NAME "arm64"
39 #else
40 #error unsupported platform
41 #endif
42 
43 namespace {
44 const std::string SANDBOX_LIB_PATH = "/data/storage/el1/bundle/libs/" APP_LIB_NAME;
45 const std::string CJ_RT_PATH = SANDBOX_LIB_PATH + "/runtime";
46 const std::string CJ_LIB_PATH = SANDBOX_LIB_PATH + "/ohos";
47 const std::string CJ_SYSLIB_PATH = "/system/lib64:/system/lib64/platformsdk";
48 const std::string CJ_CHIPSDK_PATH = "/system/lib64/chipset-pub-sdk";
49 const std::string CJ_SDK_PATH = "/system/lib64/platformsdk/cjsdk";
50 } // namespace
51 
52 namespace OHOS {
53 namespace {
54 const char DEBUGGER_LIBNAME[] = "libcj_debugger.z.so";
55 const char DEBUGGER_SYMBOL_NAME[] = "StartDebuggerServer";
56 const char INIT_CJRUNTIME_SYMBOL_NAME[] = "InitCJRuntime";
57 const char INIT_UISCHEDULER_SYMBOL_NAME[] = "InitUIScheduler";
58 const char RUN_UISCHEDULER_SYMBOL_NAME[] = "RunUIScheduler";
59 const char FINI_CJRUNTIME_SYMBOL_NAME[] = "FiniCJRuntime";
60 const char INIT_CJLIBRARY_SYMBOL_NAME[] = "InitCJLibrary";
61 const char REGISTER_EVENTHANDLER_CALLBACKS_NAME[] = "RegisterEventHandlerCallbacks";
62 
63 using InitCJRuntimeType = int(*)(const struct RuntimeParam*);;
64 using InitUISchedulerType = void*(*)();
65 using RunUISchedulerType = int(*)(unsigned long long);
66 using FiniCJRuntimeType = int(*)();
67 using InitCJLibraryType = int(*)(const char*);
68 using RegisterEventHandlerType = void(*)(PostTaskType, HasHigherPriorityType);
69 
70 #ifdef __OHOS__
71 const char REGISTER_UNCAUGHT_EXCEPTION_NAME[] = "RegisterUncaughtExceptionHandler";
72 using RegisterUncaughtExceptionType = void (*)(const CJUncaughtExceptionInfo& handle);
73 #endif
74 
75 #ifdef WITH_EVENT_HANDLER
76 static std::shared_ptr<AppExecFwk::EventHandler> g_handler = nullptr;
77 #endif
78 
LoadSymbolInitCJRuntime(void * handle,CJRuntimeAPI & apis)79 bool LoadSymbolInitCJRuntime(void* handle, CJRuntimeAPI& apis)
80 {
81     auto symbol = DynamicFindSymbol(handle, INIT_CJRUNTIME_SYMBOL_NAME);
82     if (symbol == nullptr) {
83         LOGE("runtime api not found: %{public}s", INIT_CJRUNTIME_SYMBOL_NAME);
84         return false;
85     }
86     apis.InitCJRuntime = reinterpret_cast<InitCJRuntimeType>(symbol);
87     return true;
88 }
89 
LoadSymbolInitUIScheduler(void * handle,CJRuntimeAPI & apis)90 bool LoadSymbolInitUIScheduler(void* handle, CJRuntimeAPI& apis)
91 {
92     auto symbol = DynamicFindSymbol(handle, INIT_UISCHEDULER_SYMBOL_NAME);
93     if (symbol == nullptr) {
94         LOGE("runtime api not found: %{public}s", INIT_UISCHEDULER_SYMBOL_NAME);
95         return false;
96     }
97     apis.InitUIScheduler = reinterpret_cast<InitUISchedulerType>(symbol);
98     return true;
99 }
100 
LoadSymbolRunUIScheduler(void * handle,CJRuntimeAPI & apis)101 bool LoadSymbolRunUIScheduler(void* handle, CJRuntimeAPI& apis)
102 {
103     auto symbol = DynamicFindSymbol(handle, RUN_UISCHEDULER_SYMBOL_NAME);
104     if (symbol == nullptr) {
105         LOGE("runtime api not found: %{public}s", RUN_UISCHEDULER_SYMBOL_NAME);
106         return false;
107     }
108     apis.RunUIScheduler = reinterpret_cast<RunUISchedulerType>(symbol);
109     return true;
110 }
111 
LoadSymbolFiniCJRuntime(void * handle,CJRuntimeAPI & apis)112 bool LoadSymbolFiniCJRuntime(void* handle, CJRuntimeAPI& apis)
113 {
114     auto symbol = DynamicFindSymbol(handle, FINI_CJRUNTIME_SYMBOL_NAME);
115     if (symbol == nullptr) {
116         LOGE("runtime api not found: %{public}s", FINI_CJRUNTIME_SYMBOL_NAME);
117         return false;
118     }
119     apis.FiniCJRuntime = reinterpret_cast<FiniCJRuntimeType>(symbol);
120     return true;
121 }
122 
LoadSymbolInitCJLibrary(void * handle,CJRuntimeAPI & apis)123 bool LoadSymbolInitCJLibrary(void* handle, CJRuntimeAPI& apis)
124 {
125     auto symbol = DynamicFindSymbol(handle, INIT_CJLIBRARY_SYMBOL_NAME);
126     if (symbol == nullptr) {
127         LOGE("runtime api not found: %{public}s", INIT_CJLIBRARY_SYMBOL_NAME);
128         return false;
129     }
130     apis.InitCJLibrary = reinterpret_cast<InitCJLibraryType>(symbol);
131     return true;
132 }
133 
LoadSymbolRegisterEventHandlerCallbacks(void * handle,CJRuntimeAPI & apis)134 bool LoadSymbolRegisterEventHandlerCallbacks(void* handle, CJRuntimeAPI& apis)
135 {
136     auto symbol = DynamicFindSymbol(handle, REGISTER_EVENTHANDLER_CALLBACKS_NAME);
137     if (symbol == nullptr) {
138         LOGE("runtime api not found: %{public}s", REGISTER_EVENTHANDLER_CALLBACKS_NAME);
139         return false;
140     }
141     apis.RegisterEventHandlerCallbacks = reinterpret_cast<RegisterEventHandlerType>(symbol);
142     return true;
143 }
144 
145 #ifdef __OHOS__
LoadSymbolRegisterCJUncaughtExceptionHandler(void * handle,CJRuntimeAPI & apis)146 bool LoadSymbolRegisterCJUncaughtExceptionHandler(void* handle, CJRuntimeAPI& apis)
147 {
148     auto symbol = DynamicFindSymbol(handle, REGISTER_UNCAUGHT_EXCEPTION_NAME);
149     if (symbol == nullptr) {
150         LOGE("runtime api not found: %{public}s", REGISTER_UNCAUGHT_EXCEPTION_NAME);
151         return false;
152     }
153     apis.RegisterCJUncaughtExceptionHandler = reinterpret_cast<RegisterUncaughtExceptionType>(symbol);
154     return true;
155 }
156 #endif
157 
PostTaskWrapper(void * func)158 bool PostTaskWrapper(void* func)
159 {
160     return CJEnvironment::GetInstance()->PostTask(reinterpret_cast<TaskFuncType>(func));
161 }
162 
HasHigherPriorityTaskWrapper()163 bool HasHigherPriorityTaskWrapper()
164 {
165     return CJEnvironment::GetInstance()->HasHigherPriorityTask();
166 }
167 
168 CJEnvironment* instance_ = nullptr;
169 } // namespace
170 
171 const char *CJEnvironment::cjAppNSName = "cj_app";
172 const char *CJEnvironment::cjSDKNSName = "cj_app_sdk";
173 const char *CJEnvironment::cjSysNSName = "cj_system";
174 const char *CJEnvironment::cjChipSDKNSName = "cj_chipsdk";
175 const char *CJEnvironment::cjNewAppNSName = "moduleNs_default";
176 const char *CJEnvironment::cjNewSDKNSName = "cj_rom_sdk";
177 const char *CJEnvironment::cjNewSysNSName = "default";
178 const char *CJEnvironment::cjNDKNSName = "ndk";
179 
180 #ifdef WITH_EVENT_HANDLER
GetGHandler()181 static std::shared_ptr<AppExecFwk::EventHandler>GetGHandler()
182 {
183     if (g_handler == nullptr) {
184         g_handler = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
185     }
186     return g_handler;
187 }
188 #endif
189 
InitSpawnEnv()190 void CJEnvironment::InitSpawnEnv()
191 {
192 #ifdef WITH_EVENT_HANDLER
193     GetGHandler();
194 #endif
195     instance_ = new CJEnvironment(NSMode::SINK);
196     instance_->PreloadLibs();
197 }
198 
PreloadLibs()199 void CJEnvironment::PreloadLibs()
200 {
201     LOGI("start Preloadlibs");
202     LoadCJLibrary(SDK, "libohos.ability.so");
203     LoadCJLibrary(SDK, "libohos.component.so");
204     LoadCJLibrary(SDK, "libohos.window.so");
205 }
206 
SetAppPath(const std::string & appPath)207 void CJEnvironment::SetAppPath(const std::string& appPath)
208 {
209     static bool isInited = false;
210     static std::mutex initMutex;
211     std::lock_guard<std::mutex> lock(initMutex);
212     if (isInited) {
213         return;
214     }
215     auto mode = DetectAppNSMode();
216     if (instance_) {
217         if (instance_->nsMode_ == mode) {
218             instance_->InitCJNS(appPath);
219             return;
220         }
221         delete instance_;
222     }
223     instance_ = new CJEnvironment(mode);
224     instance_->InitCJNS(appPath);
225     isInited = true;
226 }
227 
CJEnvironment(NSMode mode)228 CJEnvironment::CJEnvironment(NSMode mode) : nsMode_(mode)
229 {
230     InitRuntimeNS();
231     LoadRuntimeApis();
232 }
233 
~CJEnvironment()234 CJEnvironment::~CJEnvironment()
235 {
236     StopRuntime();
237     if (lazyApis_ != nullptr) {
238         delete lazyApis_;
239         lazyApis_ = nullptr;
240     }
241 }
242 
GetInstance()243 CJEnvironment* CJEnvironment::GetInstance()
244 {
245     return instance_;
246 }
247 
LoadRuntimeApis()248 bool CJEnvironment::LoadRuntimeApis()
249 {
250     if (isRuntimeApiLoaded) {
251         return true;
252     }
253     lazyApis_ = new CJRuntimeAPI();
254 #ifdef __WINDOWS__
255 #define RTLIB_NAME "libcangjie-runtime.dll"
256 #else
257 #define RTLIB_NAME "libcangjie-runtime.so"
258 #endif
259 #ifdef __OHOS__
260     Dl_namespace ns;
261     dlns_get(nsMode_ == NSMode::APP ? cjSDKNSName : cjNewSDKNSName, &ns);
262     std::string runtimeLibName = "libcangjie-runtime";
263     runtimeLibName += ".so";
264     auto dso = DynamicLoadLibrary(&ns, runtimeLibName.c_str(), 1);
265 #else
266     auto dso = DynamicLoadLibrary(RTLIB_NAME, 1);
267 #endif
268     if (!dso) {
269         LOGE("load library failed: %{public}s", RTLIB_NAME);
270         return false;
271     }
272 #undef RTLIB_NAME
273     if (!LoadSymbolInitCJRuntime(dso, *lazyApis_) ||
274         !LoadSymbolInitUIScheduler(dso, *lazyApis_) ||
275         !LoadSymbolRunUIScheduler(dso, *lazyApis_) ||
276         !LoadSymbolFiniCJRuntime(dso, *lazyApis_) ||
277         !LoadSymbolInitCJLibrary(dso, *lazyApis_) ||
278         !LoadSymbolRegisterEventHandlerCallbacks(dso, *lazyApis_)) {
279         LOGE("load symbol failed");
280         return false;
281     }
282 #ifdef __OHOS__
283     if (!LoadSymbolRegisterCJUncaughtExceptionHandler(dso, *lazyApis_)) {
284         LOGE("load symbol RegisterCJUncaughtExceptionHandler failed");
285         return false;
286     }
287 #endif
288     isRuntimeApiLoaded = true;
289     return true;
290 }
291 
RegisterCJUncaughtExceptionHandler(const CJUncaughtExceptionInfo & handle)292 void CJEnvironment::RegisterCJUncaughtExceptionHandler(const CJUncaughtExceptionInfo& handle)
293 {
294     lazyApis_->RegisterCJUncaughtExceptionHandler(handle);
295 }
296 
PostTask(TaskFuncType task)297 bool CJEnvironment::PostTask(TaskFuncType task)
298 {
299 #ifdef WITH_EVENT_HANDLER
300     if (task == nullptr) {
301         LOGE("null task could not be posted");
302         return false;
303     }
304 
305     bool postDone = GetGHandler()->PostTask(task, "spawn-main-task-from-cj", 0, AppExecFwk::EventQueue::Priority::HIGH);
306     if (!postDone) {
307         LOGE("event handler support cj ui scheduler");
308         return false;
309     }
310     return true;
311 #endif
312     return true;
313 }
314 
HasHigherPriorityTask()315 bool CJEnvironment::HasHigherPriorityTask()
316 {
317 #ifdef WITH_EVENT_HANDLER
318     return GetGHandler()->HasPreferEvent(static_cast<int>(AppExecFwk::EventQueue::Priority::HIGH));
319 #endif
320     return false;
321 }
322 
InitCJChipSDKNS(const std::string & path)323 void CJEnvironment::InitCJChipSDKNS(const std::string& path)
324 {
325 #ifdef __OHOS__
326     LOGI("InitCJChipSDKNS: %{public}s", path.c_str());
327     Dl_namespace chip_sdk;
328     DynamicInitNamespace(&chip_sdk, nullptr, path.c_str(), CJEnvironment::cjChipSDKNSName);
329 
330     Dl_namespace cjnative;
331     Dl_namespace current;
332     dlns_get(nullptr, &current);
333     dlns_get(CJEnvironment::cjNDKNSName, &cjnative);
334     dlns_inherit(&chip_sdk, &cjnative, "allow_all_shared_libs");
335     dlns_inherit(&chip_sdk, &current, "allow_all_shared_libs");
336 #endif
337 }
338 
InitNewCJChipSDKNS(const std::string & path)339 void CJEnvironment::InitNewCJChipSDKNS(const std::string& path)
340 {
341 #ifdef __OHOS__
342     LOGI("InitCJChipSDKNS: %{public}s", path.c_str());
343     Dl_namespace chip_sdk;
344     DynamicInitNewNamespace(&chip_sdk, path.c_str(), CJEnvironment::cjChipSDKNSName);
345 #endif
346 }
347 
348 // Init app namespace
InitCJAppNS(const std::string & path)349 void CJEnvironment::InitCJAppNS(const std::string& path)
350 {
351 #ifdef __OHOS__
352     LOGI("InitCJAppNS: %{public}s", path.c_str());
353     Dl_namespace cjnative;
354     Dl_namespace sdk;
355     Dl_namespace ns;
356     Dl_namespace current;
357     DynamicInitNamespace(&ns, nullptr, path.c_str(), CJEnvironment::cjAppNSName);
358     dlns_get(CJEnvironment::cjNDKNSName, &cjnative);
359     dlns_get(nullptr, &current);
360     dlns_get(cjSDKNSName, &sdk);
361     dlns_inherit(&ns, &cjnative, "allow_all_shared_libs");
362     dlns_inherit(&cjnative, &current, "allow_all_shared_libs");
363     dlns_inherit(&current, &cjnative, "allow_all_shared_libs");
364     dlns_inherit(&ns, &sdk, "allow_all_shared_libs");
365 #endif
366 }
367 
InitNewCJAppNS(const std::string & path)368 void CJEnvironment::InitNewCJAppNS(const std::string& path)
369 {
370 #ifdef __OHOS__
371     LOGI("InitCJAppNS: %{public}s", path.c_str());
372     Dl_namespace ns;
373     DynamicInitNewNamespace(&ns, path.c_str(), CJEnvironment::cjNewAppNSName);
374     Dl_namespace sdk;
375     if (nsMode_ == NSMode::APP) {
376         Dl_namespace chip_sdk;
377         dlns_get(CJEnvironment::cjSDKNSName, &sdk);
378         dlns_get(CJEnvironment::cjChipSDKNSName, &chip_sdk);
379         dlns_inherit(&ns, &chip_sdk, "libssl_openssl.z.so");
380     } else {
381         dlns_get(CJEnvironment::cjNewSDKNSName, &sdk);
382     }
383     dlns_inherit(&ns, &sdk, "allow_all_shared_libs");
384 #endif
385 }
386 
387 // Init cj sdk namespace
InitCJSDKNS(const std::string & path)388 void CJEnvironment::InitCJSDKNS(const std::string& path)
389 {
390 #ifdef __OHOS__
391     LOGI("InitCJSDKNS: %{public}s", path.c_str());
392     Dl_namespace ns;
393     DynamicInitNewNamespace(&ns, path.c_str(), cjSDKNSName);
394 #endif
395 }
396 
InitNewCJSDKNS(const std::string & path)397 void CJEnvironment::InitNewCJSDKNS(const std::string& path)
398 {
399 #ifdef __OHOS__
400     LOGI("InitCJSDKNS: %{public}s", path.c_str());
401     Dl_namespace ns;
402     DynamicInitNewNamespace(&ns, path.c_str(), cjNewSDKNSName);
403 #endif
404 }
405 
406 // Init cj system namespace
InitCJSysNS(const std::string & path)407 void CJEnvironment::InitCJSysNS(const std::string& path)
408 {
409 #ifdef __OHOS__
410     LOGI("InitCJSysNS: %{public}s", path.c_str());
411     Dl_namespace cj_sdk;
412     Dl_namespace cjnative;
413     Dl_namespace ns;
414     dlns_get(cjSDKNSName, &cj_sdk);
415     DynamicInitNamespace(&ns, &cj_sdk, path.c_str(), cjSysNSName);
416     dlns_get(CJEnvironment::cjNDKNSName, &cjnative);
417     dlns_inherit(&ns, &cjnative, "allow_all_shared_libs");
418 #endif
419 }
420 
StartRuntime()421 bool CJEnvironment::StartRuntime()
422 {
423     if (isRuntimeStarted_) {
424         return true;
425     }
426 
427     if (!LoadRuntimeApis()) {
428         LOGE("LoadRuntimeApis failed");
429         return false;
430     }
431 
432     RuntimeParam rtParams {
433         .heapParam = {
434             .regionSize = 64,
435             .heapSize = 256 * 1024,
436             .exemptionThreshold= 0.8,
437             .heapUtilization = 0.8,
438             .heapGrowth = 0.15,
439             .allocationRate = 0,
440             .allocationWaitTime = 0,
441         },
442         .gcParam = {
443             .gcThreshold = 0,
444             .garbageThreshold = 0,
445             .gcInterval = 0,
446             .backupGCInterval = 0,
447             .gcThreads = 0,
448         },
449         .logParam = {
450             .logLevel = RTLOG_ERROR,
451         },
452         .coParam = {
453             .thStackSize = 2 * 1024,
454             .coStackSize = 2 * 1024,
455             .processorNum = 8,
456         }
457     };
458 
459     auto status = lazyApis_->InitCJRuntime(&rtParams);
460     if (status != E_OK) {
461         LOGE("init cj runtime failed: %{public}d", status);
462         return false;
463     }
464 
465     lazyApis_->RegisterEventHandlerCallbacks(PostTaskWrapper, HasHigherPriorityTaskWrapper);
466 
467     isRuntimeStarted_ = true;
468     return true;
469 }
470 
StopRuntime()471 void CJEnvironment::StopRuntime()
472 {
473     if (!isRuntimeStarted_) {
474         return;
475     }
476 
477     if (isUISchedulerStarted_) {
478         StopUIScheduler();
479     }
480 
481     auto code = lazyApis_->FiniCJRuntime();
482     if (code == E_OK) {
483         isRuntimeStarted_ = false;
484     }
485 }
486 
StartUIScheduler()487 bool CJEnvironment::StartUIScheduler()
488 {
489     if (isUISchedulerStarted_) {
490         return true;
491     }
492 
493     uiScheduler_ = lazyApis_->InitUIScheduler();
494     if (!uiScheduler_) {
495         LOGE("init cj ui scheduler failed");
496         return false;
497     }
498 
499     isUISchedulerStarted_ = true;
500     return true;
501 }
502 
StopUIScheduler()503 void CJEnvironment::StopUIScheduler()
504 {
505     isUISchedulerStarted_ = false;
506 }
507 
LoadCJLibrary(const char * dlName)508 void* CJEnvironment::LoadCJLibrary(const char* dlName)
509 {
510     if (!StartRuntime()) {
511         LOGE("StartRuntime failed");
512         return nullptr;
513     }
514     auto handle = LoadCJLibrary(APP, dlName);
515     if (!handle) {
516         LOGE("load cj library failed: %{public}s", DynamicGetError());
517         return nullptr;
518     }
519 
520     LOGI("LoadCJLibrary InitCJLibrary: %{public}s", dlName);
521     auto status = lazyApis_->InitCJLibrary(dlName);
522     if (status != E_OK) {
523         LOGE("InitCJLibrary failed: %{public}s", dlName);
524         UnLoadCJLibrary(handle);
525         return nullptr;
526     }
527 
528     return handle;
529 }
530 
LoadCJLibrary(OHOS::CJEnvironment::LibraryKind kind,const char * dlName)531 void* CJEnvironment::LoadCJLibrary(OHOS::CJEnvironment::LibraryKind kind, const char* dlName)
532 {
533 #ifdef __OHOS__
534     Dl_namespace ns;
535     switch (kind) {
536         case APP:
537             dlns_get(CJEnvironment::cjNewAppNSName, &ns);
538             break;
539         case SYSTEM:
540             dlns_get(CJEnvironment::cjNewSysNSName, &ns);
541             break;
542         case SDK:
543             dlns_get(nsMode_ == NSMode::APP ? CJEnvironment::cjSDKNSName : CJEnvironment::cjNewSDKNSName, &ns);
544             break;
545     }
546     auto handle = DynamicLoadLibrary(&ns, dlName, 0);
547 #else
548     auto handle = DynamicLoadLibrary(dlName, 1);
549 #endif
550     if (!handle) {
551         LOGE("load cj library failed: %{public}s", DynamicGetError());
552         return nullptr;
553     }
554     return handle;
555 }
556 
UnLoadCJLibrary(void * handle)557 void CJEnvironment::UnLoadCJLibrary(void* handle)
558 {
559     DynamicFreeLibrary(handle);
560 }
561 
GetSymbol(void * dso,const char * symbol)562 void* CJEnvironment::GetSymbol(void* dso, const char* symbol)
563 {
564     return DynamicFindSymbol(dso, symbol);
565 }
566 
StartDebugger()567 bool CJEnvironment::StartDebugger()
568 {
569 #ifdef __OHOS__
570     Dl_namespace ns;
571     dlns_get(CJEnvironment::cjNewSysNSName, &ns);
572     auto handle = DynamicLoadLibrary(&ns, DEBUGGER_LIBNAME, 0);
573 #else
574     auto handle = DynamicLoadLibrary(DEBUGGER_LIBNAME, 0);
575 #endif
576     if (!handle) {
577         LOGE("failed to load library: %{public}s", DEBUGGER_LIBNAME);
578         return false;
579     }
580     auto symbol = DynamicFindSymbol(handle, DEBUGGER_SYMBOL_NAME);
581     if (!symbol) {
582         LOGE("failed to find symbol: %{public}s", DEBUGGER_SYMBOL_NAME);
583         DynamicFreeLibrary(handle);
584         return false;
585     }
586     auto func = reinterpret_cast<bool (*)(int, const std::string&)>(symbol);
587     std::string name = "PandaDebugger";
588     func(0, name);
589     return true;
590 }
591 
DetectAppNSMode()592 CJEnvironment::NSMode CJEnvironment::DetectAppNSMode()
593 {
594     std::filesystem::path runtimePath(CJ_RT_PATH + "/libcangjie-runtime.so");
595     if (std::filesystem::exists(runtimePath)) {
596         return NSMode::APP;
597     } else {
598         return NSMode::SINK;
599     }
600 }
601 
InitRuntimeNS()602 void CJEnvironment::InitRuntimeNS()
603 {
604 #ifdef __OHOS__
605     if (nsMode_ == NSMode::APP) {
606         InitNewCJChipSDKNS(CJ_CHIPSDK_PATH);
607         InitCJSDKNS(CJ_RT_PATH + ":" + CJ_LIB_PATH);
608     } else {
609         InitNewCJSDKNS(CJ_SDK_PATH);
610     }
611 #endif
612 }
613 
InitCJNS(const std::string & appPath)614 void CJEnvironment::InitCJNS(const std::string& appPath)
615 {
616 #ifdef __OHOS__
617     InitNewCJAppNS(appPath.empty() ? SANDBOX_LIB_PATH : appPath);
618 #endif
619     if (!StartRuntime()) {
620         LOGE("StartRuntime failed");
621         return;
622     }
623     if (!StartUIScheduler()) {
624         LOGE("StartUIScheduler failed");
625         return;
626     }
627 }
628 
CreateEnvMethods()629 CJEnvMethods* CJEnvironment::CreateEnvMethods()
630 {
631     static CJEnvMethods gCJEnvMethods {
632         .initCJAppNS = [](const std::string& path) {
633             // to keep compatibility with older version
634             CJEnvironment::SetAppPath(path);
635         },
636         .initCJSDKNS = [](const std::string& path) {
637             // @deprecated
638         },
639         .initCJSysNS = [](const std::string& path) {
640             // @deprecated
641         },
642         .initCJChipSDKNS = [](const std::string& path) {
643             // @deprecated
644         },
645         .startRuntime = [] {
646             return CJEnvironment::GetInstance()->StartRuntime();
647         },
648         .startUIScheduler = [] {
649             return CJEnvironment::GetInstance()->StartUIScheduler();
650         },
651         .loadCJModule = [](const char* dllName) {
652             return CJEnvironment::GetInstance()->LoadCJLibrary(dllName);
653         },
654         .loadLibrary = [](uint32_t kind, const char* dllName) {
655             return CJEnvironment::GetInstance()->LoadCJLibrary(static_cast<CJEnvironment::LibraryKind>(kind), dllName);
656         },
657         .getSymbol = [](void* handle, const char* dllName) {
658             return CJEnvironment::GetInstance()->GetSymbol(handle, dllName);
659         },
660         .loadCJLibrary = [](const char* dllName) {
661             return CJEnvironment::GetInstance()->LoadCJLibrary(dllName);
662         },
663         .startDebugger = []() {
664             return CJEnvironment::GetInstance()->StartDebugger();
665         },
666         .registerCJUncaughtExceptionHandler = [](const CJUncaughtExceptionInfo& handle) {
667             return CJEnvironment::GetInstance()->RegisterCJUncaughtExceptionHandler(handle);
668         },
669         .setSanitizerKindRuntimeVersion = [](SanitizerKind kind) {
670             return CJEnvironment::GetInstance()->SetSanitizerKindRuntimeVersion(kind);
671         }
672     };
673     return &gCJEnvMethods;
674 }
675 
OHOS_InitSpawnEnv()676 CJ_EXPORT extern "C" void OHOS_InitSpawnEnv()
677 {
678     CJEnvironment::InitSpawnEnv();
679 }
680 
OHOS_GetCJEnvInstance()681 CJ_EXPORT extern "C" CJEnvMethods* OHOS_GetCJEnvInstance()
682 {
683     return CJEnvironment::CreateEnvMethods();
684 }
685 }
686