• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 <dlfcn.h>
17 #include <fstream>
18 #include <regex>
19 
20 #include "static_capability_loader.h"
21 
22 #include "config_policy_utils.h"
23 #include "content_sensor_manager_utils.h"
24 #include "distributed_device_profile_constants.h"
25 #include "distributed_device_profile_enums.h"
26 #include "distributed_device_profile_errors.h"
27 #include "i_static_capability_collector.h"
28 #include "profile_utils.h"
29 
30 namespace OHOS {
31 namespace DistributedDeviceProfile {
32 IMPLEMENT_SINGLE_INSTANCE(StaticCapabilityLoader);
33 namespace {
34     const std::string TAG = "StaticCapabilityLoader";
35 }
36 using StaticCapabilityHandler = IStaticCapabilityCollector *(*)();
Init()37 int32_t StaticCapabilityLoader::Init()
38 {
39     HILOGI("call!");
40     return DP_SUCCESS;
41 }
42 
UnInit()43 int32_t StaticCapabilityLoader::UnInit()
44 {
45     HILOGI("call!");
46     return DP_SUCCESS;
47 }
48 
LoadStaticCapability(std::string & staticCapability)49 int32_t StaticCapabilityLoader::LoadStaticCapability(std::string& staticCapability)
50 {
51     HILOGD("call!");
52     std::string fileContent = "";
53     int32_t loadJsonResult = LoadJsonFile(STATIC_CAPABILITY_PATH, fileContent);
54     if (loadJsonResult != DP_SUCCESS) {
55         HILOGE("Load json failed, result: %{public}d!", loadJsonResult);
56         return loadJsonResult;
57     }
58     cJSON* staticCapabilityJson = cJSON_Parse(fileContent.c_str());
59     if (!cJSON_IsObject(staticCapabilityJson)) {
60         HILOGE("Static capability json parse failed!");
61         cJSON_Delete(staticCapabilityJson);
62         return DP_LOAD_STATIC_CAP_FAIL;
63     }
64     int32_t getCapResult = GetStaticCapability(staticCapabilityJson, staticCapability);
65     if (getCapResult != DP_SUCCESS) {
66         HILOGE("Get static capability result %{public}d!", getCapResult);
67         cJSON_Delete(staticCapabilityJson);
68         return getCapResult;
69     }
70     HILOGI("success!");
71     cJSON_Delete(staticCapabilityJson);
72     return DP_SUCCESS;
73 }
74 
GetStaticCapability(const cJSON * const staticCapabilityJson,std::string & staticCapability)75 int32_t StaticCapabilityLoader::GetStaticCapability(const cJSON* const staticCapabilityJson,
76     std::string& staticCapability)
77 {
78     HILOGD("call!");
79     if (!cJSON_IsObject(staticCapabilityJson)) {
80         HILOGE("staticInfoJson is json object!");
81         return DP_INVALID_PARAM;
82     }
83     cJSON* staticCapabilities = cJSON_GetObjectItem(staticCapabilityJson, STATIC_CAPABILITY_ATTRIBUTE.c_str());
84     if (!cJSON_IsArray(staticCapabilities)) {
85         HILOGE("StaticCapabilities is not Array!");
86         return DP_PARSE_STATIC_CAP_FAIL;
87     }
88     int32_t capabilityNum = static_cast<int32_t>(cJSON_GetArraySize(staticCapabilities));
89     if (capabilityNum == 0 || capabilityNum > MAX_STATIC_CAPABILITY_SIZE) {
90         HILOGE("CapabilityNum is invalid, nums: %{public}d!", capabilityNum);
91         return DP_PARSE_STATIC_CAP_FAIL;
92     }
93     InitStaticCapability(capabilityNum, staticCapability);
94     SetStaticCapability(staticCapabilities, staticCapability);
95     return DP_SUCCESS;
96 }
97 
GetStaticInfo(const cJSON * const staticInfoJson,const std::string & staticCapability,std::string & staticVersion,std::unordered_map<std::string,CharacteristicProfile> & charProfiles)98 int32_t StaticCapabilityLoader::GetStaticInfo(const cJSON* const staticInfoJson, const std::string& staticCapability,
99     std::string& staticVersion, std::unordered_map<std::string, CharacteristicProfile>& charProfiles)
100 {
101     HILOGD("call!");
102     if (!cJSON_IsObject(staticInfoJson)) {
103         HILOGE("staticInfoJson is json object!");
104         return DP_INVALID_PARAM;
105     }
106     cJSON* lastStaticInfoJson = GetLatestStaticInfoJson(staticInfoJson);
107     if (lastStaticInfoJson == NULL) {
108         HILOGE("lastStaticInfo is nullptr!");
109         return DP_GET_STATIC_INFO_FAIL;
110     }
111     GetStaticVersion(lastStaticInfoJson, staticVersion);
112     std::string localDeviceId = ContentSensorManagerUtils::GetInstance().ObtainLocalUdid();
113     GenerateStaticProfiles(localDeviceId, staticCapability, lastStaticInfoJson, charProfiles);
114     return DP_SUCCESS;
115 }
116 
GetStaticInfoByVersion(const std::string & deviceId,const std::string & staticCapability,const cJSON * const staticInfoJson,const std::string & staticVersion,std::unordered_map<std::string,CharacteristicProfile> & charProfiles)117 int32_t StaticCapabilityLoader::GetStaticInfoByVersion(const std::string& deviceId,
118     const std::string& staticCapability, const cJSON* const staticInfoJson,
119     const std::string& staticVersion, std::unordered_map<std::string, CharacteristicProfile>& charProfiles)
120 {
121     HILOGD("call!");
122     if (deviceId.empty() || deviceId.size() > MAX_STRING_LEN) {
123         HILOGE("deviceId is invalid!");
124         return DP_INVALID_PARAM;
125     }
126     if (!cJSON_IsObject(staticInfoJson)) {
127         HILOGE("staticInfoJson is json object!");
128         return DP_INVALID_PARAM;
129     }
130     if (staticVersion.empty() || staticVersion.size() > MAX_STRING_LEN) {
131         HILOGE("staticVersion is invalid!");
132         return DP_INVALID_PARAM;
133     }
134     cJSON* json = GetStaticInfoJsonByVersion(staticInfoJson, staticVersion);
135     if (json == NULL) {
136         HILOGE("staticInfoJson is nullptr!");
137         return DP_GET_STATIC_INFO_FAIL;
138     }
139     GenerateStaticProfiles(deviceId, staticCapability, json, charProfiles);
140     return DP_SUCCESS;
141 }
142 
GetLatestStaticInfoJson(const cJSON * const staticInfoJson)143 cJSON* StaticCapabilityLoader::GetLatestStaticInfoJson(const cJSON* const staticInfoJson)
144 {
145     HILOGD("call!");
146     if (!cJSON_IsObject(staticInfoJson)) {
147         HILOGE("staticInfoJson is not object!");
148         return NULL;
149     }
150     cJSON* staticInfos = cJSON_GetObjectItem(staticInfoJson, STATIC_INFO.c_str());
151     if (!cJSON_IsArray(staticInfos)) {
152         HILOGE("StaticInfos is not Array!");
153         return NULL;
154     }
155     int32_t staticInfoNum = static_cast<int32_t>(cJSON_GetArraySize(staticInfos));
156     if (staticInfoNum == 0 || staticInfoNum > MAX_STATIC_CAPABILITY_SIZE) {
157         HILOGE("staticInfoNum is invalid, nums: %{public}d!", staticInfoNum);
158         return NULL;
159     }
160     return cJSON_GetArrayItem(staticInfos, staticInfoNum - 1);
161 }
162 
GetStaticInfoJsonByVersion(const cJSON * const staticInfoJson,const std::string & staticVersion)163 cJSON* StaticCapabilityLoader::GetStaticInfoJsonByVersion(const cJSON* const staticInfoJson,
164     const std::string& staticVersion)
165 {
166     HILOGD("call!");
167     if (!cJSON_IsObject(staticInfoJson)) {
168         HILOGE("staticInfoJson is not object!");
169         return NULL;
170     }
171     if (staticVersion.empty() || staticVersion.size() > MAX_STRING_LEN) {
172         HILOGE("staticVersion is invalid!");
173         return NULL;
174     }
175     cJSON* staticInfos = cJSON_GetObjectItem(staticInfoJson, STATIC_INFO.c_str());
176     if (!cJSON_IsArray(staticInfos)) {
177         HILOGE("StaticInfos is not Array!");
178         return NULL;
179     }
180     int32_t staticInfoNum = static_cast<int32_t>(cJSON_GetArraySize(staticInfos));
181     if (staticInfoNum == 0 || staticInfoNum > MAX_STATIC_CAPABILITY_SIZE) {
182         HILOGE("staticInfoNum is invalid, nums: %{public}d!", staticInfoNum);
183         return NULL;
184     }
185     cJSON *item = NULL;
186     cJSON_ArrayForEach(item, staticInfos) {
187         if (!cJSON_IsObject(item)) {
188             HILOGE("Item is not object!");
189             continue;
190         }
191         cJSON* versionItem = cJSON_GetObjectItemCaseSensitive(item, DP_VERSION.c_str());
192         if (!cJSON_IsString(versionItem) || versionItem->valuestring == NULL) {
193             HILOGE("Get DP_Version fail!");
194             continue;
195         }
196         std::string version = versionItem->valuestring;
197         if (StaticVersionCheck(staticVersion, version)) {
198             HILOGI("Get staticInfoJson Success!");
199             return item;
200         }
201     }
202     HILOGE("staticInfoJson not found");
203     return NULL;
204 }
205 
GetStaticVersion(const cJSON * const lastStaticInfo,std::string & staticVersion)206 int32_t StaticCapabilityLoader::GetStaticVersion(const cJSON* const lastStaticInfo, std::string& staticVersion)
207 {
208     HILOGD("call!");
209     if (!cJSON_IsObject(lastStaticInfo)) {
210         HILOGE("LastStaticInfoItem is not object!");
211         return DP_GET_STATIC_INFO_FAIL;
212     }
213     cJSON* dpVersionJson = cJSON_GetObjectItemCaseSensitive(lastStaticInfo, DP_VERSION.c_str());
214     if (!cJSON_IsString(dpVersionJson) || dpVersionJson->valuestring == NULL) {
215         HILOGE("dpVersionJson is invalid!");
216         return DP_GET_STATIC_INFO_FAIL;
217     }
218     staticVersion = dpVersionJson->valuestring;
219     return DP_SUCCESS;
220 }
221 
GenerateStaticProfiles(const std::string & deviceId,const std::string & staticCapability,const cJSON * const staticInfoJson,std::unordered_map<std::string,CharacteristicProfile> & charProfiles)222 int32_t StaticCapabilityLoader::GenerateStaticProfiles(const std::string& deviceId, const std::string& staticCapability,
223     const cJSON* const staticInfoJson, std::unordered_map<std::string, CharacteristicProfile>& charProfiles)
224 {
225     HILOGD("call!");
226     if (deviceId.empty() || deviceId.size() > MAX_STRING_LEN) {
227         HILOGE("deviceId is invalid!");
228         return DP_INVALID_PARAM;
229     }
230     if (!cJSON_IsObject(staticInfoJson)) {
231         HILOGE("staticInfoJson is not object!");
232         return DP_GET_STATIC_INFO_FAIL;
233     }
234     cJSON* abilitiesJson = cJSON_GetObjectItemCaseSensitive(staticInfoJson, ABILITIES.c_str());
235     if (!cJSON_IsArray(abilitiesJson)) {
236         HILOGE("abilitiesJson is not array!");
237         return DP_GET_STATIC_INFO_FAIL;
238     }
239     cJSON* abilityItem = NULL;
240     cJSON_ArrayForEach(abilityItem, abilitiesJson) {
241         if (!cJSON_IsObject(abilityItem)) {
242             HILOGE("abilityItem is not object!");
243             continue;
244         }
245         cJSON* abilityKeyItem = cJSON_GetObjectItemCaseSensitive(abilityItem, ABILITY_KEY.c_str());
246         if (!cJSON_IsString(abilityKeyItem) || abilityKeyItem->valuestring == NULL) {
247             HILOGE("Get abilityKeyItem fail!");
248             continue;
249         }
250         cJSON* abilityValueItem = cJSON_GetObjectItemCaseSensitive(abilityItem, ABILITY_VALUE.c_str());
251         if (!cJSON_IsObject(abilityValueItem)) {
252             HILOGE("Get abilityValueItem fail!");
253             continue;
254         }
255         std::string serviceId = abilityKeyItem->valuestring;
256         if (!HasStaticCapability(serviceId, staticCapability)) {
257             HILOGW("service: %{public}s does not have static capability", serviceId.c_str());
258             continue;
259         }
260         HILOGD("service: %{public}s has static capability", serviceId.c_str());
261         char* abilityValue = cJSON_Print(abilityValueItem);
262         if (abilityValue == NULL) {
263             HILOGE("Get abilityValue fail!");
264             continue;
265         }
266         std::string charValue = abilityValue;
267         cJSON_free(abilityValue);
268         CharacteristicProfile characteristicProfile(deviceId, serviceId, STATIC_CHARACTERISTIC_KEY, charValue);
269         charProfiles[ProfileUtils::GenerateCharProfileKey(deviceId, serviceId, STATIC_CHARACTERISTIC_KEY)] =
270             characteristicProfile;
271     }
272     return DP_SUCCESS;
273 }
274 
LoadStaticInfo(const std::string & staticCapability,std::string & staticVersion,std::unordered_map<std::string,CharacteristicProfile> & charProfiles)275 int32_t StaticCapabilityLoader::LoadStaticInfo(const std::string& staticCapability, std::string& staticVersion,
276     std::unordered_map<std::string, CharacteristicProfile>& charProfiles)
277 {
278     HILOGD("call!");
279     if (staticCapability.empty() || staticCapability.size() > MAX_STRING_LEN) {
280         HILOGE("staticCapability is invalid!");
281         return DP_INVALID_PARAM;
282     }
283     std::string fileContent = "";
284     int32_t loadJsonResult = LoadJsonFile(STATIC_INFO_PATH, fileContent);
285     if (loadJsonResult != DP_SUCCESS) {
286         HILOGE("Load staticInfo json failed, result: %{public}d!", loadJsonResult);
287         return loadJsonResult;
288     }
289     cJSON* staticInfoJson = cJSON_Parse(fileContent.c_str());
290     if (!cJSON_IsObject(staticInfoJson)) {
291         HILOGE("Static info json parse failed!");
292         cJSON_Delete(staticInfoJson);
293         return DP_PARSE_STATIC_INFO_FAIL;
294     }
295     int32_t getInfoResult = GetStaticInfo(staticInfoJson, staticCapability, staticVersion, charProfiles);
296     if (getInfoResult != DP_SUCCESS) {
297         HILOGE("Get static info result %{public}d!", getInfoResult);
298         cJSON_Delete(staticInfoJson);
299         return getInfoResult;
300     }
301     HILOGI("success!");
302     cJSON_Delete(staticInfoJson);
303     return DP_SUCCESS;
304 }
305 
LoadStaticProfiles(const std::string & deviceId,const std::string & staticCapability,const std::string & staticVersion,std::unordered_map<std::string,CharacteristicProfile> & charProfiles)306 int32_t StaticCapabilityLoader::LoadStaticProfiles(const std::string& deviceId, const std::string& staticCapability,
307     const std::string& staticVersion, std::unordered_map<std::string, CharacteristicProfile>& charProfiles)
308 {
309     HILOGD("call!");
310     if (deviceId.empty() || deviceId.size() > MAX_STRING_LEN) {
311         HILOGE("deviceId is invalid!");
312         return DP_INVALID_PARAM;
313     }
314     if (staticCapability.empty() || staticCapability.size() > MAX_STRING_LEN) {
315         HILOGE("staticCapability is invalid!");
316         return DP_INVALID_PARAM;
317     }
318     if (staticVersion.empty() || staticVersion.size() > MAX_STRING_LEN) {
319         HILOGE("staticVersion is invalid!");
320         return DP_INVALID_PARAM;
321     }
322     std::string fileContent = "";
323     int32_t loadJsonResult = LoadJsonFile(STATIC_INFO_PATH, fileContent);
324     if (loadJsonResult != DP_SUCCESS) {
325         HILOGE("Load staticInfo json failed, result: %{public}d!", loadJsonResult);
326         return loadJsonResult;
327     }
328     cJSON* staticInfoJson = cJSON_Parse(fileContent.c_str());
329     if (!cJSON_IsObject(staticInfoJson)) {
330         HILOGE("Static info json parse failed!");
331         cJSON_Delete(staticInfoJson);
332         return DP_PARSE_STATIC_INFO_FAIL;
333     }
334     int32_t getInfoResult = GetStaticInfoByVersion(deviceId, staticCapability, staticInfoJson,
335         staticVersion, charProfiles);
336     if (getInfoResult != DP_SUCCESS) {
337         HILOGE("Get static info result %{public}d!", getInfoResult);
338         cJSON_Delete(staticInfoJson);
339         return getInfoResult;
340     }
341     HILOGI("success!");
342     cJSON_Delete(staticInfoJson);
343     return DP_SUCCESS;
344 }
345 
InitStaticCapability(int32_t size,std::string & staticCapability)346 void StaticCapabilityLoader::InitStaticCapability(int32_t size, std::string& staticCapability)
347 {
348     HILOGI("InitStaticCapability size %{public}d!", size);
349     staticCapability = EMPTY_STRING;
350     for (int32_t i = 0; i < size; i++) {
351         staticCapability += DEFAULT_STATIC_VAL;
352     }
353     HILOGI("InitStaticCapability value %{public}s!", staticCapability.c_str());
354 }
355 
SetStaticCapability(const cJSON * const staticCapabilityItems,std::string & staticCapability)356 void StaticCapabilityLoader::SetStaticCapability(const cJSON* const staticCapabilityItems,
357     std::string& staticCapability)
358 {
359     HILOGD("call!");
360     if (!cJSON_IsArray(staticCapabilityItems)) {
361         HILOGE("staticCapabilityItems is not json array!");
362         return;
363     }
364     cJSON *item = NULL;
365     cJSON_ArrayForEach(item, staticCapabilityItems) {
366         if (!cJSON_IsObject(item)) {
367             HILOGE("Item is not object!");
368             continue;
369         }
370         cJSON* nameItem = cJSON_GetObjectItemCaseSensitive(item, STATIC_CAP_HANDLER_NAME.c_str());
371         if (!cJSON_IsString(nameItem) || nameItem->valuestring == NULL) {
372             HILOGE("Get handler_name fail!");
373             continue;
374         }
375         cJSON* locItem = cJSON_GetObjectItemCaseSensitive(item, STATIC_CAP_HANDLER_LOC.c_str());
376         if (!cJSON_IsString(locItem) || locItem->valuestring == NULL) {
377             HILOGE("Get handler_loc fail!");
378             continue;
379         }
380         std::string handlerName = nameItem->valuestring;
381         std::string handlerLoc = locItem->valuestring;
382         SetStaticCapabilityFlag(handlerName, handlerLoc, staticCapability);
383     }
384 }
385 
SetStaticCapabilityFlag(const std::string & handlerName,const std::string & handlerLoc,std::string & staticCapability)386 void StaticCapabilityLoader::SetStaticCapabilityFlag(const std::string& handlerName, const std::string& handlerLoc,
387     std::string& staticCapability)
388 {
389     HILOGD("call!");
390     if (handlerName.empty() || handlerName.size() > MAX_STRING_LEN) {
391         HILOGE("handlerName is invalid!");
392         return;
393     }
394     if (handlerLoc.empty() || handlerLoc.size() > MAX_STRING_LEN) {
395         HILOGE("handlerLoc is invalid!");
396         return;
397     }
398     if (CAPABILITY_FLAG_MAP.count(handlerName) == 0) {
399         HILOGE("SetStaticCapabilityFlag fail, handlerName: %{public}s!", handlerName.c_str());
400         return;
401     }
402     int32_t capabilityFlag = static_cast<int32_t>(CAPABILITY_FLAG_MAP.at(handlerName));
403     if (capabilityFlag >= static_cast<int32_t>(staticCapability.size())) {
404         HILOGE("SetStaticCapabilityFlag fail, handlerName: %{public}s!", handlerName.c_str());
405         return;
406     }
407     char capabilityValue = GetStaticCapabilityValue(handlerLoc) ? SUPPORT_STATIC_VAL : NOT_SUPPORT_STATIC_VAL;
408     staticCapability[capabilityFlag] = capabilityValue;
409     HILOGI("handlerName: %{public}s, staticCapability: %{public}c", handlerName.c_str(), capabilityValue);
410 }
411 
GetStaticCapabilityValue(const std::string & handlerLoc)412 bool StaticCapabilityLoader::GetStaticCapabilityValue(const std::string& handlerLoc)
413 {
414     HILOGD("call!");
415     if (handlerLoc.length() == 0 || handlerLoc.length() > PATH_MAX) {
416         HILOGE("File canonicalization failed!");
417         return false;
418     }
419     void *so_handler = dlopen(handlerLoc.c_str(), RTLD_LAZY | RTLD_NODELETE);
420     if (so_handler == nullptr) {
421         HILOGE("%{public}s handler load failed, failed reason : %{public}s", handlerLoc.c_str(), dlerror());
422         return false;
423     }
424     auto func = (StaticCapabilityHandler)dlsym(so_handler, "GetStaticCapabilityCollector");
425     if (func == nullptr) {
426         dlclose(so_handler);
427         HILOGE("Get StaticCapabilityHandler is null, failed reason : %{public}s", dlerror());
428         return false;
429     }
430     bool isSupportStaticCapability = func();
431     HILOGI("GetStaticCapabilityValue %{public}d", isSupportStaticCapability);
432     dlclose(so_handler);
433     return isSupportStaticCapability;
434 }
435 
HasStaticCapability(const std::string & serviceId,const std::string & staticCapability)436 bool StaticCapabilityLoader::HasStaticCapability(const std::string& serviceId, const std::string& staticCapability)
437 {
438     HILOGD("call!");
439     if (CAPABILITY_FLAG_MAP.find(serviceId) == CAPABILITY_FLAG_MAP.end()) {
440         HILOGE("serviceId doesn't exist map, serviceId: %{public}s",
441             ProfileUtils::GetAnonyString(serviceId).c_str());
442         return false;
443     }
444     int32_t capabilityFlag = static_cast<int32_t>(CAPABILITY_FLAG_MAP.at(serviceId));
445     if (capabilityFlag >= static_cast<int32_t>(staticCapability.size())) {
446         HILOGE("HasStaticCapability fail, capabilityFlag is out of range, serviceId: %{public}s",
447             ProfileUtils::GetAnonyString(serviceId).c_str());
448         return false;
449     }
450     return staticCapability[capabilityFlag] == SUPPORT_STATIC_VAL;
451 }
452 
StaticVersionCheck(const std::string & peerVersion,const std::string & localVersion)453 bool StaticCapabilityLoader::StaticVersionCheck(const std::string& peerVersion, const std::string& localVersion)
454 {
455     HILOGD("call!");
456     if (peerVersion == localVersion) {
457         HILOGI("staticVersion equal");
458         return true;
459     }
460     if (!IsValidVersion(peerVersion) || !IsValidVersion(localVersion)) {
461         HILOGE("Params are valid");
462         return false;
463     }
464     return true;
465 }
466 
IsValidVersion(const std::string & version)467 bool StaticCapabilityLoader::IsValidVersion(const std::string& version)
468 {
469     std::regex rule(STATIC_VERSION_RULES);
470     return std::regex_match(version, rule);
471 }
472 
473 } // namespace DistributedDeviceProfile
474 } // namespace OHOS
475