* 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 "aot_args_handler.h"
#include <charconv>
#include <fcntl.h>
#include <fstream>
#include <sstream>
#include <unistd.h>
#include <sys/stat.h>
#include "aot_args_list.h"
#include "aot_args_verify.h"
#include "aot_compiler_constants.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/platform/file.h"
#ifdef ENABLE_COMPILER_SERVICE_GET_PARAMETER
#include "parameters.h"
#endif
namespace OHOS::ArkCompiler {
#ifdef ENABLE_COMPILER_SERVICE_GET_PARAMETER
const bool ARK_AOT_ENABLE_STATIC_COMPILER_DEFAULT_VALUE = true;
#endif
AOTArgsHandler::AOTArgsHandler(const AotCompilerArgs &args)
: args_(args)
{
#ifdef ENABLE_COMPILER_SERVICE_GET_PARAMETER
SetIsEnableStaticCompiler(AOTArgsParserBase::IsEnableStaticCompiler());
#endif
SetParser();
}
void AOTArgsHandler::SetParser()
{
auto parserOpt = AOTArgsParserFactory::GetParser(args_, IsEnableStaticCompiler());
if (parserOpt.has_value()) {
parser_ = std::move(parserOpt.value());
} else {
parser_ = nullptr;
}
}
int32_t AOTArgsHandler::Handle(int32_t thermalLevel)
{
if (!parser_) {
LOG_SA(ERROR) << "AOTArgsParser is null, invalid parameters";
return ERR_AOT_COMPILER_PARAM_FAILED;
}
if (!parser_->Check(args_)) {
LOG_SA(ERROR) << "Parser check validation failed";
return ERR_AOT_COMPILER_PARAM_FAILED;
}
std::lock_guard<std::mutex> lock(argsMutex_);
int32_t ret = parser_->Parse(args_, argVector_, thermalLevel);
return ret;
}
std::vector<const char*> AOTArgsHandler::GetAotArgs() const
{
std::lock_guard<std::mutex> lock(argsMutex_);
std::vector<const char*> argv;
constexpr size_t extraArgsCapacity = 4;
argv.reserve(argVector_.size() + extraArgsCapacity);
for (auto &arg : argVector_) {
argv.emplace_back(arg.c_str());
}
if (childAnFd_ >= 0 && parser_) {
anFdArg_ = Symbols::PREFIX + parser_->GetFdArgName() + Symbols::EQ
+ std::to_string(childAnFd_);
argv.emplace_back(anFdArg_.c_str());
LOG_SA(INFO) << "GetAotArgs appended " << anFdArg_;
}
if (childHapFd_ >= 0 && parser_) {
hapFdArg_ = Symbols::PREFIX + parser_->GetHapFdArgName() + Symbols::EQ
+ std::to_string(childHapFd_);
argv.emplace_back(hapFdArg_.c_str());
LOG_SA(INFO) << "GetAotArgs appended " << hapFdArg_;
}
return argv;
}
void AOTArgsHandler::GetBundleId(int32_t &bundleUid, int32_t &bundleGid) const
{
std::lock_guard<std::mutex> lock(argsMutex_);
bundleUid = args_.bundleUid;
bundleGid = args_.bundleGid;
}
std::string AOTArgsHandler::GetFileName() const
{
std::lock_guard<std::mutex> lock(argsMutex_);
return args_.anFileName;
}
std::string AOTArgsHandler::GetCodeSignArgs() const
{
std::lock_guard<std::mutex> lock(argsMutex_);
return args_.appIdentifier;
}
AotParserType AOTArgsHandler::GetParserType() const
{
if (parser_) {
return parser_->GetParserType();
}
return AotParserType::UNKNOWN;
}
bool AOTArgsHandler::IsDynamicAOT() const
{
if (!parser_) {
return false;
}
return parser_->GetParserType() == AotParserType::DYNAMIC_AOT;
}
std::string AOTArgsHandler::BuildCompilerPkgInfo(const AotCompilerArgs &args)
{
nlohmann::json pkgInfo;
pkgInfo["bundleName"] = args.bundleName;
pkgInfo["moduleName"] = args.moduleName;
pkgInfo["pkgPath"] = args.hapPath;
pkgInfo["pgoDir"] = args.pgoDir;
pkgInfo["bundleUid"] = std::to_string(args.bundleUid);
pkgInfo["processUid"] = std::to_string(args.processUid);
pkgInfo["appIdentifier"] = args.appIdentifier;
pkgInfo["isEncryptedBundle"] = std::to_string(args.isEncryptedBundle);
std::string abcName;
if (args.moduleArkTSMode == ArgsIdx::ARKTS_DYNAMIC) {
abcName = ArgsIdx::ABC_MODULES_PATH;
} else {
abcName = ArgsIdx::ABC_MODULES_STATIC_PATH;
}
pkgInfo["abcName"] = abcName;
return pkgInfo.dump();
}
std::string AOTArgsHandler::BuildExternalPkgInfo(const AotCompilerArgs &args)
{
nlohmann::json extPkgArray = nlohmann::json::array();
for (const auto &hsp : args.hspModules) {
nlohmann::json hspObj;
hspObj["bundleName"] = hsp.bundleName;
hspObj["moduleName"] = hsp.moduleName;
hspObj["pkgPath"] = hsp.hapPath;
hspObj["moduleArkTSMode"] = hsp.moduleArkTSMode;
std::string hspAbcName = (hsp.moduleArkTSMode == ArgsIdx::ARKTS_DYNAMIC)
? ArgsIdx::ABC_MODULES_PATH : ArgsIdx::ABC_MODULES_STATIC_PATH;
hspObj["abcName"] = hspAbcName;
extPkgArray.push_back(hspObj);
}
return extPkgArray.dump();
}
std::string AOTArgsHandler::BuildExternalPkgInfo(const AotCompilerArgs &args,
const std::map<std::string, int32_t> &hspFdMap)
{
nlohmann::json extPkgArray = nlohmann::json::array();
for (const auto &hsp : args.hspModules) {
nlohmann::json hspObj;
hspObj["bundleName"] = hsp.bundleName;
hspObj["moduleName"] = hsp.moduleName;
hspObj["pkgPath"] = hsp.hapPath;
hspObj["moduleArkTSMode"] = hsp.moduleArkTSMode;
std::string hspAbcName = (hsp.moduleArkTSMode == ArgsIdx::ARKTS_DYNAMIC)
? ArgsIdx::ABC_MODULES_PATH : ArgsIdx::ABC_MODULES_STATIC_PATH;
hspObj["abcName"] = hspAbcName;
auto it = hspFdMap.find(hsp.hapPath);
if (it != hspFdMap.end() && it->second >= 0) {
hspObj["hapFd"] = std::to_string(it->second);
}
extPkgArray.push_back(hspObj);
}
return extPkgArray.dump();
}
void AOTArgsHandler::UpdateExternalPkgInfo(const std::string &extPkgJson)
{
std::lock_guard<std::mutex> lock(argsMutex_);
std::string prefix = Symbols::PREFIX + ArgsIdx::COMPILER_EXTERNAL_PKG_INFO + Symbols::EQ;
for (auto &arg : argVector_) {
if (arg.compare(0, prefix.size(), prefix) == 0) {
arg = prefix + extPkgJson;
LOG_SA(INFO) << "Updated external pkg info with HSP fd data";
return;
}
}
if (!extPkgJson.empty() && extPkgJson != ArgsIdx::EMPTY_JSON_ARRAY) {
argVector_.emplace_back(prefix + extPkgJson);
}
}
int32_t AOTArgsParser::Parse(AotCompilerArgs &args, std::vector<std::string> &argVector,
int32_t thermalLevel)
{
std::string abcPath = args.sysCompPath.empty() ? args.abcPath : args.sysCompPath;
if (abcPath.empty()) {
LOG_SA(ERROR) << "aot compiler args parsing error: abcPath is empty";
return ERR_AOT_COMPILER_PARAM_FAILED;
}
argVector.clear();
argVector.emplace_back(AOT_EXE);
AddThermalLevelArg(argVector, thermalLevel);
BuildDynamicCompilerArgs(args, argVector);
#ifdef ENABLE_COMPILER_SERVICE_GET_PARAMETER
SetEnableCodeCommentBySysParam(argVector);
SetAnFileMaxSizeBySysParam(argVector);
#endif
argVector.emplace_back(abcPath);
return ERR_OK;
}
void AOTArgsParser::BuildDynamicCompilerArgs(const AotCompilerArgs &args, std::vector<std::string> &argVector)
{
std::string aotFile = args.outputPath.empty() ? "" : args.outputPath + "/" + args.moduleName;
if (!aotFile.empty()) {
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::AOT_FILE + Symbols::EQ + aotFile);
}
if (!args.compileMode.empty()) {
argVector.emplace_back(
Symbols::PREFIX + ArgsIdx::TARGET_COMPILER_MODE + Symbols::EQ + args.compileMode);
}
if (!args.optBCRangeList.empty()) {
argVector.emplace_back(
Symbols::PREFIX + ArgsIdx::COMPILER_OPT_BC_RANGE + Symbols::EQ + args.optBCRangeList);
}
argVector.emplace_back(
Symbols::PREFIX + ArgsIdx::COMPILER_DEVICE_STATE + Symbols::EQ + std::to_string(args.isScreenOff));
argVector.emplace_back(
Symbols::PREFIX + ArgsIdx::COMPILER_BASELINE_PGO + Symbols::EQ +
std::to_string(args.isEnableBaselinePgo));
argVector.emplace_back(
Symbols::PREFIX + ArgsIdx::COMPILER_PKG_INFO + Symbols::EQ + AOTArgsHandler::BuildCompilerPkgInfo(args));
std::string extPkgInfo = AOTArgsHandler::BuildExternalPkgInfo(args);
if (!extPkgInfo.empty() && extPkgInfo != ArgsIdx::EMPTY_JSON_ARRAY) {
argVector.emplace_back(
Symbols::PREFIX + ArgsIdx::COMPILER_EXTERNAL_PKG_INFO + Symbols::EQ + extPkgInfo);
}
}
bool AOTArgsParserBase::Check(const AotCompilerArgs &args)
{
switch (GetParserType()) {
case AotParserType::DYNAMIC_AOT:
return AotArgsVerify::CheckAOTArgs(args);
case AotParserType::STATIC_AOT:
return AotArgsVerify::CheckStaticAotArgs(args);
case AotParserType::FRAMEWORK_STATIC_AOT:
return AotArgsVerify::CheckFrameworkStaticAotArgs(args);
default:
LOG_SA(ERROR) << "Unknown parser type in Check";
return false;
}
}
#ifdef ENABLE_COMPILER_SERVICE_GET_PARAMETER
void AOTArgsParser::SetAnFileMaxSizeBySysParam(std::vector<std::string> &argVector)
{
int anFileMaxSize = OHOS::system::GetIntParameter<int>("ark.aot.compiler_an_file_max_size", -1);
if (anFileMaxSize >= 0) {
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::COMPILER_AN_FILE_MAX_SIZE + Symbols::EQ +
std::to_string(anFileMaxSize));
}
}
void AOTArgsParser::SetEnableCodeCommentBySysParam(std::vector<std::string> &argVector)
{
bool enableAotCodeComment = OHOS::system::GetBoolParameter("ark.aot.code_comment.enable", false);
if (enableAotCodeComment) {
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::COMPILER_ENABLE_AOT_CODE_COMMENT + Symbols::EQ +
"true");
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::COMPILER_LOG_OPT + Symbols::EQ + ArgsIdx::LOG_OPT_ALLASM);
}
}
bool AOTArgsParserBase::IsEnableStaticCompiler()
{
bool enable = OHOS::system::GetBoolParameter("ark.aot.enable_static_compiler",
ARK_AOT_ENABLE_STATIC_COMPILER_DEFAULT_VALUE);
LOG_SA(INFO) << "enable static compiler switch is : " << enable;
return enable;
}
#endif
void AOTArgsParser::AddThermalLevelArg(std::vector<std::string> &argVector, int32_t thermalLevel)
{
std::string thermalLevelArg = Symbols::PREFIX + std::string("compiler-thermal-level") + Symbols::EQ
+ std::to_string(thermalLevel);
argVector.emplace_back(thermalLevelArg);
}
void StaticAOTArgsParser::ProcessArgs(const AotCompilerArgs &args, std::string &anfilePath, bool &partialMode,
std::vector<std::string> &argVector)
{
std::string aotFile = args.outputPath.empty() ? "" : args.outputPath + "/" + args.moduleName;
anfilePath = aotFile;
if (!anfilePath.empty()) {
std::string anFileName = anfilePath + ArgsIdx::AN_SUFFIX;
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::PAOC_OUTPUT + Symbols::EQ + anFileName);
}
if (args.compileMode == ArgsIdx::PARTIAL) {
partialMode = true;
}
if (!args.optBCRangeList.empty()) {
argVector.emplace_back(
Symbols::PREFIX + ArgsIdx::COMPILER_OPT_BC_RANGE + Symbols::EQ + args.optBCRangeList);
}
}
void StaticAOTArgsParser::ProcessBlackListMethods(const std::string &bundleName, const std::string &anfilePath,
std::vector<std::string> &argVector)
{
std::string moduleName = ParseModuleName(anfilePath);
std::string blackListMethods = ParseBlackListMethods(bundleName, moduleName);
if (!blackListMethods.empty()) {
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::COMPILER_REGEX + Symbols::EQ + blackListMethods);
}
}
int32_t StaticAOTArgsParser::Parse(AotCompilerArgs &args, std::vector<std::string> &argVector,
[[maybe_unused]] int32_t thermalLevel)
{
std::string abcPath = args.sysCompPath.empty() ? args.abcPath : args.sysCompPath;
if (abcPath.empty()) {
LOG_SA(ERROR) << "aot compiler args parsing error: abcPath is empty";
return ERR_AOT_COMPILER_PARAM_FAILED;
}
if (args.bundleType == static_cast<int32_t>(BundleType::SHARED) && IsFileExists(args.anFileName)) {
LOG_SA(INFO) << "host-private shared hsp an is exist";
return ERR_AOT_COMPILER_CALL_CANCELLED;
}
argVector.clear();
argVector.emplace_back(STATIC_AOT_EXE);
for (auto &defaultArg : staticAOTDefaultArgs) {
argVector.emplace_back(defaultArg);
}
return BuildStaticCompilerArgs(args, argVector);
}
int32_t StaticAOTArgsParser::BuildStaticCompilerArgs(AotCompilerArgs &args, std::vector<std::string> &argVector)
{
std::string abcPath = args.sysCompPath.empty() ? args.abcPath : args.sysCompPath;
std::string bootfiles;
if (!ParseBootPandaFiles(bootfiles)) {
return ERR_AOT_COMPILER_PARAM_FAILED;
}
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::BOOT_PANDA_FILES + Symbols::EQ + bootfiles);
std::string anfilePath;
bool partialMode = false;
ProcessArgs(args, anfilePath, partialMode, argVector);
ProcessBlackListMethods(args.bundleName, anfilePath, argVector);
std::string location;
if (ParseLocationByBundleType(args.bundleType, abcPath, anfilePath, location) != ERR_OK) {
return ERR_AOT_COMPILER_PARAM_FAILED;
}
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::PAOC_LOCATION + Symbols::EQ + location);
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::PAOC_PANDA_FILES + Symbols::EQ + abcPath);
std::string moduleName = ParseModuleName(anfilePath);
if (partialMode && !AddProfilePathArg(argVector, args.pgoDir, moduleName)) {
return ERR_AOT_COMPILER_PARAM_FAILED;
}
return ERR_OK;
}
bool StaticAOTArgsParser::ParseBootPandaFiles(std::string &bootfiles)
{
std::ifstream inFile;
inFile.open(ArgsIdx::STATIC_BOOT_PATH, std::ios::in);
if (!inFile.is_open()) {
LOG_SA(ERROR) << "read json error";
return false;
}
nlohmann::json jsonObject = nlohmann::json::parse(inFile);
if (jsonObject.is_discarded()) {
LOG_SA(ERROR) << "json discarded error";
inFile.close();
return false;
}
if (jsonObject.is_null() || jsonObject.empty()) {
LOG_SA(ERROR) << "invalid json";
inFile.close();
return false;
}
for (const auto &[key, value] : jsonObject.items()) {
if (!value.is_null() && value.is_string()) {
std::string jsonValue = value.get<std::string>();
if (jsonValue.empty()) {
LOG_SA(ERROR) << "json value of " << key << " is empty";
continue;
}
if (!bootfiles.empty()) {
bootfiles += ":";
}
bootfiles += jsonValue.c_str();
}
}
inFile.close();
return true;
}
std::string StaticAOTArgsParser::ParseLocation(const std::string &anFilePath)
{
size_t pos = anFilePath.find_last_of("/");
if (pos == std::string::npos) {
LOG_SA(FATAL) << "aot sa parse invalid location";
}
std::string moduleName = anFilePath.substr(pos + 1);
std::string location = ArgsIdx::APP_SANDBOX_PATH_PREFIX + moduleName + ArgsIdx::ETS_PATH;
return location;
}
* Parse location for Outer Hsp
*
* Case1: hsp under /data/app/
* expected_location: /data/storage/el1/bundle/com.example.app/FLayoutCore/FLayoutCore/ets
* input_abcPath: /data/app/el1/bundle/public/com.example.app/v122000200/FLayoutCore/FLayoutCore.hsp/
* ets/modules_static.abc
*
* Case2: hsp under /system/app/
* expected_location: /system/app/shared_bundles/FlexiableLayout/FlayoutCore/ets
* input_abcPath: /system/app/shared_bundles/FlexiableLayout/FlayoutCore.hsp
*/
std::string StaticAOTArgsParser::ParseOuterHspLocation(const std::string &abcPath)
{
if (abcPath.rfind(ArgsIdx::SYS_OUTER_HSP_PATH_PREFIX, 0) == 0) {
size_t pos = abcPath.find(ArgsIdx::HSP_SUFFIX);
if (pos == std::string::npos) {
return "";
}
return abcPath.substr(0, pos) + ArgsIdx::ETS_PATH;
}
size_t hspSuffixPos = abcPath.find(ArgsIdx::HSP_SUFFIX);
if (hspSuffixPos == std::string::npos) {
return "";
}
std::string hspLocationIncludingVersionCode = ArgsIdx::APP_SANDBOX_PATH_PREFIX +
abcPath.substr(ArgsIdx::APP_ABC_PHYS_PATH_PREFIX.size(),
hspSuffixPos - ArgsIdx::APP_ABC_PHYS_PATH_PREFIX.size()) +
ArgsIdx::ETS_PATH;
std::vector<std::string> segments;
std::stringstream ss(hspLocationIncludingVersionCode);
std::string item;
while (std::getline(ss, item, '/')) {
if (!item.empty()) {
segments.push_back(item);
}
}
std::string hspLocation = "";
bool foundBundle = false;
for (size_t i = 0; i < segments.size(); ++i) {
if (!foundBundle && segments[i] == ArgsIdx::BUNDLE_PATH_SEGMENT) {
foundBundle = true;
hspLocation += "/" + segments[i];
if (i + 1 < segments.size()) {
hspLocation += "/" + segments[++i];
}
i++;
continue;
}
hspLocation += "/" + segments[i];
}
return hspLocation;
}
std::string StaticAOTArgsParser::ParseModuleName(const std::string &anFilePath)
{
size_t pos = anFilePath.find_last_of("/");
if (pos == std::string::npos) {
LOG_SA(FATAL) << "aot sa parse invalid location";
}
std::string moduleName = anFilePath.substr(pos + 1);
return moduleName;
}
int32_t StaticAOTArgsParser::ParseLocationByBundleType(int32_t bundleType, const std::string &abcPath,
const std::string &anfilePath, std::string &location)
{
if (bundleType == static_cast<int32_t>(BundleType::SHARED)) {
location = ParseOuterHspLocation(abcPath);
} else if (bundleType == static_cast<int32_t>(BundleType::APP)) {
location = ParseLocation(anfilePath);
} else {
LOG_SA(ERROR) << "bundleType invalid";
return ERR_AOT_COMPILER_PARAM_FAILED;
}
if (location.empty()) {
LOG_SA(ERROR) << "location is empty";
return ERR_AOT_COMPILER_PARAM_FAILED;
}
return ERR_OK;
}
bool StaticAOTArgsParser::AddProfilePathArg(std::vector<std::string> &argVector, const std::string &pgoDir,
const std::string &moduleName)
{
if (pgoDir.empty()) {
LOG_SA(ERROR) << "pgoDir is empty in partial mode";
return false;
}
std::string profilePath = pgoDir;
std::string profileName = profilePath + "/" + moduleName + ArgsIdx::AP_SUFFIX;
std::string pathArg = std::string("path") + Symbols::EQ + profileName;
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::PAOC_USE_PROFILE + Symbols::COLON + pathArg);
return true;
}
bool AOTArgsParserBase::ParseBlackListJson(nlohmann::json &jsonObject)
{
if (!IsFileExists(ArgsIdx::STATIC_PAOC_BLACK_LIST_PATH)) {
return false;
}
std::ifstream inFile;
inFile.open(ArgsIdx::STATIC_PAOC_BLACK_LIST_PATH, std::ios::in);
if (!inFile.is_open()) {
LOG_SA(ERROR) << "read json error";
return false;
}
std::stringstream buffer;
buffer << inFile.rdbuf();
std::string fileContent = buffer.str();
if (!nlohmann::json::accept(fileContent)) {
LOG_SA(ERROR) << "invalid json when parse profile path";
return false;
}
jsonObject = nlohmann::json::parse(fileContent);
if (jsonObject.is_discarded()) {
LOG_SA(ERROR) << "json discarded error";
inFile.close();
return false;
}
if (jsonObject.is_null()) {
LOG_SA(ERROR) << "invalid json";
inFile.close();
return false;
}
inFile.close();
return true;
}
std::vector<std::string> AOTArgsParserBase::JoinMethodList(const nlohmann::json &methodLists)
{
std::vector<std::string> methodVec;
for (size_t i = 0; i < methodLists.size(); ++i) {
if (!methodLists[i].is_string()) {
continue;
}
methodVec.emplace_back(methodLists[i].get<std::string>());
}
return methodVec;
}
std::string AOTArgsParserBase::BuildRegexPattern(const std::vector<std::string> &blacklistedMethods)
{
if (blacklistedMethods.empty()) {
return "";
}
std::string regexPattern = "^(?!(";
for (size_t i = 0; i < blacklistedMethods.size(); ++i) {
if (i > 0) {
regexPattern += "|";
}
for (char c : blacklistedMethods[i]) {
if (c == '\\' || c == '.' || c == '^' || c == '$' || c == '*' ||
c == '+' || c == '?' || c == '(' || c == ')' || c == '[' ||
c == ']' || c == '{' || c == '}' || c == '|' || c == '/') {
regexPattern += "\\";
}
regexPattern += c;
}
}
regexPattern += ")$).*";
return regexPattern;
}
bool StaticAOTArgsParser::CheckBundleNameAndModuleList(const nlohmann::json &item,
const std::string &bundleName)
{
if (!item.contains("bundleName") || !item["bundleName"].is_string()) {
return false;
}
if (item["bundleName"].get<std::string>() != bundleName) {
return false;
}
if (!item.contains("moduleLists") || !item["moduleLists"].is_array()) {
return false;
}
return true;
}
bool StaticAOTArgsParser::CheckModuleNameAndMethodList(const nlohmann::json &moduleItem,
const std::string &moduleName)
{
if (!moduleItem.contains("name") || !moduleItem["name"].is_string()) {
return false;
}
if (moduleItem["name"].get<std::string>() != moduleName) {
return false;
}
if (!moduleItem.contains("methodLists") || !moduleItem["methodLists"].is_array()) {
return false;
}
return true;
}
std::string StaticAOTArgsParser::ProcessBlackListForBundleAndModule(const nlohmann::json &jsonObject,
const std::string &bundleName,
const std::string &moduleName)
{
if (!jsonObject.contains("blackMethodList") || !jsonObject["blackMethodList"].is_array()) {
return "";
}
if (jsonObject["blackMethodList"].empty()) {
return "";
}
std::vector<std::string> blacklistedMethods;
for (const auto& item : jsonObject["blackMethodList"]) {
if (!CheckBundleNameAndModuleList(item, bundleName)) {
continue;
}
std::vector<std::string> moduleResults = ProcessMatchingModules(item, moduleName);
blacklistedMethods.insert(blacklistedMethods.end(), moduleResults.begin(), moduleResults.end());
}
if (blacklistedMethods.empty()) {
return "";
}
return AOTArgsParserBase::BuildRegexPattern(blacklistedMethods);
}
std::vector<std::string> StaticAOTArgsParser::ProcessMatchingModules(
const nlohmann::json &item,
const std::string &moduleName)
{
std::vector<std::string> resultVec;
for (const auto& moduleItem : item["moduleLists"]) {
if (!CheckModuleNameAndMethodList(moduleItem, moduleName)) {
continue;
}
const auto& methodLists = moduleItem["methodLists"];
std::vector<std::string> currentMethodVec = JoinMethodList(methodLists);
resultVec.insert(resultVec.end(), currentMethodVec.begin(), currentMethodVec.end());
}
return resultVec;
}
std::string StaticAOTArgsParser::ParseBlackListMethods(const std::string &bundleName,
const std::string &moduleName)
{
nlohmann::json jsonObject;
if (!ParseBlackListJson(jsonObject)) {
return "";
}
if (bundleName.empty()) {
return "";
}
return ProcessBlackListForBundleAndModule(jsonObject, bundleName, moduleName);
}
std::optional<std::unique_ptr<AOTArgsParserBase>> AOTArgsParserFactory::GetParser(
const AotCompilerArgs &args, bool isEnableStaticCompiler)
{
if (args.isSysComp && isEnableStaticCompiler) {
return std::make_unique<StaticFrameworkAOTArgsParser>();
}
if (args.moduleArkTSMode == ArgsIdx::ARKTS_DYNAMIC) {
LOG_SA(INFO) << "aot sa use default compiler";
return std::make_unique<AOTArgsParser>();
}
if (!isEnableStaticCompiler) {
return std::nullopt;
}
if (args.moduleArkTSMode == ArgsIdx::ARKTS_STATIC || args.moduleArkTSMode == ArgsIdx::ARKTS_HYBRID) {
return std::make_unique<StaticAOTArgsParser>();
}
LOG_SA(ERROR) << "aot sa get invalid code arkTsMode";
return std::nullopt;
}
bool AOTArgsParserBase::IsFileExists(const std::string &fileName)
{
std::string realPath;
if (!panda::ecmascript::RealPath(fileName, realPath)) {
LOG_SA(INFO) << "get real path failed:" << fileName;
return false;
}
return panda::ecmascript::FileExist(realPath.c_str());
}
int32_t StaticFrameworkAOTArgsParser::Parse(AotCompilerArgs &args, std::vector<std::string> &argVector,
[[maybe_unused]] int32_t thermalLevel)
{
std::string abcPath = args.sysCompPath.empty() ? args.abcPath : args.sysCompPath;
if (abcPath.empty()) {
LOG_SA(ERROR) << "aot compiler args parsing error: abcPath is empty";
return ERR_AOT_COMPILER_PARAM_FAILED;
}
if (IsFileExists(args.anFileName)) {
LOG_SA(INFO) << "framework's an is exist";
return ERR_AOT_COMPILER_CALL_CANCELLED;
}
argVector.clear();
argVector.emplace_back(STATIC_AOT_EXE);
args.appIdentifier = ArgsIdx::OWNERID_SHARED_TAG;
args.bundleUid = OID_SYSTEM;
args.bundleGid = OID_SYSTEM;
for (auto &defaultArg : staticFrameworkAOTDefaultArgs) {
argVector.emplace_back(defaultArg);
}
std::string fullBootfiles;
if (!ParseBootPandaFiles(fullBootfiles)) {
return ERR_AOT_COMPILER_PARAM_FAILED;
}
if (fullBootfiles.empty()) {
LOG_SA(ERROR) << "can not find paoc panda files ";
return ERR_AOT_COMPILER_PARAM_FAILED;
}
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::BOOT_PANDA_FILES + Symbols::EQ + fullBootfiles);
std::string bundleName = abcPath;
if (!args.anFileName.empty()) {
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::PAOC_OUTPUT + Symbols::EQ + args.anFileName);
}
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::PAOC_PANDA_FILES + Symbols::EQ + abcPath);
std::string blackListMethods = ParseBlackListMethods(bundleName);
if (!blackListMethods.empty()) {
argVector.emplace_back(Symbols::PREFIX + ArgsIdx::COMPILER_REGEX + Symbols::EQ + blackListMethods);
}
return ERR_OK;
}
bool StaticFrameworkAOTArgsParser::CheckBundleNameAndMethodList(const nlohmann::json &item,
const std::string &bundleName)
{
if (!item.contains("bundleName") || !item["bundleName"].is_string()) {
return false;
}
if (item["bundleName"].get<std::string>() != bundleName) {
return false;
}
if (!item.contains("methodLists") || !item["methodLists"].is_array()) {
return false;
}
return true;
}
std::string StaticFrameworkAOTArgsParser::ParseBlackListMethods(const std::string &bundleName)
{
nlohmann::json jsonObject;
if (!ParseBlackListJson(jsonObject)) {
return "";
}
std::vector<std::string> blacklistedMethods;
if (!jsonObject.contains("blackMethodList") || !jsonObject["blackMethodList"].is_array()) {
return "";
}
if (jsonObject["blackMethodList"].empty()) {
return "";
}
for (const auto& item : jsonObject["blackMethodList"]) {
if (!CheckBundleNameAndMethodList(item, bundleName)) {
continue;
}
const auto& methodLists = item["methodLists"];
std::vector<std::string> currentMethodVec = JoinMethodList(methodLists);
blacklistedMethods.insert(blacklistedMethods.end(), currentMethodVec.begin(), currentMethodVec.end());
}
if (blacklistedMethods.empty()) {
return "";
}
return AOTArgsParserBase::BuildRegexPattern(blacklistedMethods);
}
std::string StaticFrameworkAOTArgsParser::ParseFrameworkBootPandaFiles(const std::string &bootfiles,
const std::string &paocPandaFiles)
{
size_t pos = bootfiles.find(paocPandaFiles);
std::string frameworkBootPandaFiles;
if (pos != std::string::npos) {
frameworkBootPandaFiles += bootfiles.substr(0, pos + paocPandaFiles.length());
}
return frameworkBootPandaFiles;
}
}