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 }