Files
ability_ability_runtime/frameworks/native/runtime/ets_runtime.cpp
T
openharmony_ci 8cd8066710 !17240 merge coroutines-sync-branches into master
sync coroutines code in master branch

Created-by: panferovi
Commit-by: Panferov Ivan
Merged-by: openharmony_ci
Description: **IssueNo**:
https://gitcode.com/openharmony/arkcompiler_runtime_core/issues/8105

**Description**:
sync coroutines code in master branch

**稳定性自检:**
| 自检项                                                       | 自检结果  |
| ------------------------------------------------------------ | -------- |
| 涉及跨进程调用的相关操作需要抛至主线程或加锁防止并发              |          |
| 成员变量进行赋值或创建需要排查并发                               |          |
| 谨慎在lambda表达式中使用引用捕获                                |          |
| 谨慎在未经拷贝的情况下使用外部传入的string、C字符串               |          |
| map\vector\list\set等stl模板类使用时需要排查并发                |          |
| 谨慎考虑加锁范围                                               |          |
| 在IPC通信中谨慎使用同步通信方式                                 |          |
| 禁止传递this指针至其他模块或线程(特别是eventhandler任务)        |          |
| 禁止将外部传入的裸指针在内部直接构造智能指针                      |          |
| 禁止多个独立创建的智能指针管理同一地址                           |          |
| 禁止在析构函数中抛异步任务                                      |          |
| 禁止js对象在非js线程(例如在IPC线程)创建、使用或销毁             |          |
| 禁止在对外接口中未经判空直接使用外部传入的指针                    |          |
| 禁止接口返回局部变量引用                                        |          |
| 禁止在信号函数中加锁                                            |          |
| 禁止在关键流程(SA启动、应用启动等主流程)执行耗时的操作           |          |
| 禁止将同一个cpp编译在不同的so中                                 |          |

**安全编码自检:**
| 自检项                                                          | 自检结果 |
| -------------------------------------------------------------- | -------- |
| 裸指针避免通过隐式转换构造为sptr                                 |          |
| json对象在取值之前必须先判断类型,避免类型不匹配                   |          |
| 序列化时必须对传入的数组大小进行校验,避免出现超大数组              |          |
| 避免使用未明确位宽的整型,选择使用int8_t、uint8_t等类型            |          |
| 外部传入的路径要做规范化校验,对路径中的.、..、../等特殊字符严格校验 |          |
| 指针变量、表示资源描述符的变量、bool变量必须赋初值                  |          |
| readParcelable获取的对象使用前需要判空                            |          |
| 分配和释放内存的函数需要成对出现                                   |          |
| 申请内存后异常退出前需要及时进行内存释放                            |          |
| 内存申请前必须对内存大小进行合法性校验                              |          |
| 内存分配后必须判断是否成功                                         |          |
| 禁止使用realloc、alloca函数                                       |          |
| 禁止打印文件路径、口令等敏感信息,如有需要,使用private修饰          |          |
| 禁止打印内存地址                                                  |          |
| 整数之间运算时必须严格检查,确保不会出现溢出、反转、除0               |          |
| 禁止对有符号整数进行位操作符运算                                    |          |
| 禁止对指针进行逻辑或位运算                                         |          |
| 循环次数如果收外部数据控制,需要检验其合法性                         |          |
| 禁止使用内存操作类危险函数,需要使用安全函数                         |          |
| 谨慎使用不可重入函数                                               |          |
| 必须检查安全函数的返回值,并进行正确处理                             |          |
| 禁止仅通过TokenType类型判断绕过权限校验                             |          |

**TDD Result**:

**XTS Result**:

### 是否已执行L0用例
- [ ] 已验证
- [ ] 不涉及。如不涉及,请写明理由


See merge request: openharmony/ability_ability_runtime!17240
2025-11-07 21:44:48 +08:00

636 lines
22 KiB
C++

/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ets_runtime.h"
#include <algorithm>
#include <cstddef>
#include <dlfcn.h>
#include <filesystem>
#include <fstream>
#include <nlohmann/json.hpp>
#include <regex>
#include <unistd.h>
#include "bundle_constants.h"
#include "constants.h"
#include "ets_interface.h"
#include "file_path_utils.h"
#include "hilog_tag_wrapper.h"
#include "hdc_register.h"
#include "hybrid_js_module_reader.h"
#include "nocopyable.h"
#include "parameters.h"
#include "static_core/plugins/ets/runtime/ets_namespace_manager.h"
#ifdef SUPPORT_SCREEN
#include "ace_forward_compatibility.h"
#include "arkts_module_preloader.h"
#include "declarative_module_preloader.h"
#include "hot_reloader.h"
#endif //SUPPORT_SCREEN
using namespace OHOS::AbilityBase;
using Extractor = OHOS::AbilityBase::Extractor;
namespace OHOS {
namespace AbilityRuntime {
namespace {
#ifdef APP_USE_ARM64
const std::string SANDBOX_LIB_PATH = "/system/lib64";
const std::string ETS_RT_PATH = SANDBOX_LIB_PATH;
const std::string ETS_SYSLIB_PATH =
"/system/lib64:/system/lib64/platformsdk:/system/lib64/module:/system/lib64/ndk";
#else
const std::string SANDBOX_LIB_PATH = "/system/lib";
const std::string ETS_RT_PATH = SANDBOX_LIB_PATH;
const std::string ETS_SYSLIB_PATH =
"/system/lib:/system/lib/platformsdk:/system/lib/module:/system/lib/ndk";
#endif
constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/";
constexpr char SANDBOX_ARK_CACHE_PATH[] = "/data/storage/ark-cache/";
constexpr char MERGE_ABC_PATH[] = "/ets/modules_static.abc";
const char *ETS_ENV_LIBNAME = "libets_environment.z.so";
const char *ETS_ENV_REGISTER_FUNCS = "OHOS_ETS_ENV_RegisterFuncs";
static void HandleOhmUrlBase(std::string &base)
{
// <dir1>/<dir2>/ => <dir1>.<dir2>.
std::replace(base.begin(), base.end(), '/', '.');
}
ETSEnvFuncs *g_etsEnvFuncs = nullptr;
bool RegisterETSEnvFuncs()
{
if (g_etsEnvFuncs != nullptr) {
return true;
}
auto handle = dlopen(ETS_ENV_LIBNAME, RTLD_LAZY);
if (!handle) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "dlopen failed %{public}s, %{public}s", ETS_ENV_LIBNAME, dlerror());
return false;
}
auto symbol = dlsym(handle, ETS_ENV_REGISTER_FUNCS);
if (!symbol) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "dlsym failed %{public}s, %{public}s", ETS_ENV_REGISTER_FUNCS, dlerror());
dlclose(handle);
return false;
}
auto func = reinterpret_cast<ETSEnvFuncs* (*)()>(symbol);
g_etsEnvFuncs = func();
return true;
}
class EtsAppLibNamespaceMgr : public std::enable_shared_from_this<EtsAppLibNamespaceMgr>, public NoCopyable {
public:
EtsAppLibNamespaceMgr(const AppLibPathMap& appLibPaths, bool isSystemApp)
: isSystemApp_(isSystemApp), appLibPathMap_(appLibPaths)
{
}
bool CreateNamespace(const std::string& bundleModuleName, std::string &nsName)
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "Create app ns: %{public}s", bundleModuleName.c_str());
if (bundleModuleName.empty()) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "empty bundleModuleName");
return false;
}
auto appLibPath = appLibPathMap_.find(bundleModuleName);
if (appLibPath == appLibPathMap_.end()) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "not found app lib path: %{public}s", bundleModuleName.c_str());
return false;
}
auto moduleManager = NativeModuleManager::GetInstance();
if (moduleManager == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null moduleManager");
return false;
}
moduleManager->SetAppLibPath(appLibPath->first, appLibPath->second, isSystemApp_);
return moduleManager->GetLdNamespaceName(appLibPath->first, nsName);
}
private:
bool isSystemApp_ = false;
AppLibPathMap appLibPathMap_;
};
std::shared_ptr<EtsAppLibNamespaceMgr> g_etsAppLibNamespaceMgr;
} // namespace
std::unique_ptr<ETSRuntime> ETSRuntime::PreFork(const Options &options,
std::unique_ptr<Runtime> &jsRuntime, bool isMove)
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "PreFork begin");
std::unique_ptr<ETSRuntime> instance = std::make_unique<ETSRuntime>();
if (!instance->Initialize(options, jsRuntime, isMove)) {
return std::unique_ptr<ETSRuntime>();
}
return instance;
}
bool ETSRuntime::PostFork(const Options &options, std::unique_ptr<Runtime> &jsRuntime, bool isMove)
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "PostFork begin");
codePath_ = options.codePath;
if (g_etsEnvFuncs == nullptr ||
g_etsEnvFuncs->PostFork == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or PostFork");
return false;
}
napi_env napiEnv = nullptr;
if (jsRuntime != nullptr) {
napiEnv = static_cast<AbilityRuntime::JsRuntime *>(jsRuntime.get())->GetNapiEnv();
auto vm = static_cast<JsRuntime *>(jsRuntime.get())->GetEcmaVm();
panda::JSNApi::SetHostResolveBufferTrackerForHybridApp(
vm, HybridJsModuleReader(options.bundleName, options.hapPath, options.isUnique));
}
if (isMove) {
if (jsRuntime != nullptr) {
jsRuntime_ = std::move(jsRuntime);
}
}
std::string aotFilePath = "";
if (!options.arkNativeFilePath.empty()) {
aotFilePath = SANDBOX_ARK_CACHE_PATH + options.arkNativeFilePath + options.moduleName + ".an";
}
g_etsEnvFuncs->PostFork(reinterpret_cast<void *>(napiEnv), aotFilePath, options.appInnerHspPathList,
options.commonHspBundleInfos, options.eventRunner);
return true;
}
std::unique_ptr<ETSRuntime> ETSRuntime::Create(const Options &options,
std::unique_ptr<Runtime> &jsRuntime, bool isMove)
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "Create called");
if (!RegisterETSEnvFuncs()) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "RegisterETSEnvFuncs failed");
return std::unique_ptr<ETSRuntime>();
}
if (g_etsEnvFuncs == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs");
return std::unique_ptr<ETSRuntime>();
}
if (jsRuntime == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null jsRuntime");
return std::unique_ptr<ETSRuntime>();
}
std::unique_ptr<ETSRuntime> instance;
auto preloadedInstance = Runtime::GetPreloaded(Language::ETS);
#ifdef SUPPORT_SCREEN
// reload ace if compatible mode changes
if (Ace::AceForwardCompatibility::PipelineChanged() && preloadedInstance) {
preloadedInstance.reset();
}
#endif
if (preloadedInstance && preloadedInstance->GetLanguage() == Runtime::Language::ETS) {
instance.reset(static_cast<ETSRuntime *>(preloadedInstance.release()));
} else {
instance = PreFork(options, jsRuntime, isMove);
}
if (instance != nullptr && !options.preload) {
instance->PostFork(options, jsRuntime, isMove);
}
return instance;
}
void ETSRuntime::SetAppLibPath(const AppLibPathMap& appLibPaths,
const std::map<std::string, std::string>& abcPathsToBundleModuleNameMap, bool isSystemApp)
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "SetAppLibPath called");
if (!RegisterETSEnvFuncs()) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "RegisterETSEnvFuncs failed");
return;
}
if (g_etsEnvFuncs == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs");
return;
}
if (g_etsEnvFuncs->InitETSSDKNS == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null InitETSSDKNS");
return;
}
g_etsEnvFuncs->InitETSSDKNS(ETS_RT_PATH);
if (g_etsEnvFuncs->InitETSSysNS == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null InitETSSysNS");
return;
}
g_etsEnvFuncs->InitETSSysNS(ETS_SYSLIB_PATH);
if (g_etsEnvFuncs->SetAppLibPath == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null SetAppLibPath");
return;
}
g_etsAppLibNamespaceMgr = std::make_shared<EtsAppLibNamespaceMgr>(appLibPaths, isSystemApp);
std::function<bool(const std::string &bundleModuleName, std::string &namespaceName)> cb =
[weak = std::weak_ptr(g_etsAppLibNamespaceMgr)](const std::string &bundleModuleName, std::string &nsName) {
auto appLibNamespaceMgr = weak.lock();
if (appLibNamespaceMgr == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null appLibNamespaceMgr");
return false;
}
return appLibNamespaceMgr->CreateNamespace(bundleModuleName, nsName);
};
g_etsEnvFuncs->SetAppLibPath(abcPathsToBundleModuleNameMap, cb);
}
void ETSRuntime::SetExtensionApiCheckCallback(
std::function<bool(const std::string &className, const std::string &fileName)> &cb)
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "SetExtensionApiCheckCallback called");
if (!RegisterETSEnvFuncs()) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "RegisterETSEnvFuncs failed");
return;
}
if (g_etsEnvFuncs == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs");
return;
}
if (g_etsEnvFuncs->SetExtensionApiCheckCallback == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null SetExtensionApiCheckCallback");
return;
}
g_etsEnvFuncs->SetExtensionApiCheckCallback(cb);
}
bool ETSRuntime::Initialize(const Options &options, std::unique_ptr<Runtime> &jsRuntime, bool isMove)
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "Initialize called");
if (options.lang != GetLanguage()) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "language mismatch");
return false;
}
if (isMove) {
if (jsRuntime != nullptr) {
jsRuntime_ = std::move(jsRuntime);
}
}
if (!CreateEtsEnv(options)) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "CreateEtsEnv failed");
return false;
}
apiTargetVersion_ = options.apiTargetVersion;
TAG_LOGD(AAFwkTag::ETSRUNTIME, "Initialize: %{public}d", apiTargetVersion_);
#ifdef SUPPORT_SCREEN
auto aniEngine = GetAniEnv();
if (aniEngine == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "GetAniEnv failed");
return false;
}
OHOS::Ace::ArkTSModulePreloader::Preload(aniEngine);
#endif
return true;
}
void ETSRuntime::FinishPreload()
{
if (jsRuntime_ != nullptr) {
jsRuntime_->FinishPreload();
}
if (g_etsEnvFuncs == nullptr ||
g_etsEnvFuncs->FinishPreload == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or FinishPreload");
return;
}
g_etsEnvFuncs->FinishPreload();
}
void ETSRuntime::RegisterUncaughtExceptionHandler(const EtsEnv::ETSUncaughtExceptionInfo &uncaughtExceptionInfo)
{
if (g_etsEnvFuncs == nullptr ||
g_etsEnvFuncs->RegisterUncaughtExceptionHandler == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or RegisterUncaughtExceptionHandler");
return;
}
g_etsEnvFuncs->RegisterUncaughtExceptionHandler(uncaughtExceptionInfo);
}
ETSRuntime::~ETSRuntime()
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "~ETSRuntime called");
Deinitialize();
StopDebugMode();
}
void ETSRuntime::Deinitialize()
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "Deinitialize called");
}
bool ETSRuntime::CreateEtsEnv(const Options &options)
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "CreateEtsEnv called");
if (g_etsEnvFuncs == nullptr ||
g_etsEnvFuncs->Initialize == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or Initialize");
return false;
}
if (!g_etsEnvFuncs->Initialize(options.eventRunner, options.isStartWithDebug)) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "Initialize failed");
return false;
}
return true;
}
ani_env *ETSRuntime::GetAniEnv()
{
if (g_etsEnvFuncs == nullptr ||
g_etsEnvFuncs->GetAniEnv == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or GetAniEnv");
return nullptr;
}
return g_etsEnvFuncs->GetAniEnv();
}
void ETSRuntime::PreloadModule(const std::string &moduleName, const std::string &hapPath,
bool isEsMode, bool useCommonTrunk)
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "moduleName: %{public}s", moduleName.c_str());
if (g_etsEnvFuncs == nullptr ||
g_etsEnvFuncs->PreloadModule == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or PreloadModule");
return;
}
std::string modulePath = BUNDLE_INSTALL_PATH + moduleName + MERGE_ABC_PATH;
if (!g_etsEnvFuncs->PreloadModule(modulePath)) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "PreloadModule failed");
}
return;
}
std::unique_ptr<AppExecFwk::ETSNativeReference> ETSRuntime::LoadModule(const std::string &moduleName,
const std::string &modulePath, const std::string &hapPath, bool esmodule, bool useCommonChunk,
const std::string &srcEntrance)
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "LoadModule(%{public}s, %{public}s, %{public}s, %{public}s)",
moduleName.c_str(), modulePath.c_str(), hapPath.c_str(), srcEntrance.c_str());
std::string path = moduleName;
auto pos = path.find("::");
if (pos != std::string::npos) {
path.erase(pos, path.size() - pos);
moduleName_ = path;
}
TAG_LOGD(AAFwkTag::ETSRUNTIME, "moduleName_(%{public}s, path %{public}s",
moduleName_.c_str(), path.c_str());
std::string fileName;
if (!hapPath.empty()) {
fileName.append(codePath_).append(Constants::FILE_SEPARATOR).append(modulePath);
std::regex pattern(std::string(Constants::FILE_DOT) + std::string(Constants::FILE_SEPARATOR));
fileName = std::regex_replace(fileName, pattern, "");
} else {
if (!MakeFilePath(codePath_, modulePath, fileName)) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "make module file path: %{public}s failed", modulePath.c_str());
return nullptr;
}
}
std::unique_ptr<AppExecFwk::ETSNativeReference> etsNativeReference = LoadEtsModule(moduleName, fileName,
hapPath, srcEntrance);
return etsNativeReference;
}
std::unique_ptr<AppExecFwk::ETSNativeReference> ETSRuntime::LoadEtsModule(const std::string &moduleName,
const std::string &fileName, const std::string &hapPath, const std::string &srcEntrance)
{
if (g_etsEnvFuncs == nullptr ||
g_etsEnvFuncs->LoadModule == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or LoadModule");
return std::unique_ptr<AppExecFwk::ETSNativeReference>();
}
std::string modulePath = BUNDLE_INSTALL_PATH + moduleName_ + MERGE_ABC_PATH;
std::string entryPath = HandleOhmUrlSrcEntry(srcEntrance);
void *cls = nullptr;
void *obj = nullptr;
void *ref = nullptr;
if (!g_etsEnvFuncs->LoadModule(modulePath, entryPath, cls, obj, ref)) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "LoadModule failed");
return std::unique_ptr<AppExecFwk::ETSNativeReference>();
}
auto etsNativeReference = std::make_unique<AppExecFwk::ETSNativeReference>();
etsNativeReference->aniCls = reinterpret_cast<ani_class>(cls);
etsNativeReference->aniObj = reinterpret_cast<ani_object>(obj);
etsNativeReference->aniRef = reinterpret_cast<ani_ref>(ref);
return etsNativeReference;
}
bool ETSRuntime::HandleUncaughtError()
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "HandleUncaughtError called");
if (g_etsEnvFuncs == nullptr ||
g_etsEnvFuncs->HandleUncaughtError == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or HandleUncaughtError");
return false;
}
g_etsEnvFuncs->HandleUncaughtError();
return true;
}
const std::unique_ptr<AbilityRuntime::Runtime> &ETSRuntime::GetJsRuntime() const
{
return jsRuntime_;
}
std::unique_ptr<AbilityRuntime::Runtime> ETSRuntime::MoveJsRuntime()
{
return std::move(jsRuntime_);
}
void ETSRuntime::PreloadSystemModule(const std::string &moduleName)
{
if (jsRuntime_ != nullptr) {
jsRuntime_->PreloadSystemModule(moduleName);
}
}
void ETSRuntime::SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate> moduleCheckerDelegate) const
{
if (jsRuntime_ != nullptr) {
jsRuntime_->SetModuleLoadChecker(moduleCheckerDelegate);
}
}
std::string ETSRuntime::HandleOhmUrlSrcEntry(const std::string &srcEntry)
{
size_t lastSlashPos = srcEntry.rfind('/');
if (lastSlashPos == std::string::npos) {
std::string fileName = srcEntry;
// If there is no slash, the entire string is processed directly.
HandleOhmUrlFileName(fileName);
return fileName;
}
std::string base = srcEntry.substr(0, lastSlashPos + 1);
HandleOhmUrlBase(base);
std::string fileName = srcEntry.substr(lastSlashPos + 1);
HandleOhmUrlFileName(fileName);
return base + fileName;
}
void ETSRuntime::HandleOhmUrlFileName(std::string &fileName)
{
size_t colonPos = fileName.rfind(':');
if (colonPos != std::string::npos) {
// <fileName>:<className> => <fileName>.<className>
fileName.replace(colonPos, 1, ".");
} else {
// <fileName> => <fileName>.<fileName>
fileName = fileName + "." + fileName;
}
}
bool ETSRuntime::PreloadSystemClass(const char *className)
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "PreloadSystemClass called");
if (g_etsEnvFuncs == nullptr ||
g_etsEnvFuncs->PreloadSystemClass == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or PreloadSystemClass");
return false;
}
g_etsEnvFuncs->PreloadSystemClass(className);
return true;
}
void ETSRuntime::StartDebugMode(const DebugOption dOption)
{
TAG_LOGD(AAFwkTag::ETSRUNTIME, "localDebug %{public}d", dOption.isDebugFromLocal);
if (!dOption.isDebugFromLocal && !dOption.isDeveloperMode) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "developer Mode false");
return;
}
// Set instance id to tid after the first instance.
instanceId_ = static_cast<uint32_t>(getproctid());
bool isStartWithDebug = dOption.isStartWithDebug;
bool isDebugApp = dOption.isDebugApp;
std::string appProvisionType = dOption.appProvisionType;
TAG_LOGD(AAFwkTag::ETSRUNTIME, "Ark VM is starting debug mode [%{public}s]", isStartWithDebug ? "break" : "normal");
const std::string bundleName = dOption.bundleName;
uint32_t instanceId = instanceId_;
std::string inputProcessName = bundleName != dOption.processName ? dOption.processName : "";
HdcRegister::DebugRegisterMode debugMode = HdcRegister::DebugRegisterMode::HDC_DEBUG_REG;
HdcRegister::Get().StartHdcRegister(bundleName, inputProcessName, isDebugApp, debugMode,
[bundleName, isStartWithDebug, instanceId, isDebugApp, appProvisionType]
(int socketFd, std::string option) {
TAG_LOGI(AAFwkTag::ETSRUNTIME, "HdcRegister msg, fd= %{public}d, option= %{public}s", socketFd, option.c_str());
// system is debuggable when const.secure is false and const.debuggable is true
bool isSystemDebuggable = system::GetBoolParameter("const.secure", true) == false &&
system::GetBoolParameter("const.debuggable", false) == true;
// Don't start any server if (system not in debuggable mode) and app is release version
// Starting ConnectServer in release app on debuggable system is only for debug mode, not for profiling mode.
if ((!isSystemDebuggable) && appProvisionType == AppExecFwk::Constants::APP_PROVISION_TYPE_RELEASE) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "not support release app");
return;
}
if (option.find(DEBUGGER) == std::string::npos) {
// if has old connect server, stop it
if (g_etsEnvFuncs == nullptr || g_etsEnvFuncs->BroadcastAndConnect == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or BroadcastAndConnect");
return;
}
g_etsEnvFuncs->BroadcastAndConnect(bundleName, socketFd);
} else {
if (appProvisionType == AppExecFwk::Constants::APP_PROVISION_TYPE_RELEASE) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "not support release app");
return;
}
if (g_etsEnvFuncs == nullptr || g_etsEnvFuncs->StartDebuggerForSocketPair == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or StartDebuggerForSocketPair");
return;
}
g_etsEnvFuncs->StartDebuggerForSocketPair(option, socketFd);
}
});
DebuggerConnectionHandler(isDebugApp, isStartWithDebug);
}
void ETSRuntime::DebuggerConnectionHandler(bool isDebugApp, bool isStartWithDebug)
{
auto dTask = nullptr;
if (jsRuntime_ == nullptr) {
TAG_LOGD(AAFwkTag::ETSRUNTIME, "jsRuntime_ is nullptr");
return;
}
if (g_etsEnvFuncs == nullptr || g_etsEnvFuncs->NotifyDebugMode == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs or NotifyDebugMode");
return;
}
if (jsRuntime_ == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null js runtime");
return;
}
auto &jsRuntimePoint = (static_cast<AbilityRuntime::JsRuntime &>(*jsRuntime_));
auto vm = jsRuntimePoint.GetEcmaVm();
if (vm == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null js vm");
return;
}
g_etsEnvFuncs->NotifyDebugMode(getproctid(), instanceId_, isStartWithDebug, vm);
}
void ETSRuntime::StopDebugMode()
{
if (g_etsEnvFuncs == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null g_etsEnvFuncs");
return;
}
if (g_etsEnvFuncs->RemoveInstance == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null RemoveInstance");
return;
}
g_etsEnvFuncs->RemoveInstance(instanceId_);
if (g_etsEnvFuncs->StopDebugMode == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null StopDebugMode");
return;
}
if (jsRuntime_ == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null js runtime");
return;
}
auto &jsRuntimePoint = (static_cast<AbilityRuntime::JsRuntime &>(*jsRuntime_));
auto vm = jsRuntimePoint.GetEcmaVm();
if (vm == nullptr) {
TAG_LOGE(AAFwkTag::ETSRUNTIME, "null js vm");
return;
}
g_etsEnvFuncs->StopDebugMode(vm);
}
void ETSRuntime::SetJsRuntime(std::unique_ptr<AbilityRuntime::Runtime> &jsRuntime)
{
jsRuntime_ = std::move(jsRuntime);
}
} // namespace AbilityRuntime
} // namespace OHOS