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 "battery_srv_client.h"
32 #include "display_power_mgr_client.h"
33 #endif
34
35 namespace OHOS {
36 namespace AppExecFwk {
37 namespace {
38 // ark compile option parameter key
39 constexpr const char* COMPILE_INSTALL_PARAM_KEY = "persist.bm.install.arkopt";
40 constexpr const char* COMPILE_IDLE_PARA_KEY = "persist.bm.idle.arkopt";
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()->IsExistFile(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 APP_LOGD("args : %{public}s", aotArgs.ToString().c_str());
105 return aotArgs;
106 }
107
AOTInternal(std::optional<AOTArgs> aotArgs,uint32_t versionCode) const108 void AOTHandler::AOTInternal(std::optional<AOTArgs> aotArgs, uint32_t versionCode) const
109 {
110 if (!aotArgs) {
111 APP_LOGI("aotArgs empty");
112 return;
113 }
114 ErrCode ret = ERR_OK;
115 {
116 std::lock_guard<std::mutex> lock(mutex_);
117 ret = InstalldClient::GetInstance()->ExecuteAOT(*aotArgs);
118 }
119 APP_LOGI("ExecuteAOT ret : %{public}d", ret);
120
121 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
122 if (!dataMgr) {
123 APP_LOGE("dataMgr is null");
124 return;
125 }
126 AOTCompileStatus status = ret == ERR_OK ? AOTCompileStatus::COMPILE_SUCCESS : AOTCompileStatus::COMPILE_FAILED;
127 dataMgr->SetAOTCompileStatus(aotArgs->bundleName, aotArgs->moduleName, status, versionCode);
128 }
129
HandleInstallWithSingleHap(const InnerBundleInfo & info,const std::string & compileMode) const130 void AOTHandler::HandleInstallWithSingleHap(const InnerBundleInfo &info, const std::string &compileMode) const
131 {
132 std::optional<AOTArgs> aotArgs = BuildAOTArgs(info, info.GetCurrentModulePackage(), compileMode);
133 AOTInternal(aotArgs, info.GetVersionCode());
134 }
135
HandleInstall(const std::unordered_map<std::string,InnerBundleInfo> & infos) const136 void AOTHandler::HandleInstall(const std::unordered_map<std::string, InnerBundleInfo> &infos) const
137 {
138 auto task = [this, infos]() {
139 APP_LOGD("HandleInstall begin");
140 if (infos.empty() || !(infos.cbegin()->second.GetIsNewVersion())) {
141 APP_LOGD("not stage model, no need to AOT");
142 return;
143 }
144 if (!IsSupportARM64()) {
145 APP_LOGD("current device doesn't support arm64, no need to AOT");
146 return;
147 }
148 std::string compileMode = system::GetParameter(COMPILE_INSTALL_PARAM_KEY, Constants::COMPILE_NONE);
149 APP_LOGD("%{public}s = %{public}s", COMPILE_INSTALL_PARAM_KEY, compileMode.c_str());
150 if (compileMode == Constants::COMPILE_NONE) {
151 APP_LOGD("%{public}s = none, no need to AOT", COMPILE_INSTALL_PARAM_KEY);
152 return;
153 }
154 std::for_each(infos.cbegin(), infos.cend(), [this, compileMode](const auto &item) {
155 HandleInstallWithSingleHap(item.second, compileMode);
156 });
157 APP_LOGD("HandleInstall end");
158 };
159 std::thread t(task);
160 t.detach();
161 }
162
ClearArkCacheDir() const163 void AOTHandler::ClearArkCacheDir() const
164 {
165 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
166 if (!dataMgr) {
167 APP_LOGE("dataMgr is null");
168 return;
169 }
170 std::vector<std::string> bundleNames = dataMgr->GetAllBundleName();
171 std::for_each(bundleNames.cbegin(), bundleNames.cend(), [dataMgr](const auto &bundleName) {
172 std::string removeDir = Constants::ARK_CACHE_PATH + bundleName;
173 ErrCode ret = InstalldClient::GetInstance()->RemoveDir(removeDir);
174 APP_LOGD("removeDir %{public}s, ret : %{public}d", removeDir.c_str(), ret);
175 });
176 }
177
ResetAOTFlags() const178 void AOTHandler::ResetAOTFlags() const
179 {
180 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
181 if (!dataMgr) {
182 APP_LOGE("dataMgr is null");
183 return;
184 }
185 dataMgr->ResetAOTFlags();
186 }
187
HandleOTA() const188 void AOTHandler::HandleOTA() const
189 {
190 APP_LOGI("HandleOTA begin");
191 ClearArkCacheDir();
192 ResetAOTFlags();
193 APP_LOGI("HandleOTA end");
194 }
195
HandleIdleWithSingleHap(const InnerBundleInfo & info,const std::string & moduleName,const std::string & compileMode) const196 void AOTHandler::HandleIdleWithSingleHap(
197 const InnerBundleInfo &info, const std::string &moduleName, const std::string &compileMode) const
198 {
199 APP_LOGD("HandleIdleWithSingleHap, moduleName : %{public}s", moduleName.c_str());
200 if (info.GetAOTCompileStatus(moduleName) == AOTCompileStatus::COMPILE_SUCCESS) {
201 APP_LOGD("AOT history success, no need to AOT");
202 return;
203 }
204 std::optional<AOTArgs> aotArgs = BuildAOTArgs(info, moduleName, compileMode);
205 AOTInternal(aotArgs, info.GetVersionCode());
206 }
207
CheckDeviceState() const208 bool AOTHandler::CheckDeviceState() const
209 {
210 #ifdef BUNDLE_FRAMEWORK_POWER_MGR_ENABLE
211 DisplayPowerMgr::DisplayState displayState =
212 DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().GetDisplayState();
213 if (displayState != DisplayPowerMgr::DisplayState::DISPLAY_OFF) {
214 APP_LOGI("displayState is not DISPLAY_OFF");
215 return false;
216 }
217 PowerMgr::BatteryChargeState batteryChargeState =
218 OHOS::PowerMgr::BatterySrvClient::GetInstance().GetChargingStatus();
219 if (batteryChargeState == PowerMgr::BatteryChargeState::CHARGE_STATE_ENABLE
220 || batteryChargeState == PowerMgr::BatteryChargeState::CHARGE_STATE_FULL) {
221 APP_LOGI("device is in charging state");
222 return true;
223 }
224 APP_LOGI("device is not in charging state");
225 return false;
226 #else
227 APP_LOGI("device not support power system");
228 return false;
229 #endif
230 }
231
HandleIdle() const232 void AOTHandler::HandleIdle() const
233 {
234 APP_LOGI("HandleIdle begin");
235 if (!IsSupportARM64()) {
236 APP_LOGI("current device doesn't support arm64, no need to AOT");
237 return;
238 }
239 std::string compileMode = system::GetParameter(COMPILE_IDLE_PARA_KEY, Constants::COMPILE_PARTIAL);
240 APP_LOGI("%{public}s = %{public}s", COMPILE_IDLE_PARA_KEY, compileMode.c_str());
241 if (compileMode == Constants::COMPILE_NONE) {
242 APP_LOGI("%{public}s = none, no need to AOT", COMPILE_IDLE_PARA_KEY);
243 return;
244 }
245 if (!CheckDeviceState()) {
246 APP_LOGI("device state is not suitable");
247 return;
248 }
249 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
250 if (!dataMgr) {
251 APP_LOGE("dataMgr is null");
252 return;
253 }
254 std::vector<std::string> bundleNames = dataMgr->GetAllBundleName();
255 std::for_each(bundleNames.cbegin(), bundleNames.cend(), [this, dataMgr, &compileMode](const auto &bundleName) {
256 APP_LOGD("HandleIdle bundleName : %{public}s", bundleName.c_str());
257 InnerBundleInfo info;
258 if (!dataMgr->QueryInnerBundleInfo(bundleName, info)) {
259 APP_LOGE("QueryInnerBundleInfo failed");
260 return;
261 }
262 if (!info.GetIsNewVersion()) {
263 APP_LOGD("not stage model, no need to AOT");
264 return;
265 }
266 std::vector<std::string> moduleNames;
267 info.GetModuleNames(moduleNames);
268 std::for_each(moduleNames.cbegin(), moduleNames.cend(), [this, &info, &compileMode](const auto &moduleName) {
269 HandleIdleWithSingleHap(info, moduleName, compileMode);
270 });
271 });
272 APP_LOGI("HandleIdle end");
273 }
274 } // namespace AppExecFwk
275 } // namespace OHOS
276