1 /*
2 * Copyright (c) 2022-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 "dms_version_manager.h"
17
18 #include "distributed_device_profile_client.h"
19 #include "dms_constant.h"
20 #include "dtbschedmgr_device_info_storage.h"
21 #include "dtbschedmgr_log.h"
22 #include "nlohmann/json.hpp"
23 #include "string_ex.h"
24
25 namespace OHOS {
26 namespace DistributedSchedule {
27
28 using namespace Constants;
29
30 namespace {
31 const std::string TAG = "DmsVersionManager";
32 const int32_t DMS_VERSION_LENGTH = 3;
33 const int32_t DMS_MAJOR_VERSION_INDEX = 0;
34 const int32_t DMS_MINOR_VERSION_INDEX = 1;
35 const int32_t DMS_FEATURE_VERSION_INDEX = 2;
36 }
37
IsRemoteDmsVersionLower(const std::string & remoteDeviceId,const DmsVersion & thresholdDmsVersion)38 bool DmsVersionManager::IsRemoteDmsVersionLower(const std::string& remoteDeviceId,
39 const DmsVersion& thresholdDmsVersion)
40 {
41 DmsVersion dmsVersion;
42 int32_t result = GetRemoteDmsVersion(remoteDeviceId, dmsVersion);
43 if (result != ERR_OK) {
44 return false;
45 }
46 return CompareDmsVersion(dmsVersion, thresholdDmsVersion);
47 }
48
GetRemoteDmsVersion(const std::string & deviceId,DmsVersion & dmsVersion)49 int32_t DmsVersionManager::GetRemoteDmsVersion(const std::string& deviceId, DmsVersion& dmsVersion)
50 {
51 std::string appInfoJsonData;
52 int32_t result = GetAppInfoFromDP(deviceId, appInfoJsonData);
53 if (result != ERR_OK) {
54 HILOGI("get app info failed, result: %{public}d!", result);
55 return result;
56 }
57 std::string packageNamesData;
58 std::string versionsData;
59 result = ParseAppInfo(appInfoJsonData, packageNamesData, versionsData);
60 if (result != ERR_OK) {
61 HILOGI("parse app info failed");
62 return result;
63 }
64
65 std::string dmsVersionData;
66 result = GetDmsVersionDataFromAppInfo(packageNamesData, versionsData, dmsVersionData);
67 if (result != ERR_OK) {
68 HILOGW("get dms version data failed, result: %{public}d!", result);
69 return result;
70 }
71 if (!ParseDmsVersion(dmsVersionData, dmsVersion)) {
72 HILOGE("parse dms version failed");
73 return DMS_VERSION_PARSE_EXCEPTION;
74 }
75 return ERR_OK;
76 }
77
GetAppInfoFromDP(const std::string & deviceId,std::string & appInfoJsonData)78 int32_t DmsVersionManager::GetAppInfoFromDP(const std::string& deviceId, std::string& appInfoJsonData)
79 {
80 DistributedDeviceProfile::CharacteristicProfile profile;
81 std::string udid = "";
82 udid = DtbschedmgrDeviceInfoStorage::GetInstance().GetUdidByNetworkId(deviceId);
83 int32_t result = DistributedDeviceProfile::DistributedDeviceProfileClient::GetInstance().GetCharacteristicProfile(
84 udid, DMS_SERVICE_ID, DMS_CHAR_ID, profile);
85 if (result != ERR_OK) {
86 return result;
87 }
88 appInfoJsonData = profile.GetCharacteristicValue();
89 return ERR_OK;
90 }
91
ParseAppInfo(const std::string & appInfoJsonData,std::string & packageNamesData,std::string & versionsData)92 int32_t DmsVersionManager::ParseAppInfo(const std::string& appInfoJsonData, std::string& packageNamesData,
93 std::string& versionsData)
94 {
95 if (appInfoJsonData.empty()) {
96 return DMS_VERSION_EMPTY;
97 }
98 nlohmann::json appInfoJson = nlohmann::json::parse(appInfoJsonData.c_str(), nullptr, false);
99 if (appInfoJson.is_discarded()) {
100 return DMS_VERSION_EMPTY;
101 }
102 if (appInfoJson.find(PACKAGE_NAMES) == appInfoJson.end() || !appInfoJson.at(PACKAGE_NAMES).is_string()) {
103 return DMS_VERSION_EMPTY;
104 }
105 appInfoJson.at(PACKAGE_NAMES).get_to(packageNamesData);
106
107 if (appInfoJson.find(VERSIONS) == appInfoJson.end() || !appInfoJson.at(VERSIONS).is_string()) {
108 return DMS_VERSION_EMPTY;
109 }
110 appInfoJson.at(VERSIONS).get_to(versionsData);
111
112 return ERR_OK;
113 }
114
GetDmsVersionDataFromAppInfo(const std::string & packageNamesData,const std::string & versionsData,std::string & dmsVersionData)115 int32_t DmsVersionManager::GetDmsVersionDataFromAppInfo(const std::string& packageNamesData,
116 const std::string& versionsData, std::string& dmsVersionData)
117 {
118 if (packageNamesData.empty() || versionsData.empty()) {
119 return DMS_VERSION_EMPTY;
120 }
121 std::vector<std::string> packageNameList;
122 std::vector<std::string> versionsList;
123 SplitStr(packageNamesData, ",", packageNameList);
124 SplitStr(versionsData, ",", versionsList);
125 if (packageNameList.size() != versionsList.size()) {
126 return DMS_VERSION_PARSE_EXCEPTION;
127 }
128 for (std::size_t i = 0; i < packageNameList.size(); i++) {
129 if (packageNameList[i] == DMS_NAME) {
130 dmsVersionData = versionsList[i];
131 return ERR_OK;
132 }
133 }
134 return DMS_VERSION_EMPTY;
135 }
136
ParseDmsVersion(const std::string & dmsVersionData,DmsVersion & dmsVersion)137 bool DmsVersionManager::ParseDmsVersion(const std::string& dmsVersionData, DmsVersion& dmsVersion)
138 {
139 std::vector<std::string> versionNumList;
140 SplitStr(dmsVersionData, ".", versionNumList);
141 if (versionNumList.size() != DMS_VERSION_LENGTH) {
142 return false;
143 }
144 int32_t majorVersionNum = -1;
145 if (!OHOS::StrToInt(versionNumList[DMS_MAJOR_VERSION_INDEX], majorVersionNum) || majorVersionNum < 0) {
146 return false;
147 }
148 dmsVersion.majorVersionNum = static_cast<uint32_t>(majorVersionNum);
149
150 int32_t minorVersionNum = -1;
151 if (!OHOS::StrToInt(versionNumList[DMS_MINOR_VERSION_INDEX], minorVersionNum) || minorVersionNum < 0) {
152 return false;
153 }
154 dmsVersion.minorVersionNum = static_cast<uint32_t>(minorVersionNum);
155
156 int32_t featureVersionNum = -1;
157 if (!OHOS::StrToInt(versionNumList[DMS_FEATURE_VERSION_INDEX], featureVersionNum) || featureVersionNum < 0) {
158 return false;
159 }
160 dmsVersion.featureVersionNum = static_cast<uint32_t>(featureVersionNum);
161 return true;
162 }
163
CompareDmsVersion(const DmsVersion & dmsVersion,const DmsVersion & thresholdDmsVersion)164 bool DmsVersionManager::CompareDmsVersion(const DmsVersion& dmsVersion, const DmsVersion& thresholdDmsVersion)
165 {
166 if (dmsVersion.majorVersionNum < thresholdDmsVersion.majorVersionNum) {
167 return true;
168 }
169 if (dmsVersion.majorVersionNum == thresholdDmsVersion.majorVersionNum &&
170 dmsVersion.minorVersionNum < thresholdDmsVersion.minorVersionNum) {
171 return true;
172 }
173 if (dmsVersion.majorVersionNum == thresholdDmsVersion.majorVersionNum &&
174 dmsVersion.minorVersionNum == thresholdDmsVersion.minorVersionNum &&
175 dmsVersion.featureVersionNum < thresholdDmsVersion.featureVersionNum) {
176 return true;
177 }
178 return false;
179 }
180 } // namespace DistributedSchedule
181 } // namespace OHOS
182