1 /*
2 * Copyright (c) 2023 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/aot_handler.h"
17
18 #include <thread>
19 #include <vector>
20
21 #include "appexecfwk_errors.h"
22 #include "app_log_wrapper.h"
23 #include "bundle_constants.h"
24 #include "bundle_mgr_service.h"
25 #include "bundle_util.h"
26 #include "installd_client.h"
27 #include "parameter.h"
28 #include "parameters.h"
29 #include "string_ex.h"
30 #ifdef BUNDLE_FRAMEWORK_POWER_MGR_ENABLE
31 #include "display_power_mgr_client.h"
32 #endif
33
34 namespace OHOS {
35 namespace AppExecFwk {
36 namespace {
37 // ark compile option parameter key
38 constexpr const char* COMPILE_INSTALL_PARAM_KEY = "persist.bm.install.arkopt";
39 constexpr const char* COMPILE_IDLE_PARA_KEY = "persist.bm.idle.arkopt";
40 const std::string DEBUG_APP_IDENTIFIER = "DEBUG_LIB_ID";
41 }
42
GetInstance()43 AOTHandler& AOTHandler::GetInstance()
44 {
45 static AOTHandler handler;
46 return handler;
47 }
48
IsSupportARM64() const49 bool AOTHandler::IsSupportARM64() const
50 {
51 std::string abis = GetAbiList();
52 APP_LOGD("abi list : %{public}s", abis.c_str());
53 std::vector<std::string> abiList;
54 SplitStr(abis, Constants::ABI_SEPARATOR, abiList, false, false);
55 if (abiList.empty()) {
56 APP_LOGD("abiList empty");
57 return false;
58 }
59 return std::find(abiList.begin(), abiList.end(), Constants::ARM64_V8A) != abiList.end();
60 }
61
GetArkProfilePath(const std::string & bundleName,const std::string & moduleName) const62 std::string AOTHandler::GetArkProfilePath(const std::string &bundleName, const std::string &moduleName) const
63 {
64 APP_LOGD("GetArkProfilePath begin");
65 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
66 if (!dataMgr) {
67 APP_LOGE("dataMgr is null");
68 return Constants::EMPTY_STRING;
69 }
70 std::vector<int32_t> userIds = dataMgr->GetUserIds(bundleName);
71 for (int32_t userId : userIds) {
72 std::string path;
73 path.append(Constants::ARK_PROFILE_PATH).append(std::to_string(userId))
74 .append(Constants::PATH_SEPARATOR).append(bundleName)
75 .append(Constants::PATH_SEPARATOR).append(moduleName).append(Constants::AP_SUFFIX);
76 APP_LOGD("path : %{public}s", path.c_str());
77 bool isExistFile = false;
78 (void)InstalldClient::GetInstance()->IsExistApFile(path, isExistFile);
79 if (isExistFile) {
80 return path;
81 }
82 }
83 APP_LOGD("GetArkProfilePath failed");
84 return Constants::EMPTY_STRING;
85 }
86
BuildAOTArgs(const InnerBundleInfo & info,const std::string & moduleName,const std::string & compileMode) const87 std::optional<AOTArgs> AOTHandler::BuildAOTArgs(
88 const InnerBundleInfo &info, const std::string &moduleName, const std::string &compileMode) const
89 {
90 AOTArgs aotArgs;
91 aotArgs.bundleName = info.GetBundleName();
92 aotArgs.moduleName = moduleName;
93 if (compileMode == Constants::COMPILE_PARTIAL) {
94 aotArgs.arkProfilePath = GetArkProfilePath(aotArgs.bundleName, aotArgs.moduleName);
95 if (aotArgs.arkProfilePath.empty()) {
96 APP_LOGI("compile mode is partial, but ap not exist, no need to AOT");
97 return std::nullopt;
98 }
99 }
100 aotArgs.compileMode = compileMode;
101 aotArgs.hapPath = info.GetModuleHapPath(aotArgs.moduleName);
102 aotArgs.coreLibPath = Constants::EMPTY_STRING;
103 aotArgs.outputPath = Constants::ARK_CACHE_PATH + aotArgs.bundleName + Constants::PATH_SEPARATOR + Constants::ARM64;
104 // handle internal hsp
105 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
106 if (!dataMgr) {
107 APP_LOGE("dataMgr is null");
108 return std::nullopt;
109 }
110 InnerBundleInfo installedInfo;
111 if (!dataMgr->QueryInnerBundleInfo(info.GetBundleName(), installedInfo)) {
112 APP_LOGE("QueryInnerBundleInfo failed");
113 return std::nullopt;
114 }
115 installedInfo.GetInternalDependentHspInfo(moduleName, aotArgs.hspVector);
116
117 InnerBundleUserInfo newInnerBundleUserInfo;
118 if (!installedInfo.GetInnerBundleUserInfo(Constants::ALL_USERID, newInnerBundleUserInfo)) {
119 APP_LOGE("bundle(%{public}s) get user (%{public}d) failed.",
120 installedInfo.GetBundleName().c_str(), Constants::ALL_USERID);
121 return std::nullopt;
122 }
123 aotArgs.bundleUid = static_cast<uint32_t>(newInnerBundleUserInfo.uid);
124 aotArgs.isEncryptedBundle = installedInfo.IsEncryptedMoudle(moduleName) ? 1 : 0;
125 aotArgs.appIdentifier = (info.GetAppProvisionType() == Constants::APP_PROVISION_TYPE_DEBUG) ?
126 DEBUG_APP_IDENTIFIER : info.GetAppIdentifier();
127 APP_LOGD("args : %{public}s", aotArgs.ToString().c_str());
128 return aotArgs;
129 }
130
AOTInternal(std::optional<AOTArgs> aotArgs,uint32_t versionCode) const131 void AOTHandler::AOTInternal(std::optional<AOTArgs> aotArgs, uint32_t versionCode) const
132 {
133 if (!aotArgs) {
134 APP_LOGI("aotArgs empty");
135 return;
136 }
137 ErrCode ret = ERR_OK;
138 {
139 std::lock_guard<std::mutex> lock(executeMutex_);
140 ret = InstalldClient::GetInstance()->ExecuteAOT(*aotArgs);
141 }
142 APP_LOGI("ExecuteAOT ret : %{public}d", ret);
143
144 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
145 if (!dataMgr) {
146 APP_LOGE("dataMgr is null");
147 return;
148 }
149 AOTCompileStatus status = ret == ERR_OK ? AOTCompileStatus::COMPILE_SUCCESS : AOTCompileStatus::COMPILE_FAILED;
150 dataMgr->SetAOTCompileStatus(aotArgs->bundleName, aotArgs->moduleName, status, versionCode);
151 }
152
HandleInstallWithSingleHap(const InnerBundleInfo & info,const std::string & compileMode) const153 void AOTHandler::HandleInstallWithSingleHap(const InnerBundleInfo &info, const std::string &compileMode) const
154 {
155 std::optional<AOTArgs> aotArgs = BuildAOTArgs(info, info.GetCurrentModulePackage(), compileMode);
156 AOTInternal(aotArgs, info.GetVersionCode());
157 }
158
HandleInstall(const std::unordered_map<std::string,InnerBundleInfo> & infos) const159 void AOTHandler::HandleInstall(const std::unordered_map<std::string, InnerBundleInfo> &infos) const
160 {
161 auto task = [this, infos]() {
162 APP_LOGD("HandleInstall begin");
163 if (infos.empty() || !(infos.cbegin()->second.GetIsNewVersion())) {
164 APP_LOGD("not stage model, no need to AOT");
165 return;
166 }
167 if (!IsSupportARM64()) {
168 APP_LOGD("current device doesn't support arm64, no need to AOT");
169 return;
170 }
171 std::string compileMode = system::GetParameter(COMPILE_INSTALL_PARAM_KEY, Constants::COMPILE_NONE);
172 APP_LOGD("%{public}s = %{public}s", COMPILE_INSTALL_PARAM_KEY, compileMode.c_str());
173 if (compileMode == Constants::COMPILE_NONE) {
174 APP_LOGD("%{public}s = none, no need to AOT", COMPILE_INSTALL_PARAM_KEY);
175 return;
176 }
177 std::for_each(infos.cbegin(), infos.cend(), [this, compileMode](const auto &item) {
178 HandleInstallWithSingleHap(item.second, compileMode);
179 });
180 APP_LOGD("HandleInstall end");
181 };
182 std::thread t(task);
183 t.detach();
184 }
185
ClearArkCacheDir() const186 void AOTHandler::ClearArkCacheDir() const
187 {
188 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
189 if (!dataMgr) {
190 APP_LOGE("dataMgr is null");
191 return;
192 }
193 std::vector<std::string> bundleNames = dataMgr->GetAllBundleName();
194 std::for_each(bundleNames.cbegin(), bundleNames.cend(), [dataMgr](const auto &bundleName) {
195 std::string removeDir = Constants::ARK_CACHE_PATH + bundleName;
196 ErrCode ret = InstalldClient::GetInstance()->RemoveDir(removeDir);
197 APP_LOGD("removeDir %{public}s, ret : %{public}d", removeDir.c_str(), ret);
198 });
199 }
200
HandleResetAOT(const std::string & bundleName,bool isAllBundle) const201 void AOTHandler::HandleResetAOT(const std::string &bundleName, bool isAllBundle) const
202 {
203 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
204 if (!dataMgr) {
205 APP_LOGE("dataMgr is null");
206 return;
207 }
208 std::vector<std::string> bundleNames;
209 if (isAllBundle) {
210 bundleNames = dataMgr->GetAllBundleName();
211 } else {
212 bundleNames = {bundleName};
213 }
214 std::for_each(bundleNames.cbegin(), bundleNames.cend(), [dataMgr](const auto &bundleToReset) {
215 std::string removeDir = Constants::ARK_CACHE_PATH + bundleToReset;
216 ErrCode ret = InstalldClient::GetInstance()->RemoveDir(removeDir);
217 APP_LOGD("removeDir %{public}s, ret : %{public}d", removeDir.c_str(), ret);
218 dataMgr->ResetAOTFlagsCommand(bundleToReset);
219 });
220 }
221
ResetAOTFlags() const222 void AOTHandler::ResetAOTFlags() const
223 {
224 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
225 if (!dataMgr) {
226 APP_LOGE("dataMgr is null");
227 return;
228 }
229 dataMgr->ResetAOTFlags();
230 }
231
HandleOTA() const232 void AOTHandler::HandleOTA() const
233 {
234 APP_LOGI("HandleOTA begin");
235 ClearArkCacheDir();
236 ResetAOTFlags();
237 APP_LOGI("HandleOTA end");
238 }
239
HandleIdleWithSingleHap(const InnerBundleInfo & info,const std::string & moduleName,const std::string & compileMode) const240 void AOTHandler::HandleIdleWithSingleHap(
241 const InnerBundleInfo &info, const std::string &moduleName, const std::string &compileMode) const
242 {
243 APP_LOGD("HandleIdleWithSingleHap, moduleName : %{public}s", moduleName.c_str());
244 if (info.GetAOTCompileStatus(moduleName) == AOTCompileStatus::COMPILE_SUCCESS) {
245 APP_LOGD("AOT history success, no need to AOT");
246 return;
247 }
248 std::optional<AOTArgs> aotArgs = BuildAOTArgs(info, moduleName, compileMode);
249 AOTInternal(aotArgs, info.GetVersionCode());
250 }
251
HandleCompileWithSingleHap(const InnerBundleInfo & info,const std::string & moduleName,const std::string & compileMode) const252 void AOTHandler::HandleCompileWithSingleHap(
253 const InnerBundleInfo &info, const std::string &moduleName, const std::string &compileMode) const
254 {
255 APP_LOGD("HandleCompileWithSingleHap, moduleName : %{public}s", moduleName.c_str());
256 std::optional<AOTArgs> aotArgs = BuildAOTArgs(info, moduleName, compileMode);
257 AOTInternal(aotArgs, info.GetVersionCode());
258 }
259
CheckDeviceState() const260 bool AOTHandler::CheckDeviceState() const
261 {
262 #ifdef BUNDLE_FRAMEWORK_POWER_MGR_ENABLE
263 DisplayPowerMgr::DisplayState displayState =
264 DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().GetDisplayState();
265 if (displayState != DisplayPowerMgr::DisplayState::DISPLAY_OFF) {
266 APP_LOGI("displayState is not DISPLAY_OFF");
267 return false;
268 }
269 return true;
270 #else
271 APP_LOGI("device not support power system");
272 return false;
273 #endif
274 }
275
HandleIdle() const276 void AOTHandler::HandleIdle() const
277 {
278 APP_LOGI("HandleIdle begin");
279 std::unique_lock<std::mutex> lock(idleMutex_, std::defer_lock);
280 if (!lock.try_lock()) {
281 APP_LOGI("idle task is running, skip");
282 return;
283 }
284 if (!IsSupportARM64()) {
285 APP_LOGI("current device doesn't support arm64, no need to AOT");
286 return;
287 }
288 std::string compileMode = system::GetParameter(COMPILE_IDLE_PARA_KEY, Constants::COMPILE_PARTIAL);
289 APP_LOGI("%{public}s = %{public}s", COMPILE_IDLE_PARA_KEY, compileMode.c_str());
290 if (compileMode == Constants::COMPILE_NONE) {
291 APP_LOGI("%{public}s = none, no need to AOT", COMPILE_IDLE_PARA_KEY);
292 return;
293 }
294 if (!CheckDeviceState()) {
295 APP_LOGI("device state is not suitable");
296 return;
297 }
298 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
299 if (!dataMgr) {
300 APP_LOGE("dataMgr is null");
301 return;
302 }
303 std::vector<std::string> bundleNames = dataMgr->GetAllBundleName();
304 std::for_each(bundleNames.cbegin(), bundleNames.cend(), [this, dataMgr, &compileMode](const auto &bundleName) {
305 APP_LOGD("HandleIdle bundleName : %{public}s", bundleName.c_str());
306 InnerBundleInfo info;
307 if (!dataMgr->QueryInnerBundleInfo(bundleName, info)) {
308 APP_LOGE("QueryInnerBundleInfo failed");
309 return;
310 }
311 if (!info.GetIsNewVersion()) {
312 APP_LOGD("not stage model, no need to AOT");
313 return;
314 }
315 std::vector<std::string> moduleNames;
316 info.GetModuleNames(moduleNames);
317 std::for_each(moduleNames.cbegin(), moduleNames.cend(), [this, &info, &compileMode](const auto &moduleName) {
318 HandleIdleWithSingleHap(info, moduleName, compileMode);
319 });
320 });
321 APP_LOGI("HandleIdle end");
322 }
323
HandleCompile(const std::string & bundleName,const std::string & compileMode,bool isAllBundle) const324 void AOTHandler::HandleCompile(const std::string &bundleName, const std::string &compileMode, bool isAllBundle) const
325 {
326 APP_LOGI("HandleCompile begin");
327 std::unique_lock<std::mutex> lock(compileMutex_, std::defer_lock);
328 if (!lock.try_lock()) {
329 APP_LOGI("compile task is running, skip %{public}s", bundleName.c_str());
330 return;
331 }
332 if (!IsSupportARM64()) {
333 APP_LOGI("current device doesn't support arm64, no need to AOT");
334 return;
335 }
336 if (compileMode == Constants::COMPILE_NONE) {
337 APP_LOGI("%{public}s = none, no need to AOT", COMPILE_IDLE_PARA_KEY);
338 return;
339 }
340 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
341 if (!dataMgr) {
342 APP_LOGE("dataMgr is null");
343 return;
344 }
345 std::vector<std::string> bundleNames;
346 if (isAllBundle) {
347 bundleNames = dataMgr->GetAllBundleName();
348 } else {
349 bundleNames = {bundleName};
350 }
351 std::for_each(bundleNames.cbegin(), bundleNames.cend(), [this, dataMgr, &compileMode](const auto &bundleToCompile) {
352 APP_LOGD("HandleCompile bundleToCompile : %{public}s", bundleToCompile.c_str());
353 InnerBundleInfo info;
354 if (!dataMgr->QueryInnerBundleInfo(bundleToCompile, info)) {
355 APP_LOGE("QueryInnerBundleInfo failed. bundleToCompile: %{public}s", bundleToCompile.c_str());
356 return;
357 }
358 if (!info.GetIsNewVersion()) {
359 APP_LOGD("not stage model, no need to AOT");
360 return;
361 }
362 std::vector<std::string> moduleNames;
363 info.GetModuleNames(moduleNames);
364 std::for_each(moduleNames.cbegin(), moduleNames.cend(),
365 [this, &info, &compileMode](const auto &moduleName) {
366 HandleCompileWithSingleHap(info, moduleName, compileMode);
367 });
368 });
369 APP_LOGI("HandleCompile end");
370 }
371 } // namespace AppExecFwk
372 } // namespace OHOS
373