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