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             timer_->DeleteTimer(std::string(DISCOVERY_TIMEOUT_TASK));
134         }
135     }
136     softbusConnector_->UnRegisterSoftbusDiscoveryCallback(pkgName);
137     return softbusConnector_->StopDiscovery(subscribeId);
138 }
139 
OnDeviceFound(const std::string &pkgName, DmDeviceInfo &info, bool isOnline)140 void DmDiscoveryManager::OnDeviceFound(const std::string &pkgName, DmDeviceInfo &info, bool isOnline)
141 {
142     LOGI("DmDiscoveryManager::OnDeviceFound deviceId = %{public}s", GetAnonyString(info.deviceId).c_str());
143     DmDiscoveryContext discoveryContext;
144     {
145         std::lock_guard<std::mutex> autoLock(locks_);
146         auto iter = discoveryContextMap_.find(pkgName);
147         if (iter == discoveryContextMap_.end()) {
148             LOGE("subscribeId not found by pkgName %{public}s", GetAnonyString(pkgName).c_str());
149             return;
150         }
151         discoveryContext = iter->second;
152     }
153     DmDiscoveryFilter filter;
154     DmDeviceFilterPara filterPara;
155     filterPara.isOnline = isOnline;
156     filterPara.range = info.range;
157     filterPara.deviceType = info.deviceTypeId;
158     char localDeviceId[DEVICE_UUID_LENGTH];
159     GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH);
160     info.authForm = DmAuthForm::INVALID_TYPE;
161     GetAuthForm(localDeviceId, info.deviceId, filterPara.isTrusted, info.authForm);
162     filterPara.authForm = info.authForm;
163     if (filter.IsValidDevice(discoveryContext.filterOp, discoveryContext.filters, filterPara)) {
164         listener_->OnDeviceFound(pkgName, discoveryContext.subscribeId, info);
165     }
166     return;
167 }
168 
GetAuthForm(const std::string &localDeviceId, const std::string &deviceId, bool &isTrusted, DmAuthForm &authForm)169 int32_t DmDiscoveryManager::GetAuthForm(const std::string &localDeviceId, const std::string &deviceId,
170     bool &isTrusted, DmAuthForm &authForm)
171 {
172     LOGI("Get localDeviceId: %{public}s auth form.", GetAnonyString(localDeviceId).c_str());
173     isTrusted = false;
174     if (localDeviceId.empty() || deviceId.empty()) {
175         LOGE("Invalid parameter.");
176         return ERR_DM_INPUT_PARA_INVALID;
177     }
178     if (hiChainConnector_ == nullptr || softbusConnector_ == nullptr) {
179         LOGE("hiChainConnector_ or softbusConnector_ is nullpter.");
180         return ERR_DM_POINT_NULL;
181     }
182 
183     std::vector<std::string> trustDeviceUdidList = hiChainConnector_->GetTrustedDevices(localDeviceId);
184     if (trustDeviceUdidList.empty()) {
185         LOGI("Trusted devices is empty.");
186         return DM_OK;
187     }
188     std::string udidHash;
189     for (auto udid : trustDeviceUdidList) {
190         udidHash = softbusConnector_->GetDeviceUdidHashByUdid(udid);
191         if (udidHash == deviceId) {
192             isTrusted = true;
193             authForm = hiChainConnector_->GetGroupType(udid);
194             LOGI("deviceId: %{public}s is trusted!", GetAnonyString(deviceId).c_str());
195         }
196     }
197 
198     return DM_OK;
199 }
200 
OnDeviceFound(const std::string &pkgName, DmDeviceBasicInfo &info, const int32_t range, bool isOnline)201 void DmDiscoveryManager::OnDeviceFound(const std::string &pkgName,
202     DmDeviceBasicInfo &info, const int32_t range, bool isOnline)
203 {
204     LOGI("DmDiscoveryManager::OnDeviceFound deviceId = %{public}s,isOnline %{public}d",
205         GetAnonyString(info.deviceId).c_str(), isOnline);
206     DmDiscoveryContext discoveryContext;
207     {
208         std::lock_guard<std::mutex> autoLock(locks_);
209         auto iter = discoveryContextMap_.find(pkgName);
210         if (iter == discoveryContextMap_.end()) {
211             LOGE("subscribeId not found by pkgName %{public}s", GetAnonyString(pkgName).c_str());
212             return;
213         }
214         discoveryContext = iter->second;
215     }
216     DmDiscoveryFilter filter;
217     DmDeviceFilterPara filterPara;
218     filterPara.isOnline = isOnline;
219     filterPara.range = range;
220     filterPara.deviceType = info.deviceTypeId;
221     char localDeviceId[DEVICE_UUID_LENGTH];
222     GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH);
223     DmAuthForm authForm = DmAuthForm::INVALID_TYPE;
224     GetAuthForm(localDeviceId, info.deviceId, filterPara.isTrusted, authForm);
225     filterPara.authForm = authForm;
226     if (filter.IsValidDevice(discoveryContext.filterOp, discoveryContext.filters, filterPara)) {
227         listener_->OnDeviceFound(pkgName, discoveryContext.subscribeId, info);
228     }
229     return;
230 }
231 
OnDiscoveryFailed(const std::string &pkgName, int32_t subscribeId, int32_t failedReason)232 void DmDiscoveryManager::OnDiscoveryFailed(const std::string &pkgName, int32_t subscribeId, int32_t failedReason)
233 {
234     LOGI("DmDiscoveryManager::OnDiscoveryFailed subscribeId = %{public}d reason = %{public}d", subscribeId,
235         failedReason);
236     if (pkgName.empty()) {
237         LOGE("Invalid parameter, pkgName is empty.");
238         return;
239     }
240     {
241         std::lock_guard<std::mutex> autoLock(locks_);
242         if (!discoveryQueue_.empty()) {
243             discoveryQueue_.pop();
244         }
245         if (!discoveryContextMap_.empty()) {
246             discoveryContextMap_.erase(pkgName);
247             timer_->DeleteTimer(std::string(DISCOVERY_TIMEOUT_TASK));
248         }
249     }
250     softbusConnector_->StopDiscovery(subscribeId);
251     listener_->OnDiscoveryFailed(pkgName, (uint32_t)subscribeId, failedReason);
252 }
253 
OnDiscoverySuccess(const std::string &pkgName, int32_t subscribeId)254 void DmDiscoveryManager::OnDiscoverySuccess(const std::string &pkgName, int32_t subscribeId)
255 {
256     LOGI("DmDiscoveryManager::OnDiscoverySuccess subscribeId = %{public}d", subscribeId);
257     {
258         std::lock_guard<std::mutex> autoLock(locks_);
259         discoveryContextMap_[pkgName].subscribeId = (uint32_t)subscribeId;
260     }
261     listener_->OnDiscoverySuccess(pkgName, subscribeId);
262 }
263 
HandleDiscoveryTimeout(std::string name)264 void DmDiscoveryManager::HandleDiscoveryTimeout(std::string name)
265 {
266     (void)name;
267     LOGI("DmDiscoveryManager::HandleDiscoveryTimeout");
268     uint16_t subscribeId = 0;
269     std::string pkgName = "";
270     {
271         std::lock_guard<std::mutex> autoLock(locks_);
272         if (discoveryQueue_.empty()) {
273             LOGE("HandleDiscoveryTimeout: discovery queue is empty.");
274             return;
275         }
276 
277         pkgName = discoveryQueue_.front();
278         auto iter = discoveryContextMap_.find(pkgName);
279         if (iter == discoveryContextMap_.end()) {
280             LOGE("HandleDiscoveryTimeout: subscribeId not found by pkgName %{public}s",
281                 GetAnonyString(pkgName).c_str());
282             return;
283         }
284         subscribeId = discoveryContextMap_[pkgName].subscribeId;
285     }
286     StopDeviceDiscovery(pkgName, subscribeId);
287 }
288 } // namespace DistributedHardware
289 } // namespace OHOS
290