• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "ets_environment.h"
17 
18 #include <chrono>
19 #include <dlfcn.h>
20 #include <fstream>
21 #include <nlohmann/json.hpp>
22 #include <sstream>
23 #include <string>
24 #include <thread>
25 #include <vector>
26 
27 #include "static_core/plugins/ets/runtime/ets_namespace_manager.h"
28 
29 #include "ets_ani_expo.h"
30 #ifdef LIKELY
31 #undef LIKELY
32 #endif
33 #ifdef UNLIKELY
34 #undef UNLIKELY
35 #endif
36 #include "dynamic_loader.h"
37 #include "elf_factory.h"
38 #include "event_handler.h"
39 #include "hilog_tag_wrapper.h"
40 #include "unwinder.h"
41 
42 #ifdef SUPPORT_GRAPHICS
43 #include "ui_content.h"
44 #endif // SUPPORT_GRAPHICS
45 
46 namespace OHOS {
47 namespace EtsEnv {
48 namespace {
49 const char ETS_CREATE_VM[] = "ANI_CreateVM";
50 const char ETS_ANI_GET_CREATEDVMS[] = "ANI_GetCreatedVMs";
51 const char ETS_LIB_PATH[] = "libets_interop_js_napi.z.so";
52 const char BOOT_PATH[] = "/system/framework/bootpath.json";
53 const char BACKTRACE[] = "=====================Backtrace========================";
54 
55 using CreateVMETSRuntimeType = ani_status (*)(const ani_options *options, uint32_t version, ani_vm **result);
56 using ANIGetCreatedVMsType = ani_status (*)(ani_vm **vms_buffer, ani_size vms_buffer_length, ani_size *result);
57 
58 const char ETS_SDK_NSNAME[] = "ets_sdk";
59 const char ETS_SYS_NSNAME[] = "ets_system";
60 
61 constexpr const char* CLASSNAME_STRING = "Lstd/core/String;";
62 constexpr const char* CLASSNAME_LINKER = "Lstd/core/AbcRuntimeLinker;";
63 } // namespace
64 
65 ETSRuntimeAPI ETSEnvironment::lazyApis_ {};
66 std::unique_ptr<ETSEnvironment> instance_ = nullptr;
67 
GetInstance()68 std::unique_ptr<ETSEnvironment> &ETSEnvironment::GetInstance()
69 {
70     if (instance_ == nullptr) {
71         instance_ = std::make_unique<ETSEnvironment>();
72     }
73     return instance_;
74 }
75 
LoadBootPathFile(std::string & bootfiles)76 bool ETSEnvironment::LoadBootPathFile(std::string &bootfiles)
77 {
78     std::ifstream inFile;
79     inFile.open(BOOT_PATH, std::ios::in);
80     if (!inFile.is_open()) {
81         TAG_LOGE(AAFwkTag::ETSRUNTIME, "read json error");
82         return false;
83     }
84     nlohmann::json jsonObject = nlohmann::json::parse(inFile, nullptr, false);
85     if (jsonObject.is_discarded()) {
86         TAG_LOGE(AAFwkTag::ETSRUNTIME, "json discarded error");
87         inFile.close();
88         return false;
89     }
90 
91     if (jsonObject.is_null() || jsonObject.empty()) {
92         TAG_LOGE(AAFwkTag::ETSRUNTIME, "invalid json");
93         inFile.close();
94         return false;
95     }
96 
97     for (const auto &[key, value] : jsonObject.items()) {
98         if (!value.is_null() && value.is_string()) {
99             std::string jsonValue = value.get<std::string>();
100             if (jsonValue.empty()) {
101                 TAG_LOGE(AAFwkTag::ETSRUNTIME, "json value of %{public}s is empty", key.c_str());
102                 continue;
103             }
104             if (!bootfiles.empty()) {
105                 bootfiles += ":";
106             }
107             bootfiles += jsonValue.c_str();
108         }
109     }
110     inFile.close();
111     return true;
112 }
113 
LoadRuntimeApis()114 bool ETSEnvironment::LoadRuntimeApis()
115 {
116     static bool isRuntimeApiLoaded { false };
117     if (isRuntimeApiLoaded) {
118         return true;
119     }
120 
121     Dl_namespace ns;
122     dlns_get(ETS_SDK_NSNAME, &ns);
123     auto dso = DynamicLoadLibrary(&ns, ETS_LIB_PATH, 1);
124     if (!dso) {
125         TAG_LOGE(AAFwkTag::ETSRUNTIME, "load library failed: %{public}s", ETS_LIB_PATH);
126         return false;
127     }
128 
129     if (!LoadSymbolCreateVM(dso, lazyApis_) ||
130         !LoadSymbolANIGetCreatedVMs(dso, lazyApis_)) {
131         TAG_LOGE(AAFwkTag::ETSRUNTIME, "load symbol failed");
132         return false;
133     }
134 
135     isRuntimeApiLoaded = true;
136     return true;
137 }
138 
GetBuildId(std::string stack)139 std::string ETSEnvironment::GetBuildId(std::string stack)
140 {
141     std::stringstream ss(stack);
142     std::string tempStr = "";
143     std::string addBuildId = "";
144     int i = 0;
145     while (std::getline(ss, tempStr)) {
146         auto spitlPos = tempStr.rfind(" ");
147         if (spitlPos != std::string::npos) {
148             HiviewDFX::RegularElfFactory elfFactory(tempStr.substr(spitlPos + 1));
149             auto elfFile = elfFactory.Create();
150             if (elfFile == nullptr) {
151                 TAG_LOGE(AAFwkTag::ETSRUNTIME, "null elfFile");
152                 break;
153             }
154             std::string buildId = elfFile->GetBuildId();
155             if (i != 0 && !buildId.empty()) {
156                 addBuildId += tempStr + "(" + buildId + ")" + "\n";
157             } else {
158                 addBuildId += tempStr + "\n";
159             }
160         }
161         i++;
162     }
163     return addBuildId;
164 }
165 
RegisterUncaughtExceptionHandler(const ETSUncaughtExceptionInfo & handle)166 void ETSEnvironment::RegisterUncaughtExceptionHandler(const ETSUncaughtExceptionInfo &handle)
167 {
168     TAG_LOGD(AAFwkTag::ETSRUNTIME, "RegisterUncaughtExceptionHandler called");
169     uncaughtExceptionInfo_ = handle;
170 }
171 
LoadSymbolCreateVM(void * handle,ETSRuntimeAPI & apis)172 bool ETSEnvironment::LoadSymbolCreateVM(void *handle, ETSRuntimeAPI &apis)
173 {
174     auto symbol = dlsym(handle, ETS_CREATE_VM);
175     if (symbol == nullptr) {
176         TAG_LOGE(AAFwkTag::ETSRUNTIME, "runtime api not found: %{public}s", ETS_CREATE_VM);
177         return false;
178     }
179     apis.ANI_CreateVM = reinterpret_cast<CreateVMETSRuntimeType>(symbol);
180 
181     return true;
182 }
183 
LoadSymbolANIGetCreatedVMs(void * handle,ETSRuntimeAPI & apis)184 bool ETSEnvironment::LoadSymbolANIGetCreatedVMs(void *handle, ETSRuntimeAPI &apis)
185 {
186     auto symbol = dlsym(handle, ETS_ANI_GET_CREATEDVMS);
187     if (symbol == nullptr) {
188         TAG_LOGE(AAFwkTag::ETSRUNTIME, "runtime api not found: %{public}s", ETS_ANI_GET_CREATEDVMS);
189         return false;
190     }
191     apis.ANI_GetCreatedVMs = reinterpret_cast<ANIGetCreatedVMsType>(symbol);
192 
193     return true;
194 }
195 
InitETSSDKNS(const std::string & path)196 void ETSEnvironment::InitETSSDKNS(const std::string &path)
197 {
198     TAG_LOGD(AAFwkTag::ETSRUNTIME, "InitETSSDKNS: %{public}s", path.c_str());
199     Dl_namespace ndk;
200     Dl_namespace ns;
201     DynamicInitNamespace(&ns, nullptr, path.c_str(), ETS_SDK_NSNAME);
202     dlns_get("ndk", &ndk);
203     dlns_inherit(&ns, &ndk, "allow_all_shared_libs");
204 }
205 
InitETSSysNS(const std::string & path)206 void ETSEnvironment::InitETSSysNS(const std::string &path)
207 {
208     TAG_LOGD(AAFwkTag::ETSRUNTIME, "InitETSSysNS: %{public}s", path.c_str());
209     Dl_namespace ets_sdk;
210     Dl_namespace ndk;
211     Dl_namespace ns;
212     dlns_get(ETS_SDK_NSNAME, &ets_sdk);
213     DynamicInitNamespace(&ns, &ets_sdk, path.c_str(), ETS_SYS_NSNAME);
214     dlns_get("ndk", &ndk);
215     dlns_inherit(&ns, &ndk, "allow_all_shared_libs");
216 }
217 
Initialize()218 bool ETSEnvironment::Initialize()
219 {
220     TAG_LOGD(AAFwkTag::ETSRUNTIME, "Initialize called");
221     if (!LoadRuntimeApis()) {
222         TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadRuntimeApis failed");
223         return false;
224     }
225     std::string bootfiles;
226     if (!LoadBootPathFile(bootfiles)) {
227         TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadBootPathFile failed");
228         return false;
229     }
230 
231     std::vector<ani_option> options;
232     // Create boot-panda-files options
233     std::string bootString = "--ext:--boot-panda-files=" + bootfiles;
234     options.push_back(ani_option { bootString.data(), nullptr });
235     options.push_back(ani_option { "--ext:--compiler-enable-jit=false", nullptr });
236     options.push_back(ani_option { "--ext:--log-level=info", nullptr });
237     ani_options optionsPtr = { options.size(), options.data() };
238     ani_status status = ANI_ERROR;
239     if ((status = lazyApis_.ANI_CreateVM(&optionsPtr, ANI_VERSION_1, &vmEntry_.aniVm_)) != ANI_OK) {
240         TAG_LOGE(AAFwkTag::ETSRUNTIME, "ANI_CreateVM failed %{public}d", status);
241         return false;
242     }
243     if ((status = vmEntry_.aniVm_->GetEnv(ANI_VERSION_1, &vmEntry_.aniEnv_)) != ANI_OK) {
244         TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetEnv failed %{public}d", status);
245         return false;
246     }
247     return true;
248 }
249 
GetAniEnv()250 ani_env *ETSEnvironment::GetAniEnv()
251 {
252     if (vmEntry_.aniVm_ == nullptr) {
253         return nullptr;
254     }
255     ani_env* env = nullptr;
256     if (vmEntry_.aniVm_->GetEnv(ANI_VERSION_1, &env) != ANI_OK) {
257         return nullptr;
258     }
259     return env;
260 }
261 
HandleUncaughtError()262 bool ETSEnvironment::HandleUncaughtError()
263 {
264     TAG_LOGD(AAFwkTag::ETSRUNTIME, "HandleUncaughtError called");
265     const EtsEnv::ETSErrorObject errorObj = GetETSErrorObject();
266     std::string errorStack = errorObj.stack;
267     if (errorStack.empty()) {
268         TAG_LOGE(AAFwkTag::ETSRUNTIME, "errorStack is empty");
269         return false;
270     }
271     TAG_LOGE(AAFwkTag::ETSRUNTIME, "errorObj.name:%{public}s, errorObj.message:%{public}s,errorObj.stack:%{public}s",
272         errorObj.name.c_str(), errorObj.message.c_str(), errorObj.stack.c_str());
273     std::string summary = "Error name:" + errorObj.name + "\n";
274     summary += "Error message:" + errorObj.message + "\n";
275     if (errorStack.find(BACKTRACE) != std::string::npos) {
276         summary += "Stacktrace:\n" + GetBuildId(errorStack);
277     } else {
278         summary += "Stacktrace:\n" + errorStack;
279     }
280 #ifdef SUPPORT_GRAPHICS
281     std::string str = Ace::UIContent::GetCurrentUIStackInfo();
282     if (!str.empty()) {
283         summary.append(str);
284     }
285 #endif // SUPPORT_GRAPHICS
286     if (uncaughtExceptionInfo_.uncaughtTask) {
287         TAG_LOGE(AAFwkTag::ETSRUNTIME, "uncaughtTask called");
288         uncaughtExceptionInfo_.uncaughtTask(summary, errorObj);
289         return true;
290     }
291     return false;
292 }
293 
GetETSErrorObject()294 EtsEnv::ETSErrorObject ETSEnvironment::GetETSErrorObject()
295 {
296     TAG_LOGD(AAFwkTag::ETSRUNTIME, "GetETSErrorObject called");
297     ani_boolean errorExists = ANI_FALSE;
298     ani_status status = ANI_ERROR;
299     auto aniEnv = GetAniEnv();
300     if (aniEnv == nullptr) {
301         TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env");
302         return EtsEnv::ETSErrorObject();
303     }
304     if ((status = aniEnv->ExistUnhandledError(&errorExists)) != ANI_OK) {
305         TAG_LOGE(AAFwkTag::ETSRUNTIME, "ExistUnhandledError failed, status : %{public}d", status);
306         return EtsEnv::ETSErrorObject();
307     }
308     if (errorExists == ANI_FALSE) {
309         TAG_LOGE(AAFwkTag::ETSRUNTIME, "not exist error");
310         return EtsEnv::ETSErrorObject();
311     }
312     ani_error aniError = nullptr;
313     if ((status = aniEnv->GetUnhandledError(&aniError)) != ANI_OK) {
314         TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetUnhandledError failed, status : %{public}d", status);
315         return EtsEnv::ETSErrorObject();
316     }
317     if ((status = aniEnv->ResetError()) != ANI_OK) {
318         TAG_LOGE(AAFwkTag::ETSRUNTIME, "ResetError failed, status : %{public}d", status);
319         return EtsEnv::ETSErrorObject();
320     }
321     std::string errorMsg = GetErrorProperty(aniError, "message");
322     std::string errorName = GetErrorProperty(aniError, "name");
323     std::string errorStack = GetErrorProperty(aniError, "stack");
324     const EtsEnv::ETSErrorObject errorObj = {
325         .name = errorName,
326         .message = errorMsg,
327         .stack = errorStack
328     };
329     return errorObj;
330 }
331 
GetErrorProperty(ani_error aniError,const char * property)332 std::string ETSEnvironment::GetErrorProperty(ani_error aniError, const char *property)
333 {
334     TAG_LOGD(AAFwkTag::ETSRUNTIME, "GetErrorProperty called");
335     auto aniEnv = GetAniEnv();
336     std::string propertyValue;
337     ani_status status = ANI_ERROR;
338     ani_type errorType = nullptr;
339     if ((status = aniEnv->Object_GetType(aniError, &errorType)) != ANI_OK) {
340         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Object_GetType failed, status : %{public}d", status);
341         return propertyValue;
342     }
343     ani_method getterMethod = nullptr;
344     if ((status = aniEnv->Class_FindGetter(static_cast<ani_class>(errorType), property, &getterMethod)) != ANI_OK) {
345         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Class_FindGetter failed, status : %{public}d", status);
346         return propertyValue;
347     }
348     ani_ref aniRef = nullptr;
349     if ((status = aniEnv->Object_CallMethod_Ref(aniError, getterMethod, &aniRef)) != ANI_OK) {
350         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Object_CallMethod_Ref failed, status : %{public}d", status);
351         return propertyValue;
352     }
353     ani_string aniString = reinterpret_cast<ani_string>(aniRef);
354     ani_size sz {};
355     if ((status = aniEnv->String_GetUTF8Size(aniString, &sz)) != ANI_OK) {
356         TAG_LOGE(AAFwkTag::ETSRUNTIME, "String_GetUTF8Size failed, status : %{public}d", status);
357         return propertyValue;
358     }
359     propertyValue.resize(sz + 1);
360     if ((status = aniEnv->String_GetUTF8SubString(
361         aniString, 0, sz, propertyValue.data(), propertyValue.size(), &sz))!= ANI_OK) {
362         TAG_LOGE(AAFwkTag::ETSRUNTIME, "String_GetUTF8SubString failed, status : %{public}d", status);
363         return propertyValue;
364     }
365     propertyValue.resize(sz);
366     return propertyValue;
367 }
368 
PreloadModule(const std::string & modulePath)369 bool ETSEnvironment::PreloadModule(const std::string &modulePath)
370 {
371     TAG_LOGD(AAFwkTag::ETSRUNTIME, "modulePath: %{public}s", modulePath.c_str());
372     ani_env *env = GetAniEnv();
373     if (env == nullptr) {
374         TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env");
375         return false;
376     }
377 
378     ani_class abcCls = nullptr;
379     ani_object abcObj = nullptr;
380     if (!LoadAbcLinker(env, modulePath, abcCls, abcObj)) {
381         TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadAbcLinker failed");
382         return false;
383     }
384     return true;
385 }
386 
LoadAbcLinker(ani_env * env,const std::string & modulePath,ani_class & abcCls,ani_object & abcObj)387 bool ETSEnvironment::LoadAbcLinker(ani_env *env, const std::string &modulePath, ani_class &abcCls, ani_object &abcObj)
388 {
389     if (env == nullptr) {
390         TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env");
391         return false;
392     }
393     ani_status status = ANI_ERROR;
394     ani_class stringCls = nullptr;
395     if ((status = env->FindClass(CLASSNAME_STRING, &stringCls)) != ANI_OK) {
396         TAG_LOGE(AAFwkTag::ETSRUNTIME, "FindClass failed, status: %{public}d", status);
397         return false;
398     }
399     ani_string modulePathAni = nullptr;
400     if ((status = env->String_NewUTF8(modulePath.c_str(), modulePath.size(), &modulePathAni)) != ANI_OK) {
401         TAG_LOGE(AAFwkTag::ETSRUNTIME, "String_NewUTF8 failed, status: %{public}d", status);
402         return false;
403     }
404     ani_ref undefinedRef = nullptr;
405     if ((status = env->GetUndefined(&undefinedRef)) != ANI_OK) {
406         TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetUndefined failed, status: %{public}d", status);
407         return false;
408     }
409     ani_array_ref refArray = nullptr;
410     if ((status = env->Array_New_Ref(stringCls, 1, undefinedRef, &refArray)) != ANI_OK) {
411         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Array_New_Ref failed, status: %{public}d", status);
412         return false;
413     }
414     if ((status = env->Array_Set_Ref(refArray, 0, modulePathAni)) != ANI_OK) {
415         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Array_Set_Ref failed, status: %{public}d", status);
416         return false;
417     }
418     if ((status = env->FindClass(CLASSNAME_LINKER, &abcCls)) != ANI_OK) {
419         TAG_LOGE(AAFwkTag::ETSRUNTIME, "FindClass failed, status: %{public}d", status);
420         return false;
421     }
422     ani_method method = nullptr;
423     if ((status = env->Class_FindMethod(abcCls, "<ctor>", "Lstd/core/RuntimeLinker;[Lstd/core/String;:V",
424         &method)) != ANI_OK) {
425         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Class_FindMethod failed, status: %{public}d", status);
426         return false;
427     }
428     env->ResetError();
429     if ((status = env->Object_New(abcCls, method, &abcObj, undefinedRef, refArray)) != ANI_OK) {
430         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Object_New failed, status: %{public}d", status);
431         HandleUncaughtError();
432         return false;
433     }
434     return true;
435 }
436 
LoadModule(const std::string & modulePath,const std::string & srcEntrance,void * & cls,void * & obj,void * & ref)437 bool ETSEnvironment::LoadModule(const std::string &modulePath, const std::string &srcEntrance, void *&cls,
438     void *&obj, void *&ref)
439 {
440     ani_env *env = GetAniEnv();
441     if (env == nullptr) {
442         TAG_LOGE(AAFwkTag::ETSRUNTIME, "null env");
443         return false;
444     }
445     ani_status status = ANI_ERROR;
446     ani_class abcCls = nullptr;
447     ani_object abcObj = nullptr;
448     if (!LoadAbcLinker(env, modulePath, abcCls, abcObj)) {
449         TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadAbcLinker failed");
450         return false;
451     }
452     ani_method loadClassMethod = nullptr;
453     if ((status = env->Class_FindMethod(abcCls, "loadClass", nullptr, &loadClassMethod)) != ANI_OK) {
454         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Class_FindMethod failed, status: %{public}d", status);
455         return false;
456     }
457     ani_string clsStr = nullptr;
458     if ((status = env->String_NewUTF8(srcEntrance.c_str(), srcEntrance.length(), &clsStr)) != ANI_OK) {
459         TAG_LOGE(AAFwkTag::ETSRUNTIME, "String_NewUTF8 failed, status: %{public}d", status);
460         return false;
461     }
462     ani_ref clsRef = nullptr;
463     ani_class clsAni = nullptr;
464     if ((status = env->Object_CallMethod_Ref(abcObj, loadClassMethod, &clsRef, clsStr, false)) != ANI_OK) {
465         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Object_CallMethod_Ref failed, status: %{public}d", status);
466         return false;
467     }
468     clsAni = static_cast<ani_class>(clsRef);
469     ani_method method = nullptr;
470     if ((status = env->Class_FindMethod(clsAni, "<ctor>", ":V", &method)) != ANI_OK) {
471         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Class_FindMethod failed, status: %{public}d", status);
472         return false;
473     }
474     ani_object objAni = nullptr;
475     if ((status = env->Object_New(clsAni, method, &objAni)) != ANI_OK) {
476         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Object_New failed, status: %{public}d", status);
477         return false;
478     }
479     ani_ref refAni = nullptr;
480     if ((status = env->GlobalReference_Create(objAni, &refAni)) != ANI_OK) {
481         TAG_LOGE(AAFwkTag::ETSRUNTIME, "GlobalReference_Create failed, status: %{public}d", status);
482         return false;
483     }
484     cls = reinterpret_cast<void *>(clsAni);
485     obj = reinterpret_cast<void *>(objAni);
486     ref = reinterpret_cast<void *>(refAni);
487     return true;
488 }
489 
FinishPreload()490 bool ETSEnvironment::FinishPreload() {
491     ani_env *env = GetAniEnv();
492     if (env == nullptr) {
493         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed: ANI env nullptr");
494         return false;
495     }
496     ark::ets::ETSAni::Prefork(env);
497     return true;
498 }
499 
PostFork(void * napiEnv,const std::string & aotPath)500 bool ETSEnvironment::PostFork(void *napiEnv, const std::string &aotPath)
501 {
502     std::vector<ani_option> options;
503     std::string aotPathString = "";
504     if (!aotPath.empty()) {
505         aotPathString = "--ext:--aot-file=" + aotPath;
506         options.push_back(ani_option { aotPathString.data(), nullptr });
507         options.push_back(ani_option { "--ext:--enable-an", nullptr });
508         TAG_LOGD(AAFwkTag::ETSRUNTIME, "aotPathString: %{public}s", aotPathString.c_str());
509     }
510 
511     options.push_back(ani_option { "--ext:interop", napiEnv });
512 
513     ani_env *env = GetAniEnv();
514     if (env == nullptr) {
515         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Failed: ANI env nullptr");
516         return false;
517     }
518     ark::ets::ETSAni::Postfork(env, options);
519     return true;
520 }
521 
PreloadSystemClass(const char * className)522 bool ETSEnvironment::PreloadSystemClass(const char *className)
523 {
524     ani_env* env = GetAniEnv();
525     if (env == nullptr) {
526         TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetAniEnv failed");
527         return false;
528     }
529 
530     ani_class cls = nullptr;
531     if (env->FindClass(className, &cls) != ANI_OK) {
532         TAG_LOGE(AAFwkTag::ETSRUNTIME, "Find preload class failed");
533         return false;
534     }
535     return true;
536 }
537 
RegisterFuncs()538 ETSEnvFuncs *ETSEnvironment::RegisterFuncs()
539 {
540     static ETSEnvFuncs funcs {
541         .InitETSSDKNS = [](const std::string &path) {
542             ETSEnvironment::InitETSSDKNS(path);
543         },
544         .InitETSSysNS = [](const std::string &path) {
545             ETSEnvironment::InitETSSysNS(path);
546         },
547         .Initialize = []() {
548             return ETSEnvironment::GetInstance()->Initialize();
549         },
550         .RegisterUncaughtExceptionHandler = [](const ETSUncaughtExceptionInfo &exceptionInfo) {
551             ETSEnvironment::GetInstance()->RegisterUncaughtExceptionHandler(exceptionInfo);
552         },
553         .GetAniEnv = []() {
554             return ETSEnvironment::GetInstance()->GetAniEnv();
555         },
556         .PreloadModule = [](const std::string &modulePath) {
557             return ETSEnvironment::GetInstance()->PreloadModule(modulePath);
558         },
559         .LoadModule = [](const std::string &modulePath, const std::string &srcEntrance, void *&cls,
560              void *&obj,  void *&ref) {
561             return ETSEnvironment::GetInstance()->LoadModule(modulePath, srcEntrance, cls, obj, ref);
562         },
563         .SetAppLibPath = [](const std::map<std::string, std::string> &abcPathsToBundleModuleNameMap,
564             std::function<bool(const std::string &bundleModuleName, std::string &namespaceName)> &cb) {
565             ark::ets::EtsNamespaceManager::SetAppLibPaths(abcPathsToBundleModuleNameMap, cb);
566         },
567         .FinishPreload = []() {
568             ETSEnvironment::GetInstance()->FinishPreload();
569         },
570         .PostFork = [](void *napiEnv, const std::string &aotPath) {
571             ETSEnvironment::GetInstance()->PostFork(napiEnv, aotPath);
572         },
573         .PreloadSystemClass = [](const char *className) {
574             ETSEnvironment::GetInstance()->PreloadSystemClass(className);
575         }
576     };
577     return &funcs;
578 }
579 } // namespace EtsEnv
580 } // namespace OHOS
581 
OHOS_ETS_ENV_RegisterFuncs()582 ETS_EXPORT extern "C" ETSEnvFuncs *OHOS_ETS_ENV_RegisterFuncs()
583 {
584     return OHOS::EtsEnv::ETSEnvironment::RegisterFuncs();
585 }