1 /*
2 * Copyright (C) 2023-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 * Description: implement the cast source discovery
15 * Author: zhangge
16 * Create: 2022-08-23
17 */
18 #include <ipc_skeleton.h>
19 #include <algorithm>
20 #include <thread>
21
22 #include "discovery_manager.h"
23 #include "connection_manager.h"
24 #include "cast_device_data_manager.h"
25 #include "cast_engine_dfx.h"
26 #include "cast_engine_log.h"
27 #include "dm_constants.h"
28 #include "parameters.h"
29 #include "securec.h"
30 #include "softbus_common.h"
31 #include "utils.h"
32 #include "json.hpp"
33
34 using namespace OHOS::DistributedHardware;
35 using namespace OHOS::AppExecFwk;
36
37 using nlohmann::json;
38
39 namespace OHOS {
40 namespace CastEngine {
41 namespace CastEngineService {
42 DEFINE_CAST_ENGINE_LABEL("Cast-Discovery-Manager");
43
44 namespace {
45 constexpr int AV_SESSION_UID = 6700;
46 constexpr int REMOTE_DIED_SLEEP = 4000;
47 constexpr int DISCOVERY_DELAY_TIME = 3000;
48 constexpr int TIMEOUT_COUNT = 40;
49 constexpr int EVENT_START_DISCOVERY = 1;
50 constexpr int EVENT_CONTINUE_DISCOVERY = 2;
51 const std::string DISCOVERY_TRUST_VALUE = R"({"filters": [{"type": "isTrusted", "value": 2}]})";
52
ConvertDeviceType(uint16_t deviceTypeId)53 DeviceType ConvertDeviceType(uint16_t deviceTypeId)
54 {
55 switch (deviceTypeId) {
56 case DEVICE_TYPE_TV:
57 return DeviceType::DEVICE_HW_TV;
58 case DEVICE_TYPE_PAD:
59 return DeviceType::DEVICE_PAD;
60 case DEVICE_TYPE_CAR:
61 return DeviceType::DEVICE_HICAR;
62 case DEVICE_TYPE_2IN1:
63 return DeviceType::DEVICE_TYPE_2IN1;
64 default:
65 return DeviceType::DEVICE_CAST_PLUS;
66 }
67 }
68 } // namespace
69
OnRemoteDied()70 void CastDmInitCallback::OnRemoteDied()
71 {
72 CLOGE("DM is dead, deinit the DiscoveryManager");
73 std::thread([]() {
74 std::this_thread::sleep_for(std::chrono::milliseconds(REMOTE_DIED_SLEEP));
75 constexpr int sleepTime = 100; // uint: ms
76 constexpr int retryTimes = 10 * 10; // total 10s
77 for (int32_t retryTime = 0; retryTime < retryTimes; ++retryTime) {
78 std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
79 if (DeviceManager::GetInstance().InitDeviceManager(PKG_NAME,
80 std::make_shared<CastDmInitCallback>()) == DM_OK) {
81 CLOGI("DeviceManager onDied, try to init success, retryTime = %d", retryTime);
82 return;
83 }
84 CLOGI("DeviceManager onDied, try to init fail, retryTime = %d", retryTime);
85 }
86 CLOGI("DeviceManager onDied, try to init has reached the maximum, but still failed");
87 DiscoveryManager::GetInstance().Deinit();
88 return;
89 }).detach();
90 }
91
GetInstance()92 DiscoveryManager &DiscoveryManager::GetInstance()
93 {
94 static DiscoveryManager instance{};
95 return instance;
96 }
97
Init(std::shared_ptr<IDiscoveryManagerListener> listener)98 void DiscoveryManager::Init(std::shared_ptr<IDiscoveryManagerListener> listener)
99 {
100 CLOGD("init start");
101 eventRunner_ = EventRunner::Create("cast-discovery-manager");
102 eventHandler_ = std::make_shared<DiscoveryEventHandler>(eventRunner_);
103 if (listener == nullptr) {
104 CLOGE("The input listener is null!");
105 return;
106 }
107
108 if (HasListener()) {
109 CLOGE("Already inited");
110 return;
111 }
112
113 if (DeviceManager::GetInstance().InitDeviceManager(PKG_NAME, std::make_shared<CastDmInitCallback>()) != DM_OK) {
114 CLOGE("Failed to InitDeviceManager");
115 return;
116 }
117
118 SetListener(listener);
119 CLOGD("init done");
120 }
121
Deinit()122 void DiscoveryManager::Deinit()
123 {
124 if (!HasListener()) {
125 return;
126 }
127
128 StopDiscovery();
129 ResetListener();
130 DeviceManager::GetInstance().UnInitDeviceManager(PKG_NAME);
131 eventRunner_->Stop();
132 }
133
GetAndReportTrustedDevices()134 void DiscoveryManager::GetAndReportTrustedDevices()
135 {
136 std::vector<DmDeviceInfo> dmDevices;
137 auto result = DeviceManager::GetInstance().GetTrustedDeviceList(PKG_NAME, "", true, dmDevices);
138 if (result != DM_OK || dmDevices.size() == 0) {
139 CLOGW("No trusted devices, result:%d", result);
140 return;
141 }
142 for (const auto &dmDevice : dmDevices) {
143 CLOGI("GetAndReportTrustedDevices, device id is %s, device name is %s", dmDevice.deviceId, dmDevice.deviceName);
144 CastInnerRemoteDevice newDevice = CreateRemoteDevice(dmDevice);
145 NotifyDeviceIsFound(newDevice);
146 }
147 }
148
UpdateDeviceState()149 void DiscoveryManager::UpdateDeviceState()
150 {
151 auto it = std::find_if(remoteDeviceMap.begin(), remoteDeviceMap.end(), [&](const auto& pair) {
152 return scanCount - pair.second >=1 ;
153 });
154 if (it != remoteDeviceMap.end()) {
155 CastInnerRemoteDevice remoteDevice = it->first;
156 CLOGE("StartDmDiscovery offline: %{public}s", remoteDevice.deviceName.c_str());
157 ConnectionManager::GetInstance().NotifyDeviceIsOffline(remoteDevice.deviceId);
158 CastDeviceDataManager::GetInstance().RemoveDevice(remoteDevice.deviceId);
159 remoteDeviceMap.erase(it);
160 }
161 }
162
StartDmDiscovery()163 void DiscoveryManager::StartDmDiscovery()
164 {
165 CLOGI("StartDmDiscovery in");
166 UpdateDeviceState();
167 scanCount++;
168 std::map<std::string, std::string> discoverParam{
169 { PARAM_KEY_META_TYPE, std::to_string(5) } };
170 std::map<std::string, std::string> filterOptions{
171 { PARAM_KEY_FILTER_OPTIONS, DISCOVERY_TRUST_VALUE } };
172 int32_t ret = DeviceManager::GetInstance().StartDiscovering(PKG_NAME, discoverParam, filterOptions,
173 std::make_shared<CastDiscoveryCallback>());
174 if (ret != DM_OK && ret != ERR_DM_DISCOVERY_REPEATED) {
175 CLOGE("Failed to start discovery, ret:%d", ret);
176 CastEngineDfx::WriteErrorEvent(START_DISCOVERY_FAIL);
177 }
178 }
179
StopDmDiscovery()180 void DiscoveryManager::StopDmDiscovery()
181 {
182 CLOGI("StopDmDiscovery in");
183 std::map<std::string, std::string> discoverParam = {};
184 DeviceManager::GetInstance().StopDiscovering(PKG_NAME, discoverParam);
185 }
186
StartAdvertise()187 bool DiscoveryManager::StartAdvertise()
188 {
189 CLOGI("PublishDiscovery in");
190 std::map<std::string, std::string> advertiseParam { { PARAM_KEY_DISC_CAPABILITY, DM_CAPABILITY_CASTPLUS } };
191 int ret = DeviceManager::GetInstance().StartAdvertising(PKG_NAME, advertiseParam,
192 std::make_shared<CastPublishDiscoveryCallback>());
193 if (ret != DM_OK) {
194 CLOGE("Failed to publish discovery, ret:%d", ret);
195 return false;
196 }
197 return true;
198 }
199
StopAdvertise()200 bool DiscoveryManager::StopAdvertise()
201 {
202 CLOGI("UnPublishDiscoveryv in");
203 std::map<std::string, std::string> advertiseParam = {};
204 int ret = DeviceManager::GetInstance().StopAdvertising(PKG_NAME, advertiseParam);
205 if (ret != DM_OK) {
206 CLOGE("Failed to unpublish discovery, ret:%d", ret);
207 return false;
208 }
209 return true;
210 }
211
SetProtocolType(int protocols)212 void DiscoveryManager::SetProtocolType(int protocols)
213 {
214 protocolType_ = protocols;
215 }
216
GetProtocolType() const217 int DiscoveryManager::GetProtocolType() const
218 {
219 return protocolType_;
220 }
221
StartDiscovery()222 void DiscoveryManager::StartDiscovery()
223 {
224 HiSysEventWriteWrap(__func__, {
225 {"BIZ_SCENE", static_cast<int32_t>(BIZSceneType::DEVICE_DISCOVERY)},
226 {"BIZ_STATE", static_cast<int32_t>(BIZStateType::BIZ_STATE_BEGIN)},
227 {"BIZ_STAGE", static_cast<int32_t>(BIZSceneStage::START_DISCOVERY)},
228 {"STAGE_RES", static_cast<int32_t>(StageResType::STAGE_RES_IDLE)},
229 {"ERROR_CODE", CAST_RADAR_SUCCESS}}, {
230 {"TO_CALL_PKG", ""},
231 {"LOCAL_SESS_NAME", ""},
232 {"PEER_SESS_NAME", ""},
233 {"PEER_UDID", ""}});
234
235 CLOGI("StartDiscovery in");
236 scanCount = 0;
237 remoteDeviceMap.clear();
238 std::lock_guard<std::mutex> lock(mutex_);
239 uid_ = IPCSkeleton::GetCallingUid();
240 eventHandler_->SendEvent(EVENT_START_DISCOVERY);
241 CLOGI("StartDiscovery out");
242 }
243
StopDiscovery()244 void DiscoveryManager::StopDiscovery()
245 {
246 CLOGI("StopDiscovery in");
247 StopDmDiscovery();
248 eventHandler_->RemoveAllEvents();
249 }
250
SetListener(std::shared_ptr<IDiscoveryManagerListener> listener)251 void DiscoveryManager::SetListener(std::shared_ptr<IDiscoveryManagerListener> listener)
252 {
253 std::lock_guard<std::mutex> lock(mutex_);
254 listener_ = listener;
255 }
256
HasListener()257 bool DiscoveryManager::HasListener()
258 {
259 std::lock_guard<std::mutex> lock(mutex_);
260 return listener_ != nullptr;
261 }
262
ResetListener()263 void DiscoveryManager::ResetListener()
264 {
265 SetListener(nullptr);
266 }
267
RemoveSameDeviceLocked(const CastInnerRemoteDevice & newDevice)268 void DiscoveryManager::RemoveSameDeviceLocked(const CastInnerRemoteDevice &newDevice)
269 {
270 auto it = std::find_if(remoteDeviceMap.begin(), remoteDeviceMap.end(), [&](const auto& pair) {
271 return pair.first.deviceId == newDevice.deviceId;
272 });
273 if (it != remoteDeviceMap.end()) {
274 remoteDeviceMap.erase(it);
275 }
276 }
277
CreateRemoteDevice(const DmDeviceInfo & dmDeviceInfo)278 CastInnerRemoteDevice DiscoveryManager::CreateRemoteDevice(const DmDeviceInfo &dmDeviceInfo)
279 {
280 CastInnerRemoteDevice newDevice = {
281 .deviceId = dmDeviceInfo.deviceId,
282 .deviceName = dmDeviceInfo.deviceName,
283 .deviceType = ConvertDeviceType(dmDeviceInfo.deviceTypeId),
284 .deviceTypeId = dmDeviceInfo.deviceTypeId,
285 .subDeviceType = SubDeviceType::SUB_DEVICE_DEFAULT,
286 .channelType = ChannelType::SOFT_BUS,
287 .networkId = dmDeviceInfo.networkId
288 };
289
290 ParseDeviceInfo(dmDeviceInfo, newDevice);
291
292 return newDevice;
293 }
294
295 // {"BLE_MAC":"74:41:3d:f3:3d:cd","BLE_UDID_HASH":"xxxxxx","CONN_ADDR_TYPE":"BLE_TYPE","CUSTOM_DATA":""}
296 // {"CONN_ADDR_TYPE":"WLAN_IP_TYPE","CUSTOM_DATA":"{\"castPlus\":\"\"}","WIFI_IP":"192.168.135.204","WIFI_PORT":36767}
OnDeviceInfoFound(uint16_t subscribeId,const DmDeviceInfo & dmDeviceInfo)297 void DiscoveryManager::OnDeviceInfoFound(uint16_t subscribeId, const DmDeviceInfo &dmDeviceInfo)
298 {
299 CLOGD("OnDeviceInfoFound in deviceName: %{public}s, deviceId: %{public}s, extra: %{public}s",
300 dmDeviceInfo.deviceName, dmDeviceInfo.deviceId, dmDeviceInfo.extraData.c_str());
301 CastInnerRemoteDevice newDevice = CreateRemoteDevice(dmDeviceInfo);
302
303 // If the map does not exist, the notification is sent.
304 auto it = remoteDeviceMap.find(newDevice);
305 if (it == remoteDeviceMap.end()) {
306 // If the deviceId are the same, delete the old device.
307 RemoveSameDeviceLocked(newDevice);
308
309 // Set subDeviceType based on isTrusted.
310 std::string networkId = dmDeviceInfo.networkId;
311 bool isTrusted = ConnectionManager::GetInstance().IsDeviceTrusted(dmDeviceInfo.deviceId, networkId);
312 if (!isTrusted) {
313 newDevice.subDeviceType = SubDeviceType::SUB_DEVICE_MATEBOOK_PAD;
314 }
315
316 if (CastDeviceDataManager::GetInstance().AddDevice(newDevice, dmDeviceInfo)) {
317 NotifyDeviceIsFound(newDevice);
318 }
319 }
320 remoteDeviceMap[newDevice] = scanCount;
321 }
322
NotifyDeviceIsFound(const CastInnerRemoteDevice & newDevice)323 void DiscoveryManager::NotifyDeviceIsFound(const CastInnerRemoteDevice &newDevice)
324 {
325 std::vector<CastInnerRemoteDevice> devices;
326 std::vector<CastInnerRemoteDevice> device2In1;
327
328 if (newDevice.deviceType == DeviceType::DEVICE_TYPE_2IN1) {
329 CLOGI("device type is 2IN1");
330 device2In1.push_back(newDevice);
331 }
332 devices.push_back(newDevice);
333
334 std::lock_guard<std::mutex> lock(mutex_);
335 listener_->OnDeviceFound(devices);
336 if (uid_ == AV_SESSION_UID) {
337 listener_->OnDeviceFound(device2In1);
338 return;
339 }
340 }
341
NotifyDeviceIsOnline(const DmDeviceInfo & dmDeviceInfo)342 void DiscoveryManager::NotifyDeviceIsOnline(const DmDeviceInfo &dmDeviceInfo)
343 {
344 CastInnerRemoteDevice newDevice = CreateRemoteDevice(dmDeviceInfo);
345 NotifyDeviceIsFound(newDevice);
346 }
347
ParseDeviceInfo(const DmDeviceInfo & dmDevice,CastInnerRemoteDevice & castDevice)348 void DiscoveryManager::ParseDeviceInfo(const DmDeviceInfo &dmDevice, CastInnerRemoteDevice &castDevice)
349 {
350 CLOGD("parse castData extraData is %s", dmDevice.extraData.c_str());
351 auto ret = CastDeviceDataManager::GetInstance().GetDeviceNameByDeviceId(dmDevice.deviceId);
352 std::string deviceName = ret != std::nullopt ? *ret : "";
353 json jsonObj = json::parse(dmDevice.extraData, nullptr, false);
354 if (!jsonObj.is_discarded()) {
355 if (jsonObj.contains(PARAM_KEY_WIFI_IP) && jsonObj[PARAM_KEY_WIFI_IP].is_string()) {
356 castDevice.wifiIp = jsonObj[PARAM_KEY_WIFI_IP];
357 castDevice.deviceName = !castDevice.deviceName.empty() ? castDevice.deviceName : deviceName;
358 }
359 if (jsonObj.contains(PARAM_KEY_WIFI_PORT) && jsonObj[PARAM_KEY_WIFI_PORT].is_number()) {
360 castDevice.wifiPort = jsonObj[PARAM_KEY_WIFI_PORT];
361 castDevice.deviceName = !castDevice.deviceName.empty() ? castDevice.deviceName : deviceName;
362 }
363 if (jsonObj.contains(PARAM_KEY_BLE_MAC) && jsonObj[PARAM_KEY_BLE_MAC].is_string()) {
364 castDevice.bleMac = jsonObj[PARAM_KEY_BLE_MAC];
365 castDevice.deviceName = !deviceName.empty() ? deviceName : castDevice.deviceName;
366 }
367 if (jsonObj.contains(PARAM_KEY_CUSTOM_DATA) && jsonObj[PARAM_KEY_CUSTOM_DATA].is_string()) {
368 std::string customData = jsonObj[PARAM_KEY_CUSTOM_DATA];
369 json softbusCustData = json::parse(customData, nullptr, false);
370 if (softbusCustData.contains("castPlus") && softbusCustData["castPlus"].is_string()) {
371 std::string castData = softbusCustData["castPlus"];
372 castDevice.customData = castData;
373 }
374 if (softbusCustData.contains("castId") && softbusCustData["castId"].is_string()) {
375 castDevice.udid = softbusCustData["castId"];
376 }
377 }
378 } else {
379 CLOGE("dm device extraData parse error");
380 }
381 }
382
OnDiscoverySuccess(uint16_t subscribeId)383 void CastDiscoveryCallback::OnDiscoverySuccess(uint16_t subscribeId)
384 {
385 CLOGI("OnDiscoverySuccess, subscribe id:%{public}u", subscribeId);
386 }
387
OnDiscoveryFailed(uint16_t subscribeId,int32_t failedReason)388 void CastDiscoveryCallback::OnDiscoveryFailed(uint16_t subscribeId, int32_t failedReason)
389 {
390 auto errorCode = GetErrorCode(CAST_ENGINE_SYSTEM_ID, CAST_ENGINE_CAST_PLUS_MODULE_ID, subscribeId);
391 HiSysEventWriteWrap(__func__, {
392 {"BIZ_SCENE", static_cast<int32_t>(BIZSceneType::DEVICE_DISCOVERY)},
393 {"BIZ_STATE", static_cast<int32_t>(BIZStateType::BIZ_STATE_END)},
394 {"BIZ_STAGE", static_cast<int32_t>(BIZSceneStage::DEVICE_DISCOVERY)},
395 {"STAGE_RES", static_cast<int32_t>(StageResType::STAGE_RES_FAILED)},
396 {"ERROR_CODE", errorCode}}, {
397 {"TO_CALL_PKG", DEVICE_MANAGER_NAME},
398 {"LOCAL_SESS_NAME", ""},
399 {"PEER_SESS_NAME", ""},
400 {"PEER_UDID", ""}});
401
402 CLOGI("OnDiscoveryFailed, subscribe id:%{public}u, reason:%{public}d", subscribeId, failedReason);
403 }
404
OnDeviceFound(uint16_t subscribeId,const DmDeviceInfo & deviceInfo)405 void CastDiscoveryCallback::OnDeviceFound(uint16_t subscribeId, const DmDeviceInfo &deviceInfo)
406 {
407 CLOGI("OnDeviceInfoFound in, subscribe id:%{public}u, device id:%s, device name:%s", subscribeId,
408 deviceInfo.deviceId, deviceInfo.deviceName);
409 DiscoveryManager::GetInstance().OnDeviceInfoFound(subscribeId, deviceInfo);
410 }
411
OnPublishResult(int32_t publishId,int32_t publishResult)412 void CastPublishDiscoveryCallback::OnPublishResult(int32_t publishId, int32_t publishResult)
413 {
414 CLOGI("OnPublishResult publishId is %{public}d, publishResult is %{public}d", publishId, publishResult);
415 }
416
ProcessEvent(const InnerEvent::Pointer & event)417 void DiscoveryEventHandler::ProcessEvent(const InnerEvent::Pointer &event)
418 {
419 DiscoveryManager::GetInstance().StopDmDiscovery();
420 auto eventId = event->GetInnerEventId();
421 switch (eventId) {
422 case EVENT_START_DISCOVERY:
423 scanCount = 1;
424 SendEvent(EVENT_CONTINUE_DISCOVERY, DISCOVERY_DELAY_TIME);
425 break;
426 case EVENT_CONTINUE_DISCOVERY:
427 scanCount++;
428 if (scanCount < TIMEOUT_COUNT) {
429 SendEvent(EVENT_CONTINUE_DISCOVERY, DISCOVERY_DELAY_TIME);
430 }
431 break;
432 default:
433 break;
434 }
435 CLOGI("handler run, thread name: %{public}s, scanCount: %{public}d, eventId: %{public}d",
436 GetEventRunner()->GetRunnerThreadName().c_str(), scanCount, eventId);
437 DiscoveryManager::GetInstance().StartDmDiscovery();
438 }
439 } // namespace CastEngineService
440 } // namespace CastEngine
441 } // namespace OHOS
442