• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "quick_fix/patch_profile.h"
17 
18 #include <sstream>
19 
20 #include "app_log_tag_wrapper.h"
21 #include "bundle_service_constants.h"
22 #include "bundle_util.h"
23 #include "json_util.h"
24 #include "parameter.h"
25 
26 namespace OHOS {
27 namespace AppExecFwk {
28 namespace PatchProfileReader {
29 constexpr const char* BUNDLE_PATCH_PROFILE_APP_KEY_BUNDLE_NAME = "bundleName";
30 constexpr const char* BUNDLE_PATCH_PROFILE_APP_KEY_VERSION_CODE = "versionCode";
31 constexpr const char* BUNDLE_PATCH_PROFILE_APP_KEY_VERSION_NAME = "versionName";
32 constexpr const char* BUNDLE_PATCH_PROFILE_APP_KEY_PATCH_VERSION_CODE = "patchVersionCode";
33 constexpr const char* BUNDLE_PATCH_PROFILE_APP_KEY_PATCH_VERSION_NAME = "patchVersionName";
34 constexpr const char* BUNDLE_PATCH_PROFILE_MODULE_KEY_NAME = "name";
35 constexpr const char* BUNDLE_PATCH_PROFILE_MODULE_KEY_TYPE = "type";
36 constexpr const char* BUNDLE_PATCH_PROFILE_MODULE_KEY_DEVICE_TYPES = "deviceTypes";
37 constexpr const char* BUNDLE_PATCH_PROFILE_MODULE_KEY_ORIGINAL_MODULE_HASH = "originalModuleHash";
38 constexpr const char* BUNDLE_PATCH_PROFILE_KEY_APP = "app";
39 constexpr const char* BUNDLE_PATCH_PROFILE_KEY_MODULE = "module";
40 constexpr const char* BUNDLE_PATCH_TYPE_PATCH = "patch";
41 constexpr const char* BUNDLE_PATCH_TYPE_HOT_RELOAD = "hotreload";
42 
43 int32_t g_parseResult = ERR_OK;
44 std::mutex g_mutex;
45 struct App {
46     std::string bundleName;
47     uint32_t versionCode = 0;
48     uint32_t patchVersionCode = 0;
49     std::string versionName;
50     std::string patchVersionName;
51 };
52 
53 struct Module {
54     std::string name;
55     std::string type;
56     std::vector<std::string> deviceTypes;
57     std::string originalModuleHash;
58 };
59 
60 struct PatchJson {
61     App app;
62     Module module;
63 };
64 
from_json(const nlohmann::json & jsonObject,App & app)65 void from_json(const nlohmann::json &jsonObject, App &app)
66 {
67     const auto &jsonObjectEnd = jsonObject.end();
68     BMSJsonUtil::GetStrValueIfFindKey(jsonObject,
69         jsonObjectEnd,
70         BUNDLE_PATCH_PROFILE_APP_KEY_BUNDLE_NAME,
71         app.bundleName,
72         true,
73         g_parseResult);
74     GetValueIfFindKey<uint32_t>(jsonObject,
75         jsonObjectEnd,
76         BUNDLE_PATCH_PROFILE_APP_KEY_VERSION_CODE,
77         app.versionCode,
78         JsonType::NUMBER,
79         true,
80         g_parseResult,
81         ArrayType::NOT_ARRAY);
82     BMSJsonUtil::GetStrValueIfFindKey(jsonObject,
83         jsonObjectEnd,
84         BUNDLE_PATCH_PROFILE_APP_KEY_VERSION_NAME,
85         app.versionName,
86         false,
87         g_parseResult);
88     GetValueIfFindKey<uint32_t>(jsonObject,
89         jsonObjectEnd,
90         BUNDLE_PATCH_PROFILE_APP_KEY_PATCH_VERSION_CODE,
91         app.patchVersionCode,
92         JsonType::NUMBER,
93         true,
94         g_parseResult,
95         ArrayType::NOT_ARRAY);
96     BMSJsonUtil::GetStrValueIfFindKey(jsonObject,
97         jsonObjectEnd,
98         BUNDLE_PATCH_PROFILE_APP_KEY_PATCH_VERSION_NAME,
99         app.patchVersionName,
100         false,
101         g_parseResult);
102 }
103 
from_json(const nlohmann::json & jsonObject,Module & module)104 void from_json(const nlohmann::json &jsonObject, Module &module)
105 {
106     const auto &jsonObjectEnd = jsonObject.end();
107     BMSJsonUtil::GetStrValueIfFindKey(jsonObject,
108         jsonObjectEnd,
109         BUNDLE_PATCH_PROFILE_MODULE_KEY_NAME,
110         module.name,
111         true,
112         g_parseResult);
113     BMSJsonUtil::GetStrValueIfFindKey(jsonObject,
114         jsonObjectEnd,
115         BUNDLE_PATCH_PROFILE_MODULE_KEY_TYPE,
116         module.type,
117         true,
118         g_parseResult);
119     GetValueIfFindKey<std::vector<std::string>>(jsonObject,
120         jsonObjectEnd,
121         BUNDLE_PATCH_PROFILE_MODULE_KEY_DEVICE_TYPES,
122         module.deviceTypes,
123         JsonType::ARRAY,
124         false,
125         g_parseResult,
126         ArrayType::STRING);
127     BMSJsonUtil::GetStrValueIfFindKey(jsonObject,
128         jsonObjectEnd,
129         BUNDLE_PATCH_PROFILE_MODULE_KEY_ORIGINAL_MODULE_HASH,
130         module.originalModuleHash,
131         false,
132         g_parseResult);
133 }
134 
from_json(const nlohmann::json & jsonObject,PatchJson & patchJson)135 void from_json(const nlohmann::json &jsonObject, PatchJson &patchJson)
136 {
137     const auto &jsonObjectEnd = jsonObject.end();
138     GetValueIfFindKey<App>(jsonObject,
139         jsonObjectEnd,
140         BUNDLE_PATCH_PROFILE_KEY_APP,
141         patchJson.app,
142         JsonType::OBJECT,
143         true,
144         g_parseResult,
145         ArrayType::NOT_ARRAY);
146     GetValueIfFindKey<Module>(jsonObject,
147         jsonObjectEnd,
148         BUNDLE_PATCH_PROFILE_KEY_MODULE,
149         patchJson.module,
150         JsonType::OBJECT,
151         true,
152         g_parseResult,
153         ArrayType::NOT_ARRAY);
154 }
155 
GetQuickFixType(const std::string & type)156 QuickFixType GetQuickFixType(const std::string &type)
157 {
158     if (type == BUNDLE_PATCH_TYPE_PATCH) {
159         return QuickFixType::PATCH;
160     }
161     if (type == BUNDLE_PATCH_TYPE_HOT_RELOAD) {
162         return QuickFixType::HOT_RELOAD;
163     }
164     LOG_W(BMS_TAG_DEFAULT, "GetQuickFixType: unknow quick fix type");
165     return QuickFixType::UNKNOWN;
166 }
167 
CheckNameIsValid(const std::string & name)168 bool CheckNameIsValid(const std::string &name)
169 {
170     if (name.empty()) {
171         LOG_E(BMS_TAG_DEFAULT, "CheckNameIsValid: name is empty");
172         return false;
173     }
174     if (name.find(ServiceConstants::RELATIVE_PATH) != std::string::npos) {
175         return false;
176     }
177     return true;
178 }
179 
ToPatchInfo(const PatchJson & patchJson,AppQuickFix & appQuickFix)180 bool ToPatchInfo(const PatchJson &patchJson, AppQuickFix &appQuickFix)
181 {
182     if (!CheckNameIsValid(patchJson.app.bundleName)) {
183         LOG_E(BMS_TAG_DEFAULT, "bundle name is invalid");
184         return false;
185     }
186     if (!CheckNameIsValid(patchJson.module.name)) {
187         LOG_E(BMS_TAG_DEFAULT, "module name is invalid");
188         return false;
189     }
190     appQuickFix.bundleName = patchJson.app.bundleName;
191     appQuickFix.versionCode = patchJson.app.versionCode;
192     appQuickFix.versionName = patchJson.app.versionName;
193     appQuickFix.deployingAppqfInfo.versionCode = patchJson.app.patchVersionCode;
194     appQuickFix.deployingAppqfInfo.versionName = patchJson.app.patchVersionName;
195     appQuickFix.deployingAppqfInfo.type = GetQuickFixType(patchJson.module.type);
196     HqfInfo hqfInfo;
197     hqfInfo.moduleName = patchJson.module.name;
198     hqfInfo.hapSha256 = patchJson.module.originalModuleHash;
199     hqfInfo.type = GetQuickFixType(patchJson.module.type);
200     appQuickFix.deployingAppqfInfo.hqfInfos.emplace_back(hqfInfo);
201     return true;
202 }
203 }
204 
DefaultNativeSo(const PatchExtractor & patchExtractor,bool isSystemLib64Exist,AppqfInfo & appqfInfo)205 bool PatchProfile::DefaultNativeSo(
206     const PatchExtractor &patchExtractor, bool isSystemLib64Exist, AppqfInfo &appqfInfo)
207 {
208     if (isSystemLib64Exist) {
209         if (patchExtractor.IsDirExist(std::string(ServiceConstants::LIBS) + ServiceConstants::ARM64_V8A)) {
210             appqfInfo.cpuAbi = ServiceConstants::ARM64_V8A;
211             auto iter = ServiceConstants::ABI_MAP.find(ServiceConstants::ARM64_V8A);
212             if (iter != ServiceConstants::ABI_MAP.end()) {
213                 appqfInfo.nativeLibraryPath = ServiceConstants::LIBS + iter->second;
214                 return true;
215             }
216             LOG_E(BMS_TAG_DEFAULT, "Can't find ARM64_V8A in ABI_MAP");
217             return false;
218         }
219         LOG_E(BMS_TAG_DEFAULT, " ARM64_V8A's directory doesn't exist");
220         return false;
221     }
222 
223     if (patchExtractor.IsDirExist(std::string(ServiceConstants::LIBS) + ServiceConstants::ARM_EABI_V7A)) {
224         appqfInfo.cpuAbi = ServiceConstants::ARM_EABI_V7A;
225         auto iter = ServiceConstants::ABI_MAP.find(ServiceConstants::ARM_EABI_V7A);
226         if (iter != ServiceConstants::ABI_MAP.end()) {
227             appqfInfo.nativeLibraryPath = ServiceConstants::LIBS + iter->second;
228             return true;
229         }
230         LOG_E(BMS_TAG_DEFAULT, "Can't find ARM_EABI_V7A in ABI_MAP");
231         return false;
232     }
233 
234     if (patchExtractor.IsDirExist(std::string(ServiceConstants::LIBS) + ServiceConstants::ARM_EABI)) {
235         appqfInfo.cpuAbi = ServiceConstants::ARM_EABI;
236         auto iter = ServiceConstants::ABI_MAP.find(ServiceConstants::ARM_EABI);
237         if (iter != ServiceConstants::ABI_MAP.end()) {
238             appqfInfo.nativeLibraryPath = ServiceConstants::LIBS + iter->second;
239             return true;
240         }
241         LOG_E(BMS_TAG_DEFAULT, "Can't find ARM_EABI in ABI_MAP");
242         return false;
243     }
244     LOG_E(BMS_TAG_DEFAULT, "ARM_EABI_V7A and ARM_EABI directories do not exist");
245     return false;
246 }
247 
ParseNativeSo(const PatchExtractor & patchExtractor,AppqfInfo & appqfInfo)248 bool PatchProfile::ParseNativeSo(const PatchExtractor &patchExtractor, AppqfInfo &appqfInfo)
249 {
250     std::string abis = GetAbiList();
251     std::vector<std::string> abiList;
252     SplitStr(abis, ServiceConstants::ABI_SEPARATOR, abiList, false, false);
253     if (abiList.empty()) {
254         LOG_E(BMS_TAG_DEFAULT, "Abi is empty");
255         return false;
256     }
257     bool isDefault = std::find(abiList.begin(), abiList.end(), ServiceConstants::ABI_DEFAULT) != abiList.end();
258     bool isSystemLib64Exist = BundleUtil::IsExistDir(ServiceConstants::SYSTEM_LIB64);
259     LOG_D(BMS_TAG_DEFAULT, "abi list : %{public}s, isDefault : %{public}d, isSystemLib64Exist : %{public}d",
260         abis.c_str(), isDefault, isSystemLib64Exist);
261     bool soExist = patchExtractor.IsDirExist(ServiceConstants::LIBS);
262     if (!soExist) {
263         LOG_D(BMS_TAG_DEFAULT, "so not exist");
264         if (isDefault) {
265             appqfInfo.cpuAbi = isSystemLib64Exist ? ServiceConstants::ARM64_V8A : ServiceConstants::ARM_EABI_V7A;
266             return true;
267         }
268         for (const auto &abi : abiList) {
269             if (ServiceConstants::ABI_MAP.find(abi) != ServiceConstants::ABI_MAP.end()) {
270                 appqfInfo.cpuAbi = abi;
271                 return true;
272             }
273         }
274         LOG_E(BMS_TAG_DEFAULT, "None of the abiList are in the ABI_MAP");
275         return false;
276     }
277 
278     LOG_D(BMS_TAG_DEFAULT, "so exist");
279     if (isDefault) {
280         return DefaultNativeSo(patchExtractor, isSystemLib64Exist, appqfInfo);
281     }
282     for (const auto &abi : abiList) {
283         std::string libsPath;
284         libsPath.append(ServiceConstants::LIBS).append(abi).append(ServiceConstants::PATH_SEPARATOR);
285         if (ServiceConstants::ABI_MAP.find(abi) != ServiceConstants::ABI_MAP.end() &&
286             patchExtractor.IsDirExist(libsPath)) {
287             appqfInfo.cpuAbi = abi;
288             auto iter = ServiceConstants::ABI_MAP.find(abi);
289             if (iter != ServiceConstants::ABI_MAP.end()) {
290                 appqfInfo.nativeLibraryPath = ServiceConstants::LIBS + iter->second;
291                 return true;
292             }
293             LOG_E(BMS_TAG_DEFAULT, "Can't find %{public}s in ABI_MAP", abi.c_str());
294             return false;
295         }
296     }
297     return false;
298 }
299 
TransformTo(const std::ostringstream & source,const PatchExtractor & patchExtractor,AppQuickFix & appQuickFix)300 ErrCode PatchProfile::TransformTo(
301     const std::ostringstream &source, const PatchExtractor &patchExtractor, AppQuickFix &appQuickFix)
302 {
303     nlohmann::json jsonObject = nlohmann::json::parse(source.str(), nullptr, false);
304     if (jsonObject.is_discarded()) {
305         LOG_E(BMS_TAG_DEFAULT, "bad profile");
306         return ERR_APPEXECFWK_PARSE_BAD_PROFILE;
307     }
308     PatchProfileReader::PatchJson patchJson;
309     {
310         std::lock_guard<std::mutex> lock(PatchProfileReader::g_mutex);
311         PatchProfileReader::g_parseResult = ERR_OK;
312         patchJson = jsonObject.get<PatchProfileReader::PatchJson>();
313         if (PatchProfileReader::g_parseResult != ERR_OK) {
314             LOG_E(BMS_TAG_DEFAULT, "g_parseResult is %{public}d", PatchProfileReader::g_parseResult);
315             int32_t ret = PatchProfileReader::g_parseResult;
316             PatchProfileReader::g_parseResult = ERR_OK;
317             return ret;
318         }
319     }
320     if (!PatchProfileReader::ToPatchInfo(patchJson, appQuickFix)) {
321         LOG_E(BMS_TAG_DEFAULT, "bundle or module name is invalid");
322         return ERR_APPEXECFWK_PARSE_PROFILE_PROP_CHECK_ERROR;
323     }
324     // hot reload does not process so files
325     if ((appQuickFix.deployingAppqfInfo.type == QuickFixType::PATCH) &&
326         (!ParseNativeSo(patchExtractor, appQuickFix.deployingAppqfInfo))) {
327 #ifdef X86_EMULATOR_MODE
328         LOG_E(BMS_TAG_DEFAULT, "ParseNativeSo failed");
329         return ERR_APPEXECFWK_PARSE_NATIVE_SO_FAILED;
330 #endif
331         LOG_W(BMS_TAG_DEFAULT, "ParseNativeSo failed");
332     }
333     return ERR_OK;
334 }
335 }  // namespace AppExecFwk
336 }  // namespace OHOS