• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 "device/device_profile_adapter.h"
17 
18 #include "device_manager.h"
19 #include "dfs_error.h"
20 #include "ipc/i_daemon.h"
21 #include "nlohmann/json.hpp"
22 #include "string_ex.h"
23 #include "utils_log.h"
24 
25 #ifdef SUPPORT_DEVICE_PROFILE
26 #include "distributed_device_profile_client.h"
27 #endif
28 
29 namespace OHOS {
30 namespace Storage {
31 namespace DistributedFile {
32 using namespace std;
33 using namespace OHOS::FileManagement;
34 
35 #ifdef SUPPORT_DEVICE_PROFILE
36 using namespace OHOS::DistributedDeviceProfile;
37 
38 namespace {
39 constexpr const char *DFS_SERVICE_ID = "distributedfiledaemon";
40 constexpr const char *DMS_SERVICE_ID = "dmsfwk_svr_id";
41 constexpr const char *DFS_CHAR_ID = "static_capability";
42 constexpr const char *PACKAGE_NAMES = "packageNames";
43 constexpr const char *VERSIONS = "versions";
44 constexpr const char *SWITCH_ID = "SwitchStatus_Distributed_Super_Manager";
45 constexpr const char *CHARACTER_ID = "SwitchStatus";
46 constexpr const char *STATUS_ENABLE = "1";
47 constexpr const char *STATUS_DISABLE = "0";
48 const static int32_t DFS_VERSION_LENGTH = 3;
49 const static int32_t DFS_MAJOR_VERSION_INDEX = 0;
50 const static int32_t DFS_MINOR_VERSION_INDEX = 1;
51 const static int32_t DFS_FEATURE_VERSION_INDEX = 2;
52 const static DfsVersion NO_VERSION = {0, 0, 0};
53 const static int32_t MAX_JSON_SIZE = 9999;
54 }
55 
Bool2Str(bool value)56 static inline std::string Bool2Str(bool value)
57 {
58     return value ? STATUS_ENABLE : STATUS_DISABLE;
59 }
60 
Str2Bool(const std::string & value)61 static inline bool Str2Bool(const std::string &value)
62 {
63     return value == STATUS_ENABLE;
64 }
65 #endif
66 
IsRemoteDfsVersionLower(const std::string & remoteNetworkId,VersionPackageName packageName)67 bool DeviceProfileAdapter::IsRemoteDfsVersionLower(const std::string &remoteNetworkId,
68     VersionPackageName packageName)
69 {
70 #ifdef SUPPORT_DEVICE_PROFILE
71     LOGI("remoteDevice.networkId: %{public}.5s", remoteNetworkId.c_str());
72     DfsVersion localDfsVersion;
73     int32_t ret = GetLocalDfsVersion(packageName, localDfsVersion);
74     if (ret != FileManagement::ERR_OK) {
75         LOGE("GetLocalDfsVersion failed, ret=%{public}d", ret);
76         return false;
77     }
78     return IsRemoteDfsVersionLower(remoteNetworkId, localDfsVersion, packageName);
79 #else
80     return false;
81 #endif
82 }
83 
84 // Comparison of version numbers later than the current version number is not supported.
IsRemoteDfsVersionLower(const std::string & remoteNetworkId,const DfsVersion & thresholdDfsVersion,VersionPackageName packageName)85 bool DeviceProfileAdapter::IsRemoteDfsVersionLower(const std::string &remoteNetworkId,
86     const DfsVersion &thresholdDfsVersion, VersionPackageName packageName)
87 {
88 #ifdef SUPPORT_DEVICE_PROFILE
89     LOGI("remoteDevice.networkId: %{public}.5s", remoteNetworkId.c_str());
90     if (remoteNetworkId.empty()) {
91         LOGE("remoteNetworkId is empty");
92         return false;
93     }
94     DfsVersion remoteDfsVersion;
95     int32_t ret = GetDfsVersionFromNetworkId(remoteNetworkId, remoteDfsVersion, packageName);
96     if (ret != FileManagement::ERR_OK) {
97         LOGE("GetDfsVersionFromNetworkId failed, ret=%{public}d", ret);
98         return false;
99     }
100     return CompareDfsVersion(remoteDfsVersion, thresholdDfsVersion);
101 #else
102     return false;
103 #endif
104 }
105 
GetDeviceStatus(const std::string & networkId,bool & status)106 int32_t DeviceProfileAdapter::GetDeviceStatus(const std::string &networkId, bool &status)
107 {
108 #ifdef SUPPORT_DEVICE_PROFILE
109     auto udid = GetUdidByNetworkId(networkId);
110     if (udid.empty()) {
111         LOGE("remote GetUdidByNetworkId failed");
112         return ERR_GET_UDID;
113     }
114 
115     CharacteristicProfile profile;
116     int32_t ret = DistributedDeviceProfileClient::GetInstance().GetCharacteristicProfile(udid,
117         SWITCH_ID, CHARACTER_ID, profile);
118     if (ret != DistributedDeviceProfile::DP_SUCCESS) {
119         LOGE("GetDeviceStatus failed, ret=%{public}d, udid=%{public}.5s, status=%{public}d", ret, udid.c_str(),
120             status);
121         return ret;
122     }
123     std::string enabledStatus = profile.GetCharacteristicValue();
124     status = Str2Bool(enabledStatus);
125     LOGI("GetDeviceStatus success, udid=%{public}.5s, status=%{public}d", udid.c_str(), status);
126 #endif
127     return FileManagement::ERR_OK;
128 }
129 
PutDeviceStatus(bool status)130 int32_t DeviceProfileAdapter::PutDeviceStatus(bool status)
131 {
132 #ifdef SUPPORT_DEVICE_PROFILE
133     DistributedHardware::DmDeviceInfo localDeviceInfo{};
134     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
135     int ret = deviceManager.GetLocalDeviceInfo(IDaemon::SERVICE_NAME, localDeviceInfo);
136     if (ret != FileManagement::ERR_OK) {
137         LOGE("GetLocalDeviceInfo failed, errCode = %{public}d", ret);
138         return ret;
139     }
140     LOGD("GetLocalDeviceInfo success, localDeviceInfo.networkId = %{public}.5s", localDeviceInfo.networkId);
141     auto udid = GetUdidByNetworkId(localDeviceInfo.networkId);
142     if (udid.empty()) {
143         LOGE("remote GetUdidByNetworkId failed");
144         return ERR_GET_UDID;
145     }
146 
147     std::string enabledStatus = Bool2Str(status);
148     CharacteristicProfile profile;
149     profile.SetDeviceId(udid);
150     profile.SetServiceName(SWITCH_ID);
151     profile.SetCharacteristicKey(CHARACTER_ID);
152     profile.SetCharacteristicValue(enabledStatus);
153 
154     ret = DistributedDeviceProfileClient::GetInstance().PutCharacteristicProfile(profile);
155     if (ret != DistributedDeviceProfile::DP_SUCCESS) {
156         LOGE("PutDeviceStatus failed, ret=%{public}d, udid=%{public}.5s, status=%{public}d", ret, udid.c_str(), status);
157         return ret;
158     }
159     LOGI("PutDeviceStatus success, udid=%{public}.5s, status=%{public}d", udid.c_str(), status);
160 #endif
161     return FileManagement::ERR_OK;
162 }
163 
164 #ifdef SUPPORT_DEVICE_PROFILE
GetLocalDfsVersion(VersionPackageName packageName,DfsVersion & dfsVersion)165 int32_t DeviceProfileAdapter::GetLocalDfsVersion(VersionPackageName packageName, DfsVersion &dfsVersion)
166 {
167     DistributedHardware::DmDeviceInfo localDeviceInfo{};
168     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
169     int ret = deviceManager.GetLocalDeviceInfo(IDaemon::SERVICE_NAME, localDeviceInfo);
170     if (ret != FileManagement::ERR_OK) {
171         LOGE("GetLocalDeviceInfo failed, errCode = %{public}d", ret);
172         return ret;
173     }
174     LOGD("GetLocalDeviceInfo success, localDeviceInfo.networkId=%{public}.5s", localDeviceInfo.networkId);
175     auto udid = GetUdidByNetworkId(localDeviceInfo.networkId);
176     if (udid.empty()) {
177         LOGE("remote GetUdidByNetworkId failed, networkId=%{public}.5s", localDeviceInfo.networkId);
178         return ERR_GET_UDID;
179     }
180     return GetDfsVersion(udid, packageName, dfsVersion, false);
181 }
182 #endif
183 
GetDfsVersionFromNetworkId(const std::string & networkId,DfsVersion & dfsVersion,VersionPackageName packageName)184 int32_t DeviceProfileAdapter::GetDfsVersionFromNetworkId(
185     const std::string &networkId, DfsVersion &dfsVersion, VersionPackageName packageName)
186 {
187 #ifdef SUPPORT_DEVICE_PROFILE
188     if (networkId.empty()) {
189         LOGE("networkId: %{public}.5s is empty", networkId.c_str());
190         return ERR_NULLPTR;
191     }
192     auto udid = GetUdidByNetworkId(networkId);
193     if (udid.empty()) {
194         LOGE("remote GetUdidByNetworkId failed, networkId=%{public}.5s ", networkId.c_str());
195         return ERR_GET_UDID;
196     }
197     return GetDfsVersion(udid, packageName, dfsVersion, true);
198 #else
199     return FileManagement::ERR_OK;
200 #endif
201 }
202 
203 #ifdef SUPPORT_DEVICE_PROFILE
GetDfsVersion(const std::string & udid,VersionPackageName packageName,DfsVersion & dfsVersion,bool IsVerifyCode)204 int32_t DeviceProfileAdapter::GetDfsVersion(const std::string &udid,
205     VersionPackageName packageName, DfsVersion &dfsVersion, bool IsVerifyCode)
206 {
207     std::string appInfoJsonData;
208     int32_t ret = GetAppInfoFromDP(udid, DFS_SERVICE_ID, appInfoJsonData);
209     if (ret == DistributedDeviceProfile::DP_NOT_FOUND_FAIL) {
210         auto dmsResult = GetAppInfoFromDP(udid, DMS_SERVICE_ID, appInfoJsonData);
211         if (IsVerifyCode && dmsResult == DistributedDeviceProfile::DP_NOT_FOUND_FAIL) {
212             LOGW("The DP version of the remote device is later, return local dfsVersion.");
213             GetLocalDfsVersion(packageName, dfsVersion);
214             return FileManagement::ERR_OK;
215         } else if (dmsResult != DistributedDeviceProfile::DP_SUCCESS) {
216             LOGE("get app info failed, result: %{public}d!", dmsResult);
217             return dmsResult;
218         }
219         LOGW("The dfs version number has not been added to the remote device.");
220         dfsVersion = NO_VERSION;
221         return FileManagement::ERR_OK;
222     } else if (ret != DistributedDeviceProfile::DP_SUCCESS) {
223         LOGE("get app info failed, result: %{public}d!", ret);
224         return ret;
225     }
226 
227     std::string packageNamesData;
228     std::string versionsData;
229     ret = ParseAppInfo(appInfoJsonData, packageNamesData, versionsData);
230     if (ret != FileManagement::ERR_OK) {
231         LOGE("parse app info failed ret=%{public}d, appInfoJsonData=%{public}s", ret, appInfoJsonData.c_str());
232         return ret;
233     }
234 
235     std::string dfsVersionData;
236     ret = GetDfsVersionDataFromAppInfo(packageNamesData, versionsData, packageName, dfsVersionData);
237     if (ret != FileManagement::ERR_OK) {
238         if (ret == ERR_NO_FIND_PACKAGE_NAME) {
239             LOGW("not find packageName: %{public}d, %{public}s", static_cast<int>(packageName), dfsVersionData.c_str());
240             dfsVersion = NO_VERSION;
241             return FileManagement::ERR_OK;
242         }
243         LOGE("get dfs version data failed, result: %{public}d!", ret);
244         return ret;
245     }
246 
247     if (!ParseDfsVersion(dfsVersionData, dfsVersion)) {
248         LOGE("parse dfs version failed, dfsVersionData=%{public}s", dfsVersionData.c_str());
249         return ERR_DFS_VERSION_PARSE_EXCEPTION;
250     }
251     LOGI("GetDfsVersion success, %{public}s", dfsVersion.dump().c_str());
252     return FileManagement::ERR_OK;
253 }
254 
ParseDfsVersion(const std::string & dfsVersionData,DfsVersion & dfsVersion)255 bool DeviceProfileAdapter::ParseDfsVersion(const std::string &dfsVersionData, DfsVersion &dfsVersion)
256 {
257     std::vector<std::string> versionNumList;
258     SplitStr(dfsVersionData, ".", versionNumList);
259     if (versionNumList.size() != DFS_VERSION_LENGTH) {
260         return false;
261     }
262     int32_t majorVersionNum = -1;
263     if (!OHOS::StrToInt(versionNumList[DFS_MAJOR_VERSION_INDEX], majorVersionNum) || majorVersionNum < 0) {
264         return false;
265     }
266     dfsVersion.majorVersionNum = static_cast<uint32_t>(majorVersionNum);
267 
268     int32_t minorVersionNum = -1;
269     if (!OHOS::StrToInt(versionNumList[DFS_MINOR_VERSION_INDEX], minorVersionNum) || minorVersionNum < 0) {
270         return false;
271     }
272     dfsVersion.minorVersionNum = static_cast<uint32_t>(minorVersionNum);
273 
274     int32_t featureVersionNum = -1;
275     if (!OHOS::StrToInt(versionNumList[DFS_FEATURE_VERSION_INDEX], featureVersionNum) || featureVersionNum < 0) {
276         return false;
277     }
278     dfsVersion.featureVersionNum = static_cast<uint32_t>(featureVersionNum);
279     return true;
280 }
281 
ParseAppInfo(const std::string & appInfoJsonData,std::string & packageNamesData,std::string & versionsData)282 int32_t DeviceProfileAdapter::ParseAppInfo(const std::string &appInfoJsonData, std::string &packageNamesData,
283     std::string &versionsData)
284 {
285     if (appInfoJsonData.empty() || appInfoJsonData.size() > MAX_JSON_SIZE) {
286         return ERR_DFS_VERSION_EMPTY;
287     }
288     nlohmann::json appInfoJson = nlohmann::json::parse(appInfoJsonData.c_str(), nullptr, false);
289     if (appInfoJson.is_discarded()) {
290         return ERR_DFS_VERSION_EMPTY;
291     }
292     if (appInfoJson.find(PACKAGE_NAMES) == appInfoJson.end() || !appInfoJson.at(PACKAGE_NAMES).is_string()) {
293         return ERR_DFS_VERSION_EMPTY;
294     }
295     appInfoJson.at(PACKAGE_NAMES).get_to(packageNamesData);
296 
297     if (appInfoJson.find(VERSIONS) == appInfoJson.end() || !appInfoJson.at(VERSIONS).is_string()) {
298         return ERR_DFS_VERSION_EMPTY;
299     }
300     appInfoJson.at(VERSIONS).get_to(versionsData);
301 
302     return FileManagement::ERR_OK;
303 }
304 
GetDfsVersionDataFromAppInfo(const std::string & packageNamesData,const std::string & versionsData,VersionPackageName packageName,std::string & dfsVersionData)305 int32_t DeviceProfileAdapter::GetDfsVersionDataFromAppInfo(const std::string &packageNamesData,
306     const std::string &versionsData, VersionPackageName packageName, std::string &dfsVersionData)
307 {
308     std::string packageNameString = GetPackageName(packageName);
309     if (packageNamesData.empty() || versionsData.empty() || packageNameString.empty()) {
310         return ERR_DFS_VERSION_EMPTY;
311     }
312 
313     std::vector<std::string> packageNameList;
314     std::vector<std::string> versionsList;
315     SplitStr(packageNamesData, ",", packageNameList);
316     SplitStr(versionsData, ",", versionsList);
317     if (packageNameList.size() != versionsList.size()) {
318         return ERR_DFS_VERSION_PARSE_EXCEPTION;
319     }
320     for (std::size_t i = 0; i < packageNameList.size(); i++) {
321         if (packageNameList[i] == packageNameString) {
322             dfsVersionData = versionsList[i];
323             return FileManagement::ERR_OK;
324         }
325     }
326     return ERR_NO_FIND_PACKAGE_NAME;
327 }
328 
GetAppInfoFromDP(const std::string & udid,const std::string & serviceName,std::string & appInfoJsonData)329 int32_t DeviceProfileAdapter::GetAppInfoFromDP(const std::string &udid,
330     const std::string &serviceName, std::string &appInfoJsonData)
331 {
332     DistributedDeviceProfile::CharacteristicProfile profile;
333     int32_t ret = DistributedDeviceProfileClient::GetInstance().GetCharacteristicProfile(
334         udid, serviceName, DFS_CHAR_ID, profile);
335     if (ret != DistributedDeviceProfile::DP_SUCCESS) {
336         return ret;
337     }
338     appInfoJsonData = profile.GetCharacteristicValue();
339     return FileManagement::ERR_OK;
340 }
341 
CompareDfsVersion(const DfsVersion & dfsVersion,const DfsVersion & thresholdDfsVersion)342 bool DeviceProfileAdapter::CompareDfsVersion(const DfsVersion &dfsVersion, const DfsVersion &thresholdDfsVersion)
343 {
344     if (dfsVersion.majorVersionNum != thresholdDfsVersion.majorVersionNum) {
345         return dfsVersion.majorVersionNum < thresholdDfsVersion.majorVersionNum;
346     }
347     if (dfsVersion.minorVersionNum != thresholdDfsVersion.minorVersionNum) {
348         return dfsVersion.minorVersionNum < thresholdDfsVersion.minorVersionNum;
349     }
350     return dfsVersion.featureVersionNum < thresholdDfsVersion.featureVersionNum;
351 }
352 
GetUdidByNetworkId(const std::string & networkId)353 std::string DeviceProfileAdapter::GetUdidByNetworkId(const std::string &networkId)
354 {
355     std::string udid;
356     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
357     auto ret = deviceManager.GetUdidByNetworkId(IDaemon::SERVICE_NAME, networkId, udid);
358     if (ret != FileManagement::ERR_OK) {
359         LOGE("GetUdidByNetworkId failed, ret = %{public}d", ret);
360         return "";
361     }
362     return udid;
363 }
364 #endif
365 } // namespace DistributedFile
366 } // namespace Storage
367 } // namespace OHOS
368