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