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