• 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 "aot_args_handler.h"
17 
18 #include <charconv>
19 #include <cstdio>
20 #include <fstream>
21 #include <nlohmann/json.hpp>
22 
23 #include "aot_args_list.h"
24 #include "aot_compiler_constants.h"
25 #include "ecmascript/log_wrapper.h"
26 #include "ecmascript/platform/file.h"
27 
28 #ifdef ENABLE_COMPILER_SERVICE_GET_PARAMETER
29 #include "parameters.h"
30 #endif
31 
32 namespace OHOS::ArkCompiler {
33 const std::string AOT_FILE = "aot-file";
34 
35 const std::string STATIC_BOOT_PANDA_FILES = "boot-panda-files";
36 const std::string STATIC_PAOC_PANDA_FILES = "paoc-panda-files";
37 const std::string STATIC_PAOC_LOCATION = "paoc-location";
38 const std::string STATIC_PAOC_OUTPUT = "paoc-output";
39 const std::string STATIC_BOOT_PATH = "/system/framework/bootpath.json";
40 
41 const std::string ARKTS_DYNAMIC = "dynamic";
42 const std::string ARKTS_STATIC = "static";
43 const std::string AN_FILE_NAME = "anFileName";
44 const std::string ARKTS_HYBRID = "hybrid";
45 
46 const std::string AN_SUFFIX = ".an";
47 const std::string APP_SANBOX_PATH_PREFIX = "/data/storage/el1/bundle/";
48 const std::string ETS_PATH = "/ets";
49 const std::string OWNERID_SHARED_TAG = "SHARED_LIB_ID";
50 
51 #ifdef ENABLE_COMPILER_SERVICE_GET_PARAMETER
52 // Default closed, open on qiangji
53 const bool ARK_AOT_ENABLE_STATIC_COMPILER_DEFAULT_VALUE = false;
54 #endif
55 
AOTArgsHandler(const std::unordered_map<std::string,std::string> & argsMap)56 AOTArgsHandler::AOTArgsHandler(const std::unordered_map<std::string, std::string> &argsMap) : argsMap_(argsMap)
57 {
58     parser_ = *AOTArgsParserFactory::GetParser(argsMap);
59 }
60 
Handle(int32_t thermalLevel)61 int32_t AOTArgsHandler::Handle(int32_t thermalLevel)
62 {
63     if (argsMap_.empty()) {
64         LOG_SA(ERROR) << "pass empty args to aot sa";
65         return ERR_AOT_COMPILER_PARAM_FAILED;
66     }
67 
68     std::lock_guard<std::mutex> lock(hapArgsMutex_);
69     int32_t ret = parser_->Parse(argsMap_, hapArgs_, thermalLevel);
70     return ret;
71 }
72 
GetAotArgs() const73 std::vector<const char*> AOTArgsHandler::GetAotArgs() const
74 {
75     std::lock_guard<std::mutex> lock(hapArgsMutex_);
76     std::vector<const char*> argv;
77     argv.reserve(hapArgs_.argVector.size() + 1);  // 1: for nullptr
78     for (auto &arg : hapArgs_.argVector) {
79         argv.emplace_back(arg.c_str());
80     }
81 
82     return argv;
83 }
84 
GetBundleId(int32_t & bundleUid,int32_t & bundleGid) const85 void AOTArgsHandler::GetBundleId(int32_t &bundleUid, int32_t &bundleGid) const
86 {
87     std::lock_guard<std::mutex> lock(hapArgsMutex_);
88     bundleUid = hapArgs_.bundleUid;
89     bundleGid = hapArgs_.bundleGid;
90 }
91 
GetFileName() const92 std::string AOTArgsHandler::GetFileName() const
93 {
94     std::lock_guard<std::mutex> lock(hapArgsMutex_);
95     return hapArgs_.fileName;
96 }
97 
GetCodeSignArgs() const98 std::string AOTArgsHandler::GetCodeSignArgs() const
99 {
100     std::lock_guard<std::mutex> lock(hapArgsMutex_);
101     return hapArgs_.signature;
102 }
103 
FindArgsIdxToInteger(const std::unordered_map<std::string,std::string> & argsMap,const std::string & keyName,int32_t & bundleID)104 int32_t AOTArgsParserBase::FindArgsIdxToInteger(const std::unordered_map<std::string, std::string> &argsMap,
105                                                 const std::string &keyName, int32_t &bundleID)
106 {
107     if (argsMap.find(keyName) == argsMap.end()) {
108         return ERR_AOT_COMPILER_PARAM_FAILED;
109     }
110 
111     if (argsMap.at(keyName).empty() || !isdigit(argsMap.at(keyName).at(0))) {
112         return ERR_AOT_COMPILER_PARAM_FAILED;
113     }
114 
115     const char* beginPtr = argsMap.at(keyName).data();
116     const char* endPtr = argsMap.at(keyName).data() + argsMap.at(keyName).size();
117     auto res = std::from_chars(beginPtr, endPtr, bundleID);
118     if ((res.ec != std::errc()) || (res.ptr != endPtr)) {
119         LOG_SA(ERROR) << "trigger exception as converting string to integer";
120         return ERR_AOT_COMPILER_PARAM_FAILED;
121     }
122     return ERR_OK;
123 }
124 
FindArgsIdxToString(const std::unordered_map<std::string,std::string> & argsMap,const std::string & keyName,std::string & bundleArg)125 int32_t AOTArgsParserBase::FindArgsIdxToString(const std::unordered_map<std::string, std::string> &argsMap,
126                                                const std::string &keyName, std::string &bundleArg)
127 {
128     if (argsMap.find(keyName) == argsMap.end()) {
129         return ERR_AOT_COMPILER_PARAM_FAILED;
130     }
131 
132     bundleArg = argsMap.at(keyName);
133     return ERR_OK;
134 }
135 
Parse(const std::unordered_map<std::string,std::string> & argsMap,HapArgs & hapArgs,int32_t thermalLevel)136 int32_t AOTArgsParser::Parse(const std::unordered_map<std::string, std::string> &argsMap, HapArgs &hapArgs,
137                              int32_t thermalLevel)
138 {
139     std::string abcPath;
140     if ((FindArgsIdxToInteger(argsMap, ArgsIdx::BUNDLE_UID, hapArgs.bundleUid) != ERR_OK)   ||
141         (FindArgsIdxToInteger(argsMap, ArgsIdx::BUNDLE_GID, hapArgs.bundleGid) != ERR_OK)   ||
142         (FindArgsIdxToString(argsMap, ArgsIdx::AN_FILE_NAME, hapArgs.fileName) != ERR_OK)   ||
143         (FindArgsIdxToString(argsMap, ArgsIdx::APP_SIGNATURE, hapArgs.signature) != ERR_OK) ||
144         (FindArgsIdxToString(argsMap, ArgsIdx::ABC_PATH, abcPath) != ERR_OK)) {
145         LOG_SA(ERROR) << "aot compiler args parsing error";
146         return ERR_AOT_COMPILER_PARAM_FAILED;
147     }
148 
149     hapArgs.argVector.clear();
150     hapArgs.argVector.emplace_back(AOT_EXE);
151 
152     // service process add aot compile args here
153     AddExpandArgs(hapArgs.argVector, thermalLevel);
154 
155     for (auto &argPair : argsMap) {
156         if (aotArgsList.find(argPair.first) != aotArgsList.end()) {
157             hapArgs.argVector.emplace_back(Symbols::PREFIX + argPair.first + Symbols::EQ + argPair.second);
158         }
159     }
160 
161 #ifdef ENABLE_COMPILER_SERVICE_GET_PARAMETER
162     SetEnableCodeCommentBySysParam(hapArgs);
163     SetAnFileMaxSizeBySysParam(hapArgs);
164 #endif
165 
166     hapArgs.argVector.emplace_back(abcPath);
167     return ERR_OK;
168 }
169 
170 #ifdef ENABLE_COMPILER_SERVICE_GET_PARAMETER
SetAnFileMaxSizeBySysParam(HapArgs & hapArgs)171 void AOTArgsParser::SetAnFileMaxSizeBySysParam(HapArgs &hapArgs)
172 {
173     int anFileMaxSize = OHOS::system::GetIntParameter<int>("ark.aot.compiler_an_file_max_size", -1);
174     if (anFileMaxSize >= 0) {
175         hapArgs.argVector.emplace_back(Symbols::PREFIX + ArgsIdx::COMPILER_AN_FILE_MAX_SIZE + Symbols::EQ +
176                                        std::to_string(anFileMaxSize));
177     }
178 }
179 
SetEnableCodeCommentBySysParam(HapArgs & hapArgs)180 void AOTArgsParser::SetEnableCodeCommentBySysParam(HapArgs &hapArgs)
181 {
182     bool enableAotCodeComment = OHOS::system::GetBoolParameter("ark.aot.code_comment.enable", false);
183     if (enableAotCodeComment) {
184         hapArgs.argVector.emplace_back(Symbols::PREFIX + ArgsIdx::COMPILER_ENABLE_AOT_CODE_COMMENT + Symbols::EQ +
185                                        "true");
186         hapArgs.argVector.emplace_back(Symbols::PREFIX + ArgsIdx::COMPILER_LOG_OPT + Symbols::EQ + "allasm");
187     }
188 }
189 
IsEnableStaticCompiler()190 bool AOTArgsParserBase::IsEnableStaticCompiler()
191 {
192     return OHOS::system::GetBoolParameter("ark.aot.enable_static_compiler",
193         ARK_AOT_ENABLE_STATIC_COMPILER_DEFAULT_VALUE);
194 }
195 #endif
196 
AddExpandArgs(std::vector<std::string> & argVector,int32_t thermalLevel)197 void AOTArgsParser::AddExpandArgs(std::vector<std::string> &argVector, int32_t thermalLevel)
198 {
199     std::string thermalLevelArg = "--compiler-thermal-level=" + std::to_string(thermalLevel);
200     argVector.emplace_back(thermalLevelArg);
201 }
202 
Parse(const std::unordered_map<std::string,std::string> & argsMap,HapArgs & hapArgs,int32_t thermalLevel)203 int32_t StaticAOTArgsParser::Parse(const std::unordered_map<std::string, std::string> &argsMap,
204                                    HapArgs &hapArgs, [[maybe_unused]] int32_t thermalLevel)
205 {
206     std::string abcPath;
207     if ((FindArgsIdxToInteger(argsMap, ArgsIdx::BUNDLE_UID, hapArgs.bundleUid) != ERR_OK)   ||
208         (FindArgsIdxToInteger(argsMap, ArgsIdx::BUNDLE_GID, hapArgs.bundleGid) != ERR_OK)   ||
209         (FindArgsIdxToString(argsMap, ArgsIdx::AN_FILE_NAME, hapArgs.fileName) != ERR_OK)   ||
210         (FindArgsIdxToString(argsMap, ArgsIdx::APP_SIGNATURE, hapArgs.signature) != ERR_OK) ||
211         (FindArgsIdxToString(argsMap, ArgsIdx::ABC_PATH, abcPath) != ERR_OK)) {
212         LOG_SA(ERROR) << "aot compiler args parsing error";
213         return ERR_AOT_COMPILER_PARAM_FAILED;
214     }
215 
216     hapArgs.argVector.clear();
217     hapArgs.argVector.emplace_back(STATIC_AOT_EXE);
218 
219     for (auto &defaultArg : staticAOTDefaultArgs) {
220         hapArgs.argVector.emplace_back(defaultArg);
221     }
222 
223     std::string bootfiles;
224     if (!ParseBootPandaFiles(bootfiles)) {
225         return ERR_AOT_COMPILER_PARAM_FAILED;
226     }
227     hapArgs.argVector.emplace_back(Symbols::PREFIX + STATIC_BOOT_PANDA_FILES + Symbols::EQ + bootfiles);
228 
229     std::string anfilePath;
230     for (auto &argPair : argsMap) {
231         // for 1.2, replace aot-file by paoc-output
232         if (argPair.first == AOT_FILE) {
233             anfilePath = argPair.second;
234             std::string anFileName = anfilePath + AN_SUFFIX;
235             hapArgs.argVector.emplace_back(Symbols::PREFIX + STATIC_PAOC_OUTPUT + Symbols::EQ + anFileName);
236             continue;
237         }
238 
239         if (staticAOTArgsList.find(argPair.first) != staticAOTArgsList.end()) {
240             hapArgs.argVector.emplace_back(Symbols::PREFIX + argPair.first + Symbols::EQ + argPair.second);
241         }
242     }
243 
244     std::string location = ParseLocation(anfilePath);
245     hapArgs.argVector.emplace_back(Symbols::PREFIX + STATIC_PAOC_LOCATION + Symbols::EQ + location);
246     hapArgs.argVector.emplace_back(Symbols::PREFIX + STATIC_PAOC_PANDA_FILES + Symbols::EQ + abcPath);
247 
248     return ERR_OK;
249 }
250 
ParseBootPandaFiles(std::string & bootfiles)251 bool StaticAOTArgsParser::ParseBootPandaFiles(std::string &bootfiles)
252 {
253     std::ifstream inFile;
254     inFile.open(STATIC_BOOT_PATH, std::ios::in);
255     if (!inFile.is_open()) {
256         LOG_SA(ERROR) << "read json error";
257         return false;
258     }
259     nlohmann::json jsonObject = nlohmann::json::parse(inFile);
260     if (jsonObject.is_discarded()) {
261         LOG_SA(ERROR) << "json discarded error";
262         inFile.close();
263         return false;
264     }
265 
266     if (jsonObject.is_null() || jsonObject.empty()) {
267         LOG_SA(ERROR) << "invalid json";
268         inFile.close();
269         return false;
270     }
271 
272     for (const auto &[key, value] : jsonObject.items()) {
273         if (!value.is_null() && value.is_string()) {
274             std::string jsonValue = value.get<std::string>();
275             if (jsonValue.empty()) {
276                 LOG_SA(ERROR) << "json value of " << key << " is empty";
277                 continue;
278             }
279             if (!bootfiles.empty()) {
280                 bootfiles += ":";
281             }
282             bootfiles += jsonValue.c_str();
283         }
284     }
285     inFile.close();
286     return true;
287 }
288 
ParseLocation(std::string & anFilePath)289 std::string StaticAOTArgsParser::ParseLocation(std::string &anFilePath)
290 {
291     size_t pos = anFilePath.find_last_of("/");
292     if (pos == std::string::npos) {
293         LOG_SA(FATAL) << "aot sa parse invalid location";
294     }
295     std::string moduleName = anFilePath.substr(pos + 1);
296     std::string location = APP_SANBOX_PATH_PREFIX + moduleName + ETS_PATH;
297     return location;
298 }
299 
GetParser(const std::unordered_map<std::string,std::string> & argsMap)300 std::optional<std::unique_ptr<AOTArgsParserBase>> AOTArgsParserFactory::GetParser(
301     const std::unordered_map<std::string, std::string> &argsMap)
302 {
303 #ifdef ENABLE_COMPILER_SERVICE_GET_PARAMETER
304     if (!AOTArgsParserBase::IsEnableStaticCompiler()) {
305         return std::make_unique<AOTArgsParser>();
306     }
307 #endif
308     int32_t isSystemComponent = 0;
309     if ((AOTArgsParserBase::FindArgsIdxToInteger(argsMap, ArgsIdx::IS_SYSTEM_COMPONENT, isSystemComponent) != ERR_OK)) {
310         LOG_SA(INFO) << "aot sa failed to get isSystemComponent";
311     }
312     if (isSystemComponent) {
313         return std::make_unique<StaticFrameworkAOTArgsParser>();
314     }
315     std::string arkTsMode;
316     if (AOTArgsParserBase::FindArgsIdxToString(argsMap, ArgsIdx::ARKTS_MODE, arkTsMode) != ERR_OK) {
317         LOG_SA(INFO) << "aot sa failed to get language version";
318         arkTsMode = ARKTS_DYNAMIC;
319     }
320 
321     if (arkTsMode == ARKTS_DYNAMIC) {
322         LOG_SA(INFO) << "aot sa use default compiler";
323         return std::make_unique<AOTArgsParser>();
324     } else if (arkTsMode == ARKTS_STATIC || arkTsMode == ARKTS_HYBRID) {
325         LOG_SA(INFO) << "aot sa use static compiler";
326         return std::make_unique<StaticAOTArgsParser>();
327     }
328     LOG_SA(FATAL) << "aot sa get invalid code language version";
329     return std::nullopt;
330 }
331 
IsFileExists(const std::string & fileName)332 bool StaticFrameworkAOTArgsParser::IsFileExists(const std::string &fileName)
333 {
334     std::string realPath;
335     if (!panda::ecmascript::RealPath(fileName, realPath)) {
336         LOG_SA(ERROR) << "get real path failed:" << fileName;
337         return false;
338     }
339     return panda::ecmascript::FileExist(realPath.c_str());
340 }
341 
Parse(const std::unordered_map<std::string,std::string> & argsMap,HapArgs & hapArgs,int32_t thermalLevel)342 int32_t StaticFrameworkAOTArgsParser::Parse(const std::unordered_map<std::string, std::string> &argsMap,
343     HapArgs &hapArgs, [[maybe_unused]] int32_t thermalLevel)
344 {
345     std::string abcPath;
346     if ((FindArgsIdxToString(argsMap, ArgsIdx::ABC_PATH, abcPath) != ERR_OK) ||
347         (FindArgsIdxToString(argsMap, ArgsIdx::AN_FILE_NAME, hapArgs.fileName) != ERR_OK)) {
348         LOG_SA(ERROR) << "aot compiler args parsing error";
349         return ERR_AOT_COMPILER_PARAM_FAILED;
350     }
351 
352     if (IsFileExists(hapArgs.fileName)) {
353         LOG_SA(INFO) << "framework's an is exist";
354         return ERR_AOT_COMPILER_CALL_CANCELLED;
355     }
356 
357     hapArgs.argVector.clear();
358     hapArgs.argVector.emplace_back(STATIC_AOT_EXE);
359 
360     hapArgs.signature = OWNERID_SHARED_TAG;
361 
362     hapArgs.bundleUid = OID_SYSTEM;
363     hapArgs.bundleGid = OID_SYSTEM;
364 
365     for (auto &defaultArg : staticFrameworkAOTDefaultArgs) {
366         hapArgs.argVector.emplace_back(defaultArg);
367     }
368 
369     std::string fullBootfiles;
370     if (!ParseBootPandaFiles(fullBootfiles)) {
371         return ERR_AOT_COMPILER_PARAM_FAILED;
372     }
373     std::string bootfiles = ParseFrameworkBootPandaFiles(fullBootfiles, abcPath);
374     if (bootfiles.empty()) {
375         LOG_SA(ERROR) << "can not find paoc panda files ";
376         return ERR_AOT_COMPILER_PARAM_FAILED;
377     }
378     hapArgs.argVector.emplace_back(Symbols::PREFIX + STATIC_BOOT_PANDA_FILES + Symbols::EQ + bootfiles);
379 
380     for (auto &argPair : argsMap) {
381         if (argPair.first == AN_FILE_NAME) {
382             hapArgs.argVector.emplace_back(Symbols::PREFIX + STATIC_PAOC_OUTPUT + Symbols::EQ + argPair.second);
383         }
384     }
385     hapArgs.argVector.emplace_back(Symbols::PREFIX + STATIC_PAOC_PANDA_FILES + Symbols::EQ + abcPath);
386     return ERR_OK;
387 }
388 
ParseFrameworkBootPandaFiles(const std::string & bootfiles,const std::string & paocPandaFiles)389 std::string StaticFrameworkAOTArgsParser::ParseFrameworkBootPandaFiles(const std::string &bootfiles,
390     const std::string &paocPandaFiles)
391 {
392     size_t pos = bootfiles.find(paocPandaFiles);
393     std::string frameworkBootPandaFiles;
394     if (pos != std::string::npos) {
395         frameworkBootPandaFiles += bootfiles.substr(0, pos + paocPandaFiles.length());
396     }
397     return frameworkBootPandaFiles;
398 }
399 } // namespace OHOS::ArkCompiler
400