1 /*
2  * Copyright (c) 2021-2024 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 "ams_configuration_parameter.h"
17 #include <unistd.h>
18 #include "app_utils.h"
19 #include "config_policy_utils.h"
20 #include "hilog_tag_wrapper.h"
21 
22 namespace OHOS {
23 namespace AAFwk {
24 namespace {
25 constexpr int32_t LOAD_CONFIGURATION_FAILED = -1;
26 constexpr int32_t LOAD_CONFIGURATION_SUCCESS = 0;
27 constexpr int32_t MAX_RESIDENT_WHITE_LIST_SIZE = 100;
28 }
29 
AmsConfigurationParameter()30 AmsConfigurationParameter::AmsConfigurationParameter() {}
31 
GetInstance()32 AmsConfigurationParameter &AmsConfigurationParameter::GetInstance()
33 {
34     static AmsConfigurationParameter amsConfiguration;
35     return amsConfiguration;
36 }
37 
38 using json = nlohmann::json;
39 
Parse()40 void AmsConfigurationParameter::Parse()
41 {
42     auto ref = LoadAmsConfiguration(AmsConfig::AMS_CONFIG_FILE_PATH);
43 
44     char buf[MAX_PATH_LEN] = { 0 };
45     char *filePath = GetOneCfgFile(AmsConfig::PICKER_CONFIG_FILE_PATH, buf, MAX_PATH_LEN);
46     if (filePath == nullptr || filePath[0] == '\0' || strlen(filePath) > MAX_PATH_LEN) {
47         TAG_LOGE(AAFwkTag::ABILITYMGR, "Can not get config file");
48         LoadUIExtensionPickerConfig(AmsConfig::PICKER_CONFIG_FILE_PATH_DEFAULT);
49         return;
50     }
51     std::string customConfig = filePath;
52     TAG_LOGI(AAFwkTag::ABILITYMGR, "The configuration file path is :%{private}s", customConfig.c_str());
53     LoadUIExtensionPickerConfig(customConfig);
54     TAG_LOGI(AAFwkTag::ABILITYMGR, "load config ref : %{private}d", ref);
55 }
56 
NonConfigFile() const57 bool AmsConfigurationParameter::NonConfigFile() const
58 {
59     return nonConfigFile_;
60 }
61 
GetMissionSaveTime() const62 int AmsConfigurationParameter::GetMissionSaveTime() const
63 {
64     return missionSaveTime_;
65 }
66 
GetOrientation() const67 std::string AmsConfigurationParameter::GetOrientation() const
68 {
69     return orientation_;
70 }
71 
GetANRTimeOutTime() const72 int AmsConfigurationParameter::GetANRTimeOutTime() const
73 {
74     return anrTime_;
75 }
76 
GetAMSTimeOutTime() const77 int AmsConfigurationParameter::GetAMSTimeOutTime() const
78 {
79     return amsTime_;
80 }
81 
GetMaxRestartNum(bool isRootLauncher) const82 int AmsConfigurationParameter::GetMaxRestartNum(bool isRootLauncher) const
83 {
84     return (isRootLauncher ? maxRootLauncherRestartNum_ : maxResidentRestartNum_);
85 }
86 
GetRestartIntervalTime() const87 int AmsConfigurationParameter::GetRestartIntervalTime() const
88 {
89     return restartIntervalTime_;
90 }
91 
GetBootAnimationTimeoutTime() const92 int AmsConfigurationParameter::GetBootAnimationTimeoutTime() const
93 {
94     return bootAnimationTime_;
95 }
96 
GetAppStartTimeoutTime() const97 int AmsConfigurationParameter::GetAppStartTimeoutTime() const
98 {
99     return timeoutUnitTime_ * AppUtils::GetInstance().GetTimeoutUnitTimeRatio();
100 }
101 
SetPickerJsonObject(nlohmann::json Object)102 void AmsConfigurationParameter::SetPickerJsonObject(nlohmann::json Object)
103 {
104     if (Object.contains(AmsConfig::PICKER_CONFIGURATION)) {
105         pickerJsonObject_ = Object.at(AmsConfig::PICKER_CONFIGURATION);
106     }
107 }
108 
GetPickerJsonObject() const109 nlohmann::json AmsConfigurationParameter::GetPickerJsonObject() const
110 {
111     return pickerJsonObject_;
112 }
113 
GetPickerMap() const114 const std::map<std::string, std::string>& AmsConfigurationParameter::GetPickerMap() const
115 {
116     return picker_;
117 }
118 
LoadUIExtensionPickerConfig(const std::string & filePath)119 void AmsConfigurationParameter::LoadUIExtensionPickerConfig(const std::string &filePath)
120 {
121     TAG_LOGI(AAFwkTag::ABILITYMGR, "%{public}s", __func__);
122     if (filePath.empty()) {
123         TAG_LOGE(AAFwkTag::ABILITYMGR, "the file is not existed due to empty file path.");
124         return;
125     }
126 
127     if (access(filePath.c_str(), F_OK) != 0) {
128         TAG_LOGE(AAFwkTag::ABILITYMGR, "can not access the file: %{private}s.", filePath.c_str());
129         return;
130     }
131     std::ifstream inFile;
132     inFile.open(filePath, std::ios::in);
133     if (!inFile.is_open()) {
134         TAG_LOGE(AAFwkTag::ABILITYMGR, "read picker config error");
135         return;
136     }
137 
138     json pickerJson;
139     inFile >> pickerJson;
140     inFile.close();
141     if (pickerJson.is_discarded()) {
142         TAG_LOGE(AAFwkTag::ABILITYMGR, "json discarded error");
143         return;
144     }
145 
146     if (pickerJson.is_null() || pickerJson.empty()) {
147         TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid jsonObj");
148         return;
149     }
150 
151     if (!pickerJson.contains(AmsConfig::UIEATENSION)) {
152         TAG_LOGE(AAFwkTag::ABILITYMGR, "json config not contains the key");
153         return;
154     }
155 
156     if (pickerJson[AmsConfig::UIEATENSION].is_null() || !pickerJson[AmsConfig::UIEATENSION].is_array()
157         || pickerJson[AmsConfig::UIEATENSION].empty()) {
158         TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid obj");
159         return;
160     }
161 
162     for (auto extension : pickerJson[AmsConfig::UIEATENSION]) {
163         if (extension[AmsConfig::UIEATENSION_TYPE].is_null() || !extension[AmsConfig::UIEATENSION_TYPE].is_string()
164             || extension[AmsConfig::UIEATENSION_TYPE_PICKER].is_null()
165             || !extension[AmsConfig::UIEATENSION_TYPE_PICKER].is_string()) {
166             TAG_LOGE(AAFwkTag::ABILITYMGR, "invalid key or value");
167             continue;
168         }
169         std::string type = extension[AmsConfig::UIEATENSION_TYPE].get<std::string>();
170         std::string typePicker = extension[AmsConfig::UIEATENSION_TYPE_PICKER].get<std::string>();
171         TAG_LOGI(AAFwkTag::ABILITYMGR, "type: %{public}s, typePicker: %{public}s", type.c_str(), typePicker.c_str());
172         picker_[type] = typePicker;
173     }
174     pickerJson.clear();
175     TAG_LOGI(AAFwkTag::ABILITYMGR, "read config success");
176 }
177 
LoadAmsConfiguration(const std::string & filePath)178 int AmsConfigurationParameter::LoadAmsConfiguration(const std::string &filePath)
179 {
180     TAG_LOGD(AAFwkTag::ABILITYMGR, "%{public}s", __func__);
181     int ret[2] = {0};
182     if (filePath.empty()) {
183         TAG_LOGE(AAFwkTag::ABILITYMGR, "the file is not existed due to empty file path.");
184         return READ_FAIL;
185     }
186 
187     if (access(filePath.c_str(), F_OK) != 0) {
188         TAG_LOGE(AAFwkTag::ABILITYMGR, "can not access the file: %{private}s.", filePath.c_str());
189         return READ_FAIL;
190     }
191     std::ifstream inFile;
192     inFile.open(filePath, std::ios::in);
193     if (!inFile.is_open()) {
194         TAG_LOGI(AAFwkTag::ABILITYMGR, "Read ability manager service config error.");
195         nonConfigFile_ = true;
196         return READ_FAIL;
197     }
198 
199     json amsJson;
200     inFile >> amsJson;
201     if (amsJson.is_discarded()) {
202         TAG_LOGI(AAFwkTag::ABILITYMGR, "json discarded error ...");
203         nonConfigFile_ = true;
204         inFile.close();
205         return READ_JSON_FAIL;
206     }
207 
208     ret[0] = LoadAppConfigurationForStartUpService(amsJson);
209     if (ret[0] != 0) {
210         TAG_LOGE(AAFwkTag::ABILITYMGR, "LoadAppConfigurationForStartUpService return error");
211     }
212 
213     ret[1] = LoadAppConfigurationForMemoryThreshold(amsJson);
214     if (ret[1] != 0) {
215         TAG_LOGE(AAFwkTag::ABILITYMGR, "LoadAppConfigurationForMemoryThreshold return error");
216     }
217 
218     LoadSystemConfiguration(amsJson);
219     LoadBackToCallerConfig(amsJson);
220     LoadSupportSCBCrashRebootConfig(amsJson);
221     SetPickerJsonObject(amsJson);
222     LoadResidentWhiteListConfig(amsJson);
223     amsJson.clear();
224     inFile.close();
225 
226     for (const auto& i : ret) {
227         if (i != 0) {
228             TAG_LOGE(AAFwkTag::ABILITYMGR, "json no have service item ...");
229             return READ_JSON_FAIL;
230         }
231     }
232 
233     TAG_LOGI(AAFwkTag::ABILITYMGR, "read ams config success!");
234     return READ_OK;
235 }
236 
LoadAppConfigurationForStartUpService(nlohmann::json & Object)237 int AmsConfigurationParameter::LoadAppConfigurationForStartUpService(nlohmann::json& Object)
238 {
239     if (!Object.contains(AmsConfig::SERVICE_ITEM_AMS)) {
240         return LOAD_CONFIGURATION_FAILED;
241     }
242     UpdateStartUpServiceConfigInteger(Object, AmsConfig::MISSION_SAVE_TIME, missionSaveTime_);
243     UpdateStartUpServiceConfigInteger(Object, AmsConfig::APP_NOT_RESPONSE_PROCESS_TIMEOUT_TIME, anrTime_);
244     UpdateStartUpServiceConfigInteger(Object, AmsConfig::AMS_TIMEOUT_TIME, amsTime_);
245     UpdateStartUpServiceConfigInteger(Object, AmsConfig::ROOT_LAUNCHER_RESTART_MAX, maxRootLauncherRestartNum_);
246     UpdateStartUpServiceConfigInteger(Object, AmsConfig::RESIDENT_RESTART_MAX, maxResidentRestartNum_);
247     UpdateStartUpServiceConfigInteger(Object, AmsConfig::RESTART_INTERVAL_TIME, restartIntervalTime_);
248     UpdateStartUpServiceConfigInteger(Object, AmsConfig::BOOT_ANIMATION_TIMEOUT_TIME, bootAnimationTime_);
249     UpdateStartUpServiceConfigInteger(Object, AmsConfig::TIMEOUT_UNIT_TIME, timeoutUnitTime_);
250     UpdateStartUpServiceConfigInteger(Object, AmsConfig::MULTI_USER_TYPE, multiUserType_);
251     return LOAD_CONFIGURATION_SUCCESS;
252 }
253 
LoadAppConfigurationForMemoryThreshold(nlohmann::json & Object)254 int AmsConfigurationParameter::LoadAppConfigurationForMemoryThreshold(nlohmann::json &Object)
255 {
256     int ret = 0;
257     if (!Object.contains("memorythreshold")) {
258         TAG_LOGE(AAFwkTag::ABILITYMGR, "LoadAppConfigurationForMemoryThreshold return error");
259         ret = -1;
260     }
261 
262     return ret;
263 }
264 
LoadSystemConfiguration(nlohmann::json & Object)265 int AmsConfigurationParameter::LoadSystemConfiguration(nlohmann::json& Object)
266 {
267     if (Object.contains(AmsConfig::SYSTEM_CONFIGURATION) &&
268         Object.at(AmsConfig::SYSTEM_CONFIGURATION).contains(AmsConfig::SYSTEM_ORIENTATION) &&
269         Object.at(AmsConfig::SYSTEM_CONFIGURATION).at(AmsConfig::SYSTEM_ORIENTATION).is_string()) {
270         orientation_ = Object.at(AmsConfig::SYSTEM_CONFIGURATION).at(AmsConfig::SYSTEM_ORIENTATION).get<std::string>();
271         return READ_OK;
272     }
273 
274     return READ_FAIL;
275 }
276 
LoadBackToCallerConfig(nlohmann::json & Object)277 int32_t AmsConfigurationParameter::LoadBackToCallerConfig(nlohmann::json& Object)
278 {
279     TAG_LOGI(AAFwkTag::ABILITYMGR, "load backTocaller config");
280     if (Object.contains(AmsConfig::SUPPORT_BACK_TO_CALLER) &&
281         Object.at(AmsConfig::SUPPORT_BACK_TO_CALLER).is_boolean()) {
282         supportBackToCaller_ = Object.at(AmsConfig::SUPPORT_BACK_TO_CALLER).get<bool>();
283         return READ_OK;
284     }
285     TAG_LOGE(AAFwkTag::ABILITYMGR, "load backTocaller failed");
286     return READ_FAIL;
287 }
288 
IsSupportBackToCaller() const289 bool AmsConfigurationParameter::IsSupportBackToCaller() const
290 {
291     return supportBackToCaller_;
292 }
293 
LoadSupportSCBCrashRebootConfig(nlohmann::json & Object)294 int32_t AmsConfigurationParameter::LoadSupportSCBCrashRebootConfig(nlohmann::json& Object)
295 {
296     TAG_LOGI(AAFwkTag::ABILITYMGR, "load scb_crash_reboot_config config");
297     if (Object.contains(AmsConfig::SUPPORT_SCB_CRASH_REBOOT) &&
298         Object.at(AmsConfig::SUPPORT_SCB_CRASH_REBOOT).is_boolean()) {
299         supportSceneboardCrashReboot_ = Object.at(AmsConfig::SUPPORT_SCB_CRASH_REBOOT).get<bool>();
300         return READ_OK;
301     }
302     TAG_LOGE(AAFwkTag::ABILITYMGR, "load scb_crash_reboot_config failed");
303     return READ_FAIL;
304 }
305 
IsSupportSCBCrashReboot() const306 bool AmsConfigurationParameter::IsSupportSCBCrashReboot() const
307 {
308     return supportSceneboardCrashReboot_;
309 }
310 
CheckServiceConfigEnable(nlohmann::json & Object,const std::string & configName,JsonValueType type)311 bool AmsConfigurationParameter::CheckServiceConfigEnable(nlohmann::json& Object, const std::string &configName,
312     JsonValueType type)
313 {
314     if (Object.contains(AmsConfig::SERVICE_ITEM_AMS) &&
315         Object.at(AmsConfig::SERVICE_ITEM_AMS).contains(configName)) {
316         switch (type) {
317             case JsonValueType::NUMBER: {
318                 return Object.at(AmsConfig::SERVICE_ITEM_AMS).at(configName).is_number();
319             }
320             case JsonValueType::STRING: {
321                 return Object.at(AmsConfig::SERVICE_ITEM_AMS).at(configName).is_string();
322             }
323             case JsonValueType::BOOLEAN: {
324                 return Object.at(AmsConfig::SERVICE_ITEM_AMS).at(configName).is_boolean();
325             }
326             default: {
327                 return false;
328             }
329         }
330     }
331     return false;
332 }
333 
UpdateStartUpServiceConfigInteger(nlohmann::json & Object,const std::string & configName,int32_t & value)334 void AmsConfigurationParameter::UpdateStartUpServiceConfigInteger(nlohmann::json& Object,
335     const std::string &configName, int32_t &value)
336 {
337     if (CheckServiceConfigEnable(Object, configName, JsonValueType::NUMBER)) {
338         value = Object.at(AmsConfig::SERVICE_ITEM_AMS).at(configName).get<int>();
339     }
340 }
341 
UpdateStartUpServiceConfigString(nlohmann::json & Object,const std::string & configName,std::string & value)342 void AmsConfigurationParameter::UpdateStartUpServiceConfigString(nlohmann::json& Object,
343     const std::string &configName, std::string &value)
344 {
345     if (CheckServiceConfigEnable(Object, configName, JsonValueType::STRING)) {
346         value = Object.at(AmsConfig::SERVICE_ITEM_AMS).at(configName).get<std::string>();
347     }
348 }
349 
MultiUserType() const350 int AmsConfigurationParameter::MultiUserType() const
351 {
352     return multiUserType_;
353 }
354 
LoadResidentWhiteListConfig(nlohmann::json & Object)355 void AmsConfigurationParameter::LoadResidentWhiteListConfig(nlohmann::json& Object)
356 {
357     if (!Object.contains(AmsConfig::RESIDENT_WHITE_LIST)) {
358         TAG_LOGI(AAFwkTag::ABILITYMGR, "no normal_resident_apps");
359         return;
360     }
361     const auto &whiteListJson = Object.at(AmsConfig::RESIDENT_WHITE_LIST);
362     if (!whiteListJson.is_array()) {
363         TAG_LOGI(AAFwkTag::ABILITYMGR, "normal_resident_apps type error");
364         return;
365     }
366     auto size = whiteListJson.size();
367     if (size > MAX_RESIDENT_WHITE_LIST_SIZE) {
368         size = MAX_RESIDENT_WHITE_LIST_SIZE;
369     }
370     for (decltype(size) i = 0; i < size; i++) {
371         const auto &item = whiteListJson.at(i);
372         if (item.is_string()) {
373             residentWhiteList_.push_back(item.get<std::string>());
374         }
375     }
376 }
377 
InResidentWhiteList(const std::string & bundleName) const378 bool AmsConfigurationParameter::InResidentWhiteList(const std::string &bundleName) const
379 {
380     if (residentWhiteList_.empty()) {
381         return true;
382     }
383 
384     for (const auto &item: residentWhiteList_) {
385         if (bundleName == item) {
386             return true;
387         }
388     }
389     return false;
390 }
391 
GetResidentWhiteList() const392 const std::vector<std::string> &AmsConfigurationParameter::GetResidentWhiteList() const
393 {
394     return residentWhiteList_;
395 }
396 }  // namespace AAFwk
397 }  // namespace OHOS
398