• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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