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