1eace7efcSopenharmony_ci/* 2eace7efcSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 3eace7efcSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4eace7efcSopenharmony_ci * you may not use this file except in compliance with the License. 5eace7efcSopenharmony_ci * You may obtain a copy of the License at 6eace7efcSopenharmony_ci * 7eace7efcSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8eace7efcSopenharmony_ci * 9eace7efcSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10eace7efcSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11eace7efcSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12eace7efcSopenharmony_ci * See the License for the specific language governing permissions and 13eace7efcSopenharmony_ci * limitations under the License. 14eace7efcSopenharmony_ci */ 15eace7efcSopenharmony_ci 16eace7efcSopenharmony_ci#include "cj_runtime.h" 17eace7efcSopenharmony_ci 18eace7efcSopenharmony_ci#include <dlfcn.h> 19eace7efcSopenharmony_ci#include <unistd.h> 20eace7efcSopenharmony_ci#include <filesystem> 21eace7efcSopenharmony_ci#include <regex> 22eace7efcSopenharmony_ci 23eace7efcSopenharmony_ci#include "cj_envsetup.h" 24eace7efcSopenharmony_ci#include "hilog_tag_wrapper.h" 25eace7efcSopenharmony_ci#include "hdc_register.h" 26eace7efcSopenharmony_ci#include "connect_server_manager.h" 27eace7efcSopenharmony_ci 28eace7efcSopenharmony_ciusing namespace OHOS::AbilityRuntime; 29eace7efcSopenharmony_ci 30eace7efcSopenharmony_ci#ifdef APP_USE_ARM64 31eace7efcSopenharmony_ci#define APP_LIB_NAME "arm64" 32eace7efcSopenharmony_ci#elif defined(APP_USE_ARM) 33eace7efcSopenharmony_ci#define APP_LIB_NAME "arm" 34eace7efcSopenharmony_ci#elif defined(APP_USE_X86_64) 35eace7efcSopenharmony_ci#define APP_LIB_NAME "x86_64" 36eace7efcSopenharmony_ci#else 37eace7efcSopenharmony_ci#error unsupported platform 38eace7efcSopenharmony_ci#endif 39eace7efcSopenharmony_ci 40eace7efcSopenharmony_cinamespace { 41eace7efcSopenharmony_ciconst std::string DEBUGGER = "@Debugger"; 42eace7efcSopenharmony_ciconst std::string SANDBOX_LIB_PATH = "/data/storage/el1/bundle/libs/" APP_LIB_NAME; 43eace7efcSopenharmony_ciconst std::string CJ_RT_PATH = SANDBOX_LIB_PATH + "/runtime"; 44eace7efcSopenharmony_ciconst std::string CJ_LIB_PATH = SANDBOX_LIB_PATH + "/ohos"; 45eace7efcSopenharmony_ciconst std::string CJ_SYSLIB_PATH = "/system/lib64:/system/lib64/platformsdk:/system/lib64/module:/system/lib64/ndk"; 46eace7efcSopenharmony_ciconst std::string CJ_CHIPSDK_PATH = "/system/lib64/chipset-pub-sdk"; 47eace7efcSopenharmony_ci} // namespace 48eace7efcSopenharmony_ci 49eace7efcSopenharmony_ci#define LIB_NAME "libcj_environment.z.so" 50eace7efcSopenharmony_ci#define GET_ENV_INS_NAME "OHOS_GetCJEnvInstance" 51eace7efcSopenharmony_ci 52eace7efcSopenharmony_cinamespace OHOS { 53eace7efcSopenharmony_ciCJEnvMethods* CJEnv::LoadInstance() 54eace7efcSopenharmony_ci{ 55eace7efcSopenharmony_ci auto handle = dlopen(LIB_NAME, RTLD_NOW); 56eace7efcSopenharmony_ci if (!handle) { 57eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "dlopen failed %{public}s, %{public}s", LIB_NAME, dlerror()); 58eace7efcSopenharmony_ci return nullptr; 59eace7efcSopenharmony_ci } 60eace7efcSopenharmony_ci auto symbol = dlsym(handle, GET_ENV_INS_NAME); 61eace7efcSopenharmony_ci if (!symbol) { 62eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "dlsym failed %{public}s, %{public}s", GET_ENV_INS_NAME, dlerror()); 63eace7efcSopenharmony_ci dlclose(handle); 64eace7efcSopenharmony_ci return nullptr; 65eace7efcSopenharmony_ci } 66eace7efcSopenharmony_ci auto func = reinterpret_cast<CJEnvMethods* (*)()>(symbol); 67eace7efcSopenharmony_ci return func(); 68eace7efcSopenharmony_ci} 69eace7efcSopenharmony_ci} 70eace7efcSopenharmony_ciAppLibPathVec CJRuntime::appLibPaths_; 71eace7efcSopenharmony_ci 72eace7efcSopenharmony_cistd::string CJRuntime::packageName_; 73eace7efcSopenharmony_ci 74eace7efcSopenharmony_cistd::unique_ptr<CJRuntime> CJRuntime::Create(const Options& options) 75eace7efcSopenharmony_ci{ 76eace7efcSopenharmony_ci auto instance = std::make_unique<CJRuntime>(); 77eace7efcSopenharmony_ci if (!instance || !instance->Initialize(options)) { 78eace7efcSopenharmony_ci return nullptr; 79eace7efcSopenharmony_ci } 80eace7efcSopenharmony_ci return instance; 81eace7efcSopenharmony_ci} 82eace7efcSopenharmony_ci 83eace7efcSopenharmony_civoid CJRuntime::SetAppLibPath(const AppLibPathMap& appLibPaths) 84eace7efcSopenharmony_ci{ 85eace7efcSopenharmony_ci std::string appPath = ""; 86eace7efcSopenharmony_ci for (const auto& kv : appLibPaths) { 87eace7efcSopenharmony_ci for (const auto& libPath : kv.second) { 88eace7efcSopenharmony_ci TAG_LOGD(AAFwkTag::CJRUNTIME, "SetCJAppLibPath: %{public}s.", libPath.c_str()); 89eace7efcSopenharmony_ci CJRuntime::appLibPaths_.emplace_back(libPath); 90eace7efcSopenharmony_ci appPath += appPath.empty() ? libPath : ":" + libPath; 91eace7efcSopenharmony_ci } 92eace7efcSopenharmony_ci } 93eace7efcSopenharmony_ci auto cjEnv = OHOS::CJEnv::LoadInstance(); 94eace7efcSopenharmony_ci if (cjEnv == nullptr) { 95eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "CJEnv LoadInstance failed."); 96eace7efcSopenharmony_ci return; 97eace7efcSopenharmony_ci } 98eace7efcSopenharmony_ci cjEnv->initCJChipSDKNS(CJ_CHIPSDK_PATH); 99eace7efcSopenharmony_ci cjEnv->initCJAppNS(appPath); 100eace7efcSopenharmony_ci cjEnv->initCJSDKNS(CJ_RT_PATH + ":" + CJ_LIB_PATH); 101eace7efcSopenharmony_ci cjEnv->initCJSysNS(CJ_SYSLIB_PATH); 102eace7efcSopenharmony_ci} 103eace7efcSopenharmony_ci 104eace7efcSopenharmony_cibool CJRuntime::Initialize(const Options& options) 105eace7efcSopenharmony_ci{ 106eace7efcSopenharmony_ci if (options.lang != GetLanguage()) { 107eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "CJRuntime Initialize fail, language mismatch"); 108eace7efcSopenharmony_ci return false; 109eace7efcSopenharmony_ci } 110eace7efcSopenharmony_ci auto cjEnv = OHOS::CJEnv::LoadInstance(); 111eace7efcSopenharmony_ci if (cjEnv == nullptr) { 112eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "CJEnv LoadInstance failed."); 113eace7efcSopenharmony_ci return false; 114eace7efcSopenharmony_ci } 115eace7efcSopenharmony_ci if (!cjEnv->startRuntime()) { 116eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "start cj runtime failed"); 117eace7efcSopenharmony_ci return false; 118eace7efcSopenharmony_ci } 119eace7efcSopenharmony_ci if (!cjEnv->startUIScheduler()) { 120eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "start cj ui context failed"); 121eace7efcSopenharmony_ci return false; 122eace7efcSopenharmony_ci } 123eace7efcSopenharmony_ci if (!LoadCJAppLibrary(CJRuntime::appLibPaths_)) { 124eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "CJRuntime::Initialize fail, load app library fail."); 125eace7efcSopenharmony_ci return false; 126eace7efcSopenharmony_ci } 127eace7efcSopenharmony_ci bundleName_ = options.bundleName; 128eace7efcSopenharmony_ci instanceId_ = static_cast<uint32_t>(getproctid()); 129eace7efcSopenharmony_ci return true; 130eace7efcSopenharmony_ci} 131eace7efcSopenharmony_ci 132eace7efcSopenharmony_civoid CJRuntime::RegisterUncaughtExceptionHandler(const CJUncaughtExceptionInfo& uncaughtExceptionInfo) 133eace7efcSopenharmony_ci{ 134eace7efcSopenharmony_ci auto cjEnv = OHOS::CJEnv::LoadInstance(); 135eace7efcSopenharmony_ci if (cjEnv == nullptr) { 136eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "CJEnv LoadInstance failed."); 137eace7efcSopenharmony_ci return; 138eace7efcSopenharmony_ci } 139eace7efcSopenharmony_ci cjEnv->registerCJUncaughtExceptionHandler(uncaughtExceptionInfo); 140eace7efcSopenharmony_ci} 141eace7efcSopenharmony_ci 142eace7efcSopenharmony_cibool CJRuntime::IsCJAbility(const std::string& info) 143eace7efcSopenharmony_ci{ 144eace7efcSopenharmony_ci // in cj application, the srcEntry format should be packageName.AbilityClassName. 145eace7efcSopenharmony_ci std::string pattern = "^([a-zA-Z0-9_]+\\.)+[a-zA-Z0-9_]+$"; 146eace7efcSopenharmony_ci return std::regex_match(info, std::regex(pattern)); 147eace7efcSopenharmony_ci} 148eace7efcSopenharmony_ci 149eace7efcSopenharmony_cibool CJRuntime::LoadCJAppLibrary(const AppLibPathVec& appLibPaths) 150eace7efcSopenharmony_ci{ 151eace7efcSopenharmony_ci auto cjEnv = OHOS::CJEnv::LoadInstance(); 152eace7efcSopenharmony_ci if (cjEnv == nullptr) { 153eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "CJEnv LoadInstance failed."); 154eace7efcSopenharmony_ci return false; 155eace7efcSopenharmony_ci } 156eace7efcSopenharmony_ci void* handle = nullptr; 157eace7efcSopenharmony_ci // According to the OHOS rule, the format of the SO name is as follows 158eace7efcSopenharmony_ci auto targetSoName = "lib" + packageName_ + ".so"; 159eace7efcSopenharmony_ci 160eace7efcSopenharmony_ci for (const auto& libPath : appLibPaths) { 161eace7efcSopenharmony_ci for (auto& itor : std::filesystem::directory_iterator(libPath)) { 162eace7efcSopenharmony_ci // According to the convention, the names of cj generated products must contain the following keywords 163eace7efcSopenharmony_ci if (itor.path().string().find(targetSoName) == std::string::npos) { 164eace7efcSopenharmony_ci continue; 165eace7efcSopenharmony_ci } 166eace7efcSopenharmony_ci handle = cjEnv->loadCJLibrary(itor.path().c_str()); 167eace7efcSopenharmony_ci if (handle == nullptr) { 168eace7efcSopenharmony_ci char* errMsg = dlerror(); 169eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, 170eace7efcSopenharmony_ci "Failed to load %{public}s : reason: %{public}s.", itor.path().c_str(), errMsg ? errMsg : "null"); 171eace7efcSopenharmony_ci return false; 172eace7efcSopenharmony_ci } 173eace7efcSopenharmony_ci } 174eace7efcSopenharmony_ci } 175eace7efcSopenharmony_ci appLibLoaded_ = true; 176eace7efcSopenharmony_ci return true; 177eace7efcSopenharmony_ci} 178eace7efcSopenharmony_ci 179eace7efcSopenharmony_civoid CJRuntime::SetPackageName(std::string srcEntryName) 180eace7efcSopenharmony_ci{ 181eace7efcSopenharmony_ci // According to the srcEntry rule in the Cangjie application, 182eace7efcSopenharmony_ci // the last '.' The previous strings were all package names 183eace7efcSopenharmony_ci packageName_ = srcEntryName.substr(0, srcEntryName.find_last_of(".")); 184eace7efcSopenharmony_ci} 185eace7efcSopenharmony_ci 186eace7efcSopenharmony_civoid CJRuntime::SetSanitizerVersion(SanitizerKind kind) 187eace7efcSopenharmony_ci{ 188eace7efcSopenharmony_ci auto cjEnv = OHOS::CJEnv::LoadInstance(); 189eace7efcSopenharmony_ci if (cjEnv == nullptr) { 190eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "CJEnv LoadInstance failed."); 191eace7efcSopenharmony_ci return; 192eace7efcSopenharmony_ci } 193eace7efcSopenharmony_ci cjEnv->setSanitizerKindRuntimeVersion(kind); 194eace7efcSopenharmony_ci} 195eace7efcSopenharmony_ci 196eace7efcSopenharmony_civoid CJRuntime::StartDebugMode(const DebugOption dOption) 197eace7efcSopenharmony_ci{ 198eace7efcSopenharmony_ci if (debugModel_) { 199eace7efcSopenharmony_ci TAG_LOGI(AAFwkTag::CJRUNTIME, "Already in debug mode"); 200eace7efcSopenharmony_ci return; 201eace7efcSopenharmony_ci } 202eace7efcSopenharmony_ci 203eace7efcSopenharmony_ci bool isStartWithDebug = dOption.isStartWithDebug; 204eace7efcSopenharmony_ci bool isDebugApp = dOption.isDebugApp; 205eace7efcSopenharmony_ci const std::string bundleName = bundleName_; 206eace7efcSopenharmony_ci std::string inputProcessName = bundleName_ != dOption.processName ? dOption.processName : ""; 207eace7efcSopenharmony_ci 208eace7efcSopenharmony_ci TAG_LOGI(AAFwkTag::CJRUNTIME, "StartDebugMode %{public}s", bundleName_.c_str()); 209eace7efcSopenharmony_ci 210eace7efcSopenharmony_ci HdcRegister::Get().StartHdcRegister(bundleName_, inputProcessName, isDebugApp, 211eace7efcSopenharmony_ci [bundleName, isStartWithDebug, isDebugApp](int socketFd, std::string option) { 212eace7efcSopenharmony_ci TAG_LOGI(AAFwkTag::CJRUNTIME, 213eace7efcSopenharmony_ci "HdcRegister callback is call, socket fd is %{public}d, option is %{public}s.", 214eace7efcSopenharmony_ci socketFd, option.c_str()); 215eace7efcSopenharmony_ci if (option.find(DEBUGGER) == std::string::npos) { 216eace7efcSopenharmony_ci if (!isDebugApp) { 217eace7efcSopenharmony_ci ConnectServerManager::Get().StopConnectServer(false); 218eace7efcSopenharmony_ci } 219eace7efcSopenharmony_ci ConnectServerManager::Get().SendDebuggerInfo(isStartWithDebug, isDebugApp); 220eace7efcSopenharmony_ci ConnectServerManager::Get().StartConnectServer(bundleName, socketFd, false); 221eace7efcSopenharmony_ci } else { 222eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "debugger service unexpected option: %{public}s", option.c_str()); 223eace7efcSopenharmony_ci } 224eace7efcSopenharmony_ci }); 225eace7efcSopenharmony_ci if (isDebugApp) { 226eace7efcSopenharmony_ci ConnectServerManager::Get().StartConnectServer(bundleName_, -1, true); 227eace7efcSopenharmony_ci } 228eace7efcSopenharmony_ci ConnectServerManager::Get().AddInstance(instanceId_, instanceId_); 229eace7efcSopenharmony_ci 230eace7efcSopenharmony_ci debugModel_ = StartDebugger(); 231eace7efcSopenharmony_ci} 232eace7efcSopenharmony_ci 233eace7efcSopenharmony_cibool CJRuntime::StartDebugger() 234eace7efcSopenharmony_ci{ 235eace7efcSopenharmony_ci auto cjEnv = OHOS::CJEnv::LoadInstance(); 236eace7efcSopenharmony_ci if (cjEnv == nullptr) { 237eace7efcSopenharmony_ci TAG_LOGE(AAFwkTag::CJRUNTIME, "CJEnv LoadInstance failed."); 238eace7efcSopenharmony_ci return false; 239eace7efcSopenharmony_ci } 240eace7efcSopenharmony_ci return cjEnv->startDebugger(); 241eace7efcSopenharmony_ci} 242eace7efcSopenharmony_ci 243eace7efcSopenharmony_civoid CJRuntime::UnLoadCJAppLibrary() 244eace7efcSopenharmony_ci{ 245eace7efcSopenharmony_ci TAG_LOGI(AAFwkTag::CJRUNTIME, "UnLoadCJAppLibrary not support yet"); 246eace7efcSopenharmony_ci} 247