1 /*
2  * Copyright (c) 2022-2023 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 "dm_discovery_manager.h"
17 #include "dm_discovery_filter.h"
18 #include "dm_anonymous.h"
19 #include "dm_constants.h"
20 #include "dm_log.h"
21 #include "dm_radar_helper.h"
22 #include "parameter.h"
23 
24 namespace OHOS {
25 namespace DistributedHardware {
26 constexpr const char* DISCOVERY_TIMEOUT_TASK = "deviceManagerTimer:discovery";
27 const int32_t DISCOVERY_TIMEOUT = 120;
28 
DmDiscoveryManager(std::shared_ptr<SoftbusConnector> softbusConnector,std::shared_ptr<IDeviceManagerServiceListener> listener,std::shared_ptr<HiChainConnector> hiChainConnector)29 DmDiscoveryManager::DmDiscoveryManager(std::shared_ptr<SoftbusConnector> softbusConnector,
30                                        std::shared_ptr<IDeviceManagerServiceListener> listener,
31                                        std::shared_ptr<HiChainConnector> hiChainConnector)
32     : softbusConnector_(softbusConnector), listener_(listener), hiChainConnector_(hiChainConnector)
33 {
34     LOGI("DmDiscoveryManager constructor");
35 }
36 
~DmDiscoveryManager()37 DmDiscoveryManager::~DmDiscoveryManager()
38 {
39     LOGI("DmDiscoveryManager destructor");
40 }
41 
CfgDiscoveryTimer()42 void DmDiscoveryManager::CfgDiscoveryTimer()
43 {
44     if (timer_ == nullptr) {
45         timer_ = std::make_shared<DmTimer>();
46     }
47     timer_->StartTimer(std::string(DISCOVERY_TIMEOUT_TASK), DISCOVERY_TIMEOUT,
48         [this] (std::string name) {
49             DmDiscoveryManager::HandleDiscoveryTimeout(name);
50         });
51 }
52 
CheckDiscoveryQueue(const std::string & pkgName)53 int32_t DmDiscoveryManager::CheckDiscoveryQueue(const std::string &pkgName)
54 {
55     uint16_t subscribeId = 0;
56     std::string frontPkgName = "";
57     {
58         std::lock_guard<std::mutex> autoLock(locks_);
59         if (discoveryQueue_.empty()) {
60             return DM_OK;
61         }
62 
63         frontPkgName = discoveryQueue_.front();
64         if (pkgName == frontPkgName) {
65             LOGE("DmDiscoveryManager::StartDeviceDiscovery repeated, pkgName:%{public}s", pkgName.c_str());
66             return ERR_DM_DISCOVERY_REPEATED;
67         }
68 
69         LOGI("DmDiscoveryManager::StartDeviceDiscovery stop preview discovery first, the preview pkgName is %{public}s",
70             discoveryQueue_.front().c_str());
71         subscribeId = discoveryContextMap_[frontPkgName].subscribeId;
72     }
73     StopDeviceDiscovery(frontPkgName, subscribeId);
74     return DM_OK;
75 }
76 
StartDeviceDiscovery(const std::string & pkgName,const DmSubscribeInfo & subscribeInfo,const std::string & extra)77 int32_t DmDiscoveryManager::StartDeviceDiscovery(const std::string &pkgName, const DmSubscribeInfo &subscribeInfo,
78     const std::string &extra)
79 {
80     DmDeviceFilterOption dmFilter;
81     if (dmFilter.TransformToFilter(extra) != DM_OK) {
82         return ERR_DM_INPUT_PARA_INVALID;
83     }
84 
85     if (CheckDiscoveryQueue(pkgName) != DM_OK) {
86         return ERR_DM_DISCOVERY_REPEATED;
87     }
88     {
89         std::lock_guard<std::mutex> autoLock(locks_);
90         discoveryQueue_.push(pkgName);
91         DmDiscoveryContext context = {pkgName, extra, subscribeInfo.subscribeId, dmFilter.filterOp_, dmFilter.filters_};
92         discoveryContextMap_.emplace(pkgName, context);
93     }
94     softbusConnector_->RegisterSoftbusDiscoveryCallback(pkgName,
95         std::shared_ptr<ISoftbusDiscoveryCallback>(shared_from_this()));
96     CfgDiscoveryTimer();
97     return softbusConnector_->StartDiscovery(subscribeInfo);
98 }
99 
StartDeviceDiscovery(const std::string & pkgName,const uint16_t subscribeId,const std::string & filterOptions)100 int32_t DmDiscoveryManager::StartDeviceDiscovery(const std::string &pkgName, const uint16_t subscribeId,
101     const std::string &filterOptions)
102 {
103     DmDeviceFilterOption dmFilter;
104     dmFilter.TransformFilterOption(filterOptions);
105     if (CheckDiscoveryQueue(pkgName) != DM_OK) {
106         return ERR_DM_DISCOVERY_REPEATED;
107     }
108     {
109         std::lock_guard<std::mutex> autoLock(locks_);
110         discoveryQueue_.push(pkgName);
111         DmDiscoveryContext context = {pkgName, filterOptions, subscribeId, dmFilter.filterOp_, dmFilter.filters_};
112         discoveryContextMap_.emplace(pkgName, context);
113     }
114     softbusConnector_->RegisterSoftbusDiscoveryCallback(pkgName,
115         std::shared_ptr<ISoftbusDiscoveryCallback>(shared_from_this()));
116     CfgDiscoveryTimer();
117     return softbusConnector_->StartDiscovery(subscribeId);
118 }
119 
StopDeviceDiscovery(const std::string & pkgName,uint16_t subscribeId)120 int32_t DmDiscoveryManager::StopDeviceDiscovery(const std::string &pkgName, uint16_t subscribeId)
121 {
122     if (pkgName.empty()) {
123         LOGE("Invalid parameter, pkgName is empty.");
124         return ERR_DM_INPUT_PARA_INVALID;
125     }
126     {
127         std::lock_guard<std::mutex> autoLock(locks_);
128         if (!discoveryQueue_.empty()) {
129             discoveryQueue_.pop();
130         }
131         if (!discoveryContextMap_.empty()) {
132             discoveryContextMap_.erase(pkgName);
133             if (timer_ != nullptr) {
134                 timer_->DeleteTimer(std::string(DISCOVERY_TIMEOUT_TASK));
135             }
136         }
137     }
138     softbusConnector_->UnRegisterSoftbusDiscoveryCallback(pkgName);
139     return softbusConnector_->StopDiscovery(subscribeId);
140 }
141 
OnDeviceFound(const std::string & pkgName,DmDeviceInfo & info,bool isOnline)142 void DmDiscoveryManager::OnDeviceFound(const std::string &pkgName, DmDeviceInfo &info, bool isOnline)
143 {
144     LOGI("DmDiscoveryManager::OnDeviceFound deviceId = %{public}s", GetAnonyString(info.deviceId).c_str());
145     DmDiscoveryContext discoveryContext;
146     {
147         std::lock_guard<std::mutex> autoLock(locks_);
148         auto iter = discoveryContextMap_.find(pkgName);
149         if (iter == discoveryContextMap_.end()) {
150             LOGE("subscribeId not found by pkgName %{public}s", GetAnonyString(pkgName).c_str());
151             return;
152         }
153         discoveryContext = iter->second;
154     }
155     DmDiscoveryFilter filter;
156     DmDeviceFilterPara filterPara;
157     filterPara.isOnline = isOnline;
158     filterPara.range = info.range;
159     filterPara.deviceType = info.deviceTypeId;
160     char localDeviceId[DEVICE_UUID_LENGTH];
161     GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH);
162     info.authForm = DmAuthForm::INVALID_TYPE;
163     GetAuthForm(localDeviceId, info.deviceId, filterPara.isTrusted, info.authForm);
164     filterPara.authForm = info.authForm;
165     if (filter.IsValidDevice(discoveryContext.filterOp, discoveryContext.filters, filterPara)) {
166         listener_->OnDeviceFound(pkgName, discoveryContext.subscribeId, info);
167     }
168     return;
169 }
170 
GetAuthForm(const std::string & localDeviceId,const std::string & deviceId,bool & isTrusted,DmAuthForm & authForm)171 int32_t DmDiscoveryManager::GetAuthForm(const std::string &localDeviceId, const std::string &deviceId,
172     bool &isTrusted, DmAuthForm &authForm)
173 {
174     LOGI("Get localDeviceId: %{public}s auth form.", GetAnonyString(localDeviceId).c_str());
175     isTrusted = false;
176     if (localDeviceId.empty() || deviceId.empty()) {
177         LOGE("Invalid parameter.");
178         return ERR_DM_INPUT_PARA_INVALID;
179     }
180     if (hiChainConnector_ == nullptr || softbusConnector_ == nullptr) {
181         LOGE("hiChainConnector_ or softbusConnector_ is nullpter.");
182         return ERR_DM_POINT_NULL;
183     }
184 
185     std::vector<std::string> trustDeviceUdidList = hiChainConnector_->GetTrustedDevices(localDeviceId);
186     if (trustDeviceUdidList.empty()) {
187         LOGI("Trusted devices is empty.");
188         return DM_OK;
189     }
190     std::string udidHash;
191     for (auto udid : trustDeviceUdidList) {
192         udidHash = softbusConnector_->GetDeviceUdidHashByUdid(udid);
193         if (udidHash == deviceId) {
194             isTrusted = true;
195             authForm = hiChainConnector_->GetGroupType(udid);
196             LOGI("deviceId: %{public}s is trusted!", GetAnonyString(deviceId).c_str());
197         }
198     }
199 
200     return DM_OK;
201 }
202 
OnDeviceFound(const std::string & pkgName,DmDeviceBasicInfo & info,const int32_t range,bool isOnline)203 void DmDiscoveryManager::OnDeviceFound(const std::string &pkgName,
204     DmDeviceBasicInfo &info, const int32_t range, bool isOnline)
205 {
206     LOGI("DmDiscoveryManager::OnDeviceFound deviceId = %{public}s,isOnline %{public}d",
207         GetAnonyString(info.deviceId).c_str(), isOnline);
208     DmDiscoveryContext discoveryContext;
209     {
210         std::lock_guard<std::mutex> autoLock(locks_);
211         auto iter = discoveryContextMap_.find(pkgName);
212         if (iter == discoveryContextMap_.end()) {
213             LOGE("subscribeId not found by pkgName %{public}s", GetAnonyString(pkgName).c_str());
214             return;
215         }
216         discoveryContext = iter->second;
217     }
218     DmDiscoveryFilter filter;
219     DmDeviceFilterPara filterPara;
220     filterPara.isOnline = isOnline;
221     filterPara.range = range;
222     filterPara.deviceType = info.deviceTypeId;
223     char localDeviceId[DEVICE_UUID_LENGTH];
224     GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH);
225     DmAuthForm authForm = DmAuthForm::INVALID_TYPE;
226     GetAuthForm(localDeviceId, info.deviceId, filterPara.isTrusted, authForm);
227     filterPara.authForm = authForm;
228     if (filter.IsValidDevice(discoveryContext.filterOp, discoveryContext.filters, filterPara)) {
229         listener_->OnDeviceFound(pkgName, discoveryContext.subscribeId, info);
230     }
231     return;
232 }
233 
OnDiscoveryFailed(const std::string & pkgName,int32_t subscribeId,int32_t failedReason)234 void DmDiscoveryManager::OnDiscoveryFailed(const std::string &pkgName, int32_t subscribeId, int32_t failedReason)
235 {
236     LOGI("DmDiscoveryManager::OnDiscoveryFailed subscribeId = %{public}d reason = %{public}d", subscribeId,
237         failedReason);
238     if (pkgName.empty()) {
239         LOGE("Invalid parameter, pkgName is empty.");
240         return;
241     }
242     {
243         std::lock_guard<std::mutex> autoLock(locks_);
244         if (!discoveryQueue_.empty()) {
245             discoveryQueue_.pop();
246         }
247         if (!discoveryContextMap_.empty()) {
248             discoveryContextMap_.erase(pkgName);
249             if (timer_ != nullptr) {
250                 timer_->DeleteTimer(std::string(DISCOVERY_TIMEOUT_TASK));
251             }
252         }
253     }
254     softbusConnector_->StopDiscovery(subscribeId);
255     listener_->OnDiscoveryFailed(pkgName, (uint32_t)subscribeId, failedReason);
256 }
257 
OnDiscoverySuccess(const std::string & pkgName,int32_t subscribeId)258 void DmDiscoveryManager::OnDiscoverySuccess(const std::string &pkgName, int32_t subscribeId)
259 {
260     LOGI("DmDiscoveryManager::OnDiscoverySuccess subscribeId = %{public}d", subscribeId);
261     {
262         std::lock_guard<std::mutex> autoLock(locks_);
263         discoveryContextMap_[pkgName].subscribeId = (uint32_t)subscribeId;
264     }
265     listener_->OnDiscoverySuccess(pkgName, subscribeId);
266 }
267 
HandleDiscoveryTimeout(std::string name)268 void DmDiscoveryManager::HandleDiscoveryTimeout(std::string name)
269 {
270     (void)name;
271     LOGI("DmDiscoveryManager::HandleDiscoveryTimeout");
272     uint16_t subscribeId = 0;
273     std::string pkgName = "";
274     {
275         std::lock_guard<std::mutex> autoLock(locks_);
276         if (discoveryQueue_.empty()) {
277             LOGE("HandleDiscoveryTimeout: discovery queue is empty.");
278             return;
279         }
280 
281         pkgName = discoveryQueue_.front();
282         auto iter = discoveryContextMap_.find(pkgName);
283         if (iter == discoveryContextMap_.end()) {
284             LOGE("HandleDiscoveryTimeout: subscribeId not found by pkgName %{public}s",
285                 GetAnonyString(pkgName).c_str());
286             return;
287         }
288         subscribeId = discoveryContextMap_[pkgName].subscribeId;
289     }
290     StopDeviceDiscovery(pkgName, subscribeId);
291 }
292 } // namespace DistributedHardware
293 } // namespace OHOS
294