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, ¤t);
333 dlns_get(CJEnvironment::cjNDKNSName, &cjnative);
334 dlns_inherit(&chip_sdk, &cjnative, "allow_all_shared_libs");
335 dlns_inherit(&chip_sdk, ¤t, "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, ¤t);
360 dlns_get(cjSDKNSName, &sdk);
361 dlns_inherit(&ns, &cjnative, "allow_all_shared_libs");
362 dlns_inherit(&cjnative, ¤t, "allow_all_shared_libs");
363 dlns_inherit(¤t, &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