• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "device/device_manager_agent.h"
17 
18 #include <limits>
19 #include <sstream>
20 #include <string>
21 
22 #include "device_auth.h"
23 #include "dfsu_exception.h"
24 #include "ipc/i_daemon.h"
25 #include "mountpoint/mount_manager.h"
26 #include "network/devsl_dispatcher.h"
27 #include "network/softbus/softbus_agent.h"
28 #include "parameters.h"
29 #include "softbus_bus_center.h"
30 #include "utils_log.h"
31 
32 namespace OHOS {
33 namespace Storage {
34 namespace DistributedFile {
35 namespace {
36 constexpr int MAX_RETRY_COUNT = 7;
37 constexpr int PEER_TO_PEER_GROUP = 256;
38 constexpr int ACROSS_ACCOUNT_AUTHORIZE_GROUP = 1282;
39 const std::string SAME_ACCOUNT_MARK = "const.distributed_file_only_for_same_account_test";
40 } // namespace
41 using namespace std;
42 
DeviceManagerAgent()43 DeviceManagerAgent::DeviceManagerAgent() : DfsuActor<DeviceManagerAgent>(this, std::numeric_limits<uint32_t>::max()) {}
44 
~DeviceManagerAgent()45 DeviceManagerAgent::~DeviceManagerAgent()
46 {
47     try {
48         StopInstance();
49     } catch (const DfsuException &e) {
50         // do not throw exception
51     } catch (const std::exception &e) {
52         // do not throw exception
53     }
54 }
55 
StartInstance()56 void DeviceManagerAgent::StartInstance()
57 {
58     StartActor();
59 }
60 
StopInstance()61 void DeviceManagerAgent::StopInstance()
62 {
63     StopActor();
64 }
65 
Start()66 void DeviceManagerAgent::Start()
67 {
68     DevslDispatcher::Start();
69     RegisterToExternalDm();
70     InitLocalNodeInfo();
71 }
72 
Stop()73 void DeviceManagerAgent::Stop()
74 {
75     UnregisterFromExternalDm();
76     DevslDispatcher::Stop();
77 }
78 
JoinGroup(weak_ptr<MountPoint> mp)79 void DeviceManagerAgent::JoinGroup(weak_ptr<MountPoint> mp)
80 {
81     LOGI("join group begin");
82     auto smp = mp.lock();
83     if (!smp) {
84         stringstream ss("Failed to join group: Received empty mountpoint");
85         LOGE("%{public}s", ss.str().c_str());
86         throw runtime_error(ss.str());
87     }
88 
89     shared_ptr<SoftbusAgent> agent = nullptr;
90     {
91         unique_lock<mutex> lock(mpToNetworksMutex_);
92         agent = make_shared<SoftbusAgent>(mp);
93         auto [ignored, inserted] = mpToNetworks_.insert({ smp->GetID(), agent });
94         if (!inserted) {
95             stringstream ss;
96             ss << "Failed to join group: Mountpoint existed" << smp->ToString();
97             throw runtime_error(ss.str());
98         }
99     }
100     agent->StartActor();
101     LOGI("join group end, id : %{public}d, account : %{public}s", smp->GetID(), smp->isAccountLess() ? "no" : "yes");
102 }
103 
QuitGroup(weak_ptr<MountPoint> mp)104 void DeviceManagerAgent::QuitGroup(weak_ptr<MountPoint> mp)
105 {
106     LOGI("quit group begin");
107     OfflineAllDevice();
108 
109     auto smp = mp.lock();
110     if (!smp) {
111         stringstream ss("Failed to quit group: Received empty mountpoint");
112         LOGE("%{public}s", ss.str().c_str());
113         throw runtime_error(ss.str());
114     }
115 
116     unique_lock<mutex> lock(mpToNetworksMutex_);
117     auto it = mpToNetworks_.find(smp->GetID());
118     if (it == mpToNetworks_.end()) {
119         stringstream ss;
120         ss << "Failed to quit group: Mountpoint didn't exist " << smp->ToString();
121         throw runtime_error(ss.str());
122     }
123 
124     it->second->StopActor();
125     mpToNetworks_.erase(smp->GetID());
126     LOGI("quit group end, id : %{public}d, account : %{public}s", smp->GetID(), smp->isAccountLess() ? "no" : "yes");
127 }
128 
OfflineAllDevice()129 void DeviceManagerAgent::OfflineAllDevice()
130 {
131     unique_lock<mutex> lock(mpToNetworksMutex_);
132     for (auto [ignore, net] : cidNetTypeRecord_) {
133         if (net == nullptr) {
134             continue;
135         }
136         auto cmd = make_unique<DfsuCmd<NetworkAgentTemplate>>(&NetworkAgentTemplate::DisconnectAllDevices);
137         net->Recv(move(cmd));
138     }
139 }
140 
ReconnectOnlineDevices()141 void DeviceManagerAgent::ReconnectOnlineDevices()
142 {
143     unique_lock<mutex> lock(mpToNetworksMutex_);
144     for (auto [ignore, net] : cidNetTypeRecord_) {
145         if (net == nullptr) {
146             continue;
147         }
148         auto cmd = make_unique<DfsuCmd<NetworkAgentTemplate>>(&NetworkAgentTemplate::ConnectOnlineDevices);
149         cmd->UpdateOption({
150             .tryTimes_ = MAX_RETRY_COUNT,
151         });
152         net->Recv(move(cmd));
153     }
154 }
155 
FindNetworkBaseTrustRelation(bool isAccountless)156 std::shared_ptr<NetworkAgentTemplate> DeviceManagerAgent::FindNetworkBaseTrustRelation(bool isAccountless)
157 {
158     LOGI("enter: isAccountless %{public}d", isAccountless);
159     for (auto [ignore, net] : mpToNetworks_) {
160         if (net != nullptr) {
161             auto smp = net->GetMountPoint();
162             if (smp != nullptr && smp->isAccountLess() == isAccountless) {
163                 return net;
164             }
165         }
166     }
167     LOGE("not find this net in mpToNetworks, isAccountless %{public}d", isAccountless);
168     return nullptr;
169 }
170 
GetNetworkType(const string & cid)171 int32_t DeviceManagerAgent::GetNetworkType(const string &cid)
172 {
173     int32_t networkType = 0;
174     string pkgName = IDaemon::SERVICE_NAME;
175     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
176     int errCode = deviceManager.GetNetworkTypeByNetworkId(pkgName, cid, networkType);
177     if (errCode) {
178         LOGE("get network type error:%{public}d", errCode);
179     }
180 
181     return networkType;
182 }
183 
IsWifiNetworkType(int32_t networkType)184 bool DeviceManagerAgent::IsWifiNetworkType(int32_t networkType)
185 {
186     if ((networkType == -1) || !(networkType & (1 << DistributedHardware::BIT_NETWORK_TYPE_WIFI))) {
187         return false;
188     }
189 
190     return true;
191 }
192 
OnDeviceOnline(const DistributedHardware::DmDeviceInfo & deviceInfo)193 void DeviceManagerAgent::OnDeviceOnline(const DistributedHardware::DmDeviceInfo &deviceInfo)
194 {
195     LOGI("networkId %{public}s, OnDeviceOnline begin", deviceInfo.deviceId);
196 
197     // online first query this dev's trust info
198     DeviceInfo info(deviceInfo);
199     QueryRelatedGroups(info.udid_, info.cid_);
200 
201     // based on dev's trust info, choose corresponding network agent to obtain socket
202     unique_lock<mutex> lock(mpToNetworksMutex_);
203 
204     auto it = cidNetTypeRecord_.find(info.cid_);
205     if (it == cidNetTypeRecord_.end()) {
206         LOGE("cid %{public}s network is null!", info.cid_.c_str());
207         LOGI("OnDeviceOnline end");
208         return;
209     }
210 
211     auto type_ = cidNetworkType_.find(info.cid_);
212     if (type_ == cidNetworkType_.end()) {
213         LOGE("cid %{public}s network type is null!", info.cid_.c_str());
214         LOGI("OnDeviceOnline end");
215         return;
216     }
217 
218     int32_t newNetworkType = type_->second = GetNetworkType(info.cid_);
219     LOGI("newNetworkType:%{public}d", newNetworkType);
220 
221     if (!IsWifiNetworkType(newNetworkType)) {
222         LOGE("cid %{public}s networkType:%{public}d", info.cid_.c_str(), type_->second);
223         LOGI("OnDeviceOnline end");
224         return;
225     }
226 
227     auto cmd =
228         make_unique<DfsuCmd<NetworkAgentTemplate, const DeviceInfo>>(&NetworkAgentTemplate::ConnectDeviceAsync, info);
229     cmd->UpdateOption({.tryTimes_ = MAX_RETRY_COUNT});
230     it->second->Recv(move(cmd));
231 
232     LOGI("OnDeviceOnline end");
233 }
234 
OnDeviceOffline(const DistributedHardware::DmDeviceInfo & deviceInfo)235 void DeviceManagerAgent::OnDeviceOffline(const DistributedHardware::DmDeviceInfo &deviceInfo)
236 {
237     LOGI("OnDeviceOffline begin");
238     DeviceInfo info(deviceInfo);
239 
240     unique_lock<mutex> lock(mpToNetworksMutex_);
241     auto it = cidNetTypeRecord_.find(info.cid_);
242     if (it == cidNetTypeRecord_.end()) {
243         LOGE("cid %{public}s network is null!", info.cid_.c_str());
244         LOGI("OnDeviceOffline end");
245         return;
246     }
247 
248     auto type_ = cidNetworkType_.find(info.cid_);
249     if (type_ == cidNetworkType_.end()) {
250         LOGE("cid %{public}s network type is null!", info.cid_.c_str());
251         LOGI("OnDeviceOffline end");
252         return;
253     }
254 
255     auto cmd =
256         make_unique<DfsuCmd<NetworkAgentTemplate, const DeviceInfo>>(&NetworkAgentTemplate::DisconnectDevice, info);
257     it->second->Recv(move(cmd));
258     cidNetTypeRecord_.erase(info.cid_);
259     cidNetworkType_.erase(info.cid_);
260     LOGI("OnDeviceOffline end");
261 }
262 
OnDeviceP2POnline(const DistributedHardware::DmDeviceInfo & deviceInfo)263 int32_t DeviceManagerAgent::OnDeviceP2POnline(const DistributedHardware::DmDeviceInfo &deviceInfo)
264 {
265     LOGI("[OnDeviceP2POnline] networkId %{public}s, OnDeviceOnline begin", deviceInfo.networkId);
266     DeviceInfo info(deviceInfo);
267     LOGI("[OnDeviceP2POnline] networkId %{public}s, QueryRelatedGroups begin", deviceInfo.networkId);
268     QueryRelatedGroups(info.udid_, info.cid_);
269     LOGI("[OnDeviceP2POnline] networkId %{public}s, QueryRelatedGroups end", deviceInfo.networkId);
270     unique_lock<mutex> lock(mpToNetworksMutex_);
271     auto it = cidNetTypeRecord_.find(info.cid_);
272     if (it == cidNetTypeRecord_.end()) {
273         LOGE("[OnDeviceP2POnline] cid %{public}s network is null!", info.cid_.c_str());
274         return P2P_FAILED;
275     }
276     auto type_ = cidNetworkType_.find(info.cid_);
277     if (type_ == cidNetworkType_.end()) {
278         LOGE("[OnDeviceP2POnline] cid %{public}s network type is null!", info.cid_.c_str());
279         return P2P_FAILED;
280     }
281     openP2PSessionCount_++;
282     auto cmd = make_unique<DfsuCmd<NetworkAgentTemplate, const DeviceInfo>>(
283         &NetworkAgentTemplate::ConnectDeviceByP2PAsync, info);
284     cmd->UpdateOption({.tryTimes_ = MAX_RETRY_COUNT});
285     it->second->Recv(move(cmd));
286     LOGI("[OnDeviceP2POnline] networkId %{public}s, OnDeviceOnline end", deviceInfo.networkId);
287     return P2P_SUCCESS;
288 }
289 
OnDeviceP2POffline(const DistributedHardware::DmDeviceInfo & deviceInfo)290 int32_t DeviceManagerAgent::OnDeviceP2POffline(const DistributedHardware::DmDeviceInfo &deviceInfo)
291 {
292     LOGI("OnDeviceP2POffline begin");
293     DeviceInfo info(deviceInfo);
294 
295     unique_lock<mutex> lock(mpToNetworksMutex_);
296     openP2PSessionCount_--;
297     if (openP2PSessionCount_) {
298         return P2P_FAILED;
299     }
300     auto it = cidNetTypeRecord_.find(info.cid_);
301     if (it == cidNetTypeRecord_.end()) {
302         LOGE("cid %{public}s network is null!", info.cid_.c_str());
303         return P2P_FAILED;
304     }
305     auto type_ = cidNetworkType_.find(info.cid_);
306     if (type_ == cidNetworkType_.end()) {
307         LOGE("cid %{public}s network type is null!", info.cid_.c_str());
308         return P2P_FAILED;
309     }
310     auto cmd =
311         make_unique<DfsuCmd<NetworkAgentTemplate, const DeviceInfo>>(&NetworkAgentTemplate::DisconnectDevice, info);
312     it->second->Recv(move(cmd));
313     cidNetTypeRecord_.erase(info.cid_);
314     cidNetworkType_.erase(info.cid_);
315     LOGI("OnDeviceP2POffline end");
316     return P2P_SUCCESS;
317 }
318 
from_json(const nlohmann::json & jsonObject,GroupInfo & groupInfo)319 void from_json(const nlohmann::json &jsonObject, GroupInfo &groupInfo)
320 {
321     if (jsonObject.find(FIELD_GROUP_NAME) != jsonObject.end()) {
322         groupInfo.groupName = jsonObject.at(FIELD_GROUP_NAME).get<std::string>();
323     }
324 
325     if (jsonObject.find(FIELD_GROUP_ID) != jsonObject.end()) {
326         groupInfo.groupId = jsonObject.at(FIELD_GROUP_ID).get<std::string>();
327     }
328 
329     if (jsonObject.find(FIELD_GROUP_OWNER) != jsonObject.end()) {
330         groupInfo.groupOwner = jsonObject.at(FIELD_GROUP_OWNER).get<std::string>();
331     }
332 
333     if (jsonObject.find(FIELD_GROUP_TYPE) != jsonObject.end()) {
334         groupInfo.groupType = jsonObject.at(FIELD_GROUP_TYPE).get<int32_t>();
335     }
336 }
337 
QueryRelatedGroups(const std::string & udid,const std::string & networkId)338 void DeviceManagerAgent::QueryRelatedGroups(const std::string &udid, const std::string &networkId)
339 {
340     int ret = InitDeviceAuthService();
341     if (ret != 0) {
342         LOGE("InitDeviceAuthService failed, ret %{public}d", ret);
343         return;
344     }
345 
346     auto hichainDevGroupMgr_ = GetGmInstance();
347     if (hichainDevGroupMgr_ == nullptr) {
348         LOGE("failed to get hichain device group manager");
349         return;
350     }
351 
352     char *returnGroupVec = nullptr;
353     uint32_t groupNum = 0;
354     ret = hichainDevGroupMgr_->getRelatedGroups(ANY_OS_ACCOUNT, IDaemon::SERVICE_NAME.c_str(), udid.c_str(),
355                                                 &returnGroupVec, &groupNum);
356     if (ret != 0 || returnGroupVec == nullptr) {
357         LOGE("failed to get related groups, ret %{public}d", ret);
358         return;
359     }
360 
361     if (groupNum == 0) {
362         LOGE("failed to get related groups, groupNum is %{public}u", groupNum);
363         return;
364     }
365 
366     std::string groups = std::string(returnGroupVec);
367     nlohmann::json jsonObject = nlohmann::json::parse(groups); // transform from cjson to cppjson
368     if (jsonObject.is_discarded()) {
369         LOGE("returnGroupVec parse failed");
370         return;
371     }
372 
373     std::vector<GroupInfo> groupList;
374     groupList = jsonObject.get<std::vector<GroupInfo>>();
375     for (auto &a : groupList) {
376         LOGI("group info:[groupName] %{public}s, [groupId] %{public}s, [groupOwner] %{public}s,[groupType] %{public}d,",
377              a.groupName.c_str(), a.groupId.c_str(), a.groupOwner.c_str(), a.groupType);
378     }
379 
380     unique_lock<mutex> lock(mpToNetworksMutex_);
381     for (const auto &group : groupList) {
382         auto network = FindNetworkBaseTrustRelation(CheckIsAccountless(group));
383         if (network != nullptr) {
384             cidNetTypeRecord_.insert({ networkId, network });
385             cidNetworkType_.insert({ networkId, GetNetworkType(networkId) });
386         }
387     }
388 
389     return;
390 }
391 
CheckIsAccountless(const GroupInfo & group)392 bool DeviceManagerAgent::CheckIsAccountless(const GroupInfo &group)
393 {
394     // because of there no same_account, only for test, del later
395     LOGI("SAME_ACCOUNT_MARK val is %{public}d", system::GetBoolParameter(SAME_ACCOUNT_MARK, false));
396     if (system::GetBoolParameter(SAME_ACCOUNT_MARK, false) == true) { // isaccountless == false
397         LOGI("SAME_ACCOUNT_MARK val is true(same account)");
398         return false;
399     } else { // isaccountless == true
400         return true;
401     }
402 
403     if (group.groupType == PEER_TO_PEER_GROUP || group.groupType == ACROSS_ACCOUNT_AUTHORIZE_GROUP) {
404         return true;
405     }
406     return false;
407 }
408 
OnDeviceChanged(const DistributedHardware::DmDeviceInfo & deviceInfo)409 void DeviceManagerAgent::OnDeviceChanged(const DistributedHardware::DmDeviceInfo &deviceInfo)
410 {
411     LOGI("OnDeviceInfoChanged begin");
412     DeviceInfo info(deviceInfo);
413     unique_lock<mutex> lock(mpToNetworksMutex_);
414 
415     auto it = cidNetTypeRecord_.find(info.cid_);
416     if (it == cidNetTypeRecord_.end()) {
417         LOGE("cid %{public}s network is null!", info.cid_.c_str());
418         LOGI("OnDeviceInfoChanged end");
419         return;
420     }
421 
422     auto type_ = cidNetworkType_.find(info.cid_);
423     if (type_ == cidNetworkType_.end()) {
424         LOGE("cid %{public}s network type is null!", info.cid_.c_str());
425         LOGI("OnDeviceInfoChanged end");
426         return;
427     }
428 
429     int32_t oldNetworkType = type_->second;
430     int32_t newNetworkType = type_->second = deviceInfo.networkType;
431 
432     LOGI("oldNetworkType %{public}d, newNetworkType %{public}d", oldNetworkType, newNetworkType);
433 
434     if (IsWifiNetworkType(newNetworkType) && !IsWifiNetworkType(oldNetworkType)) {
435         LOGI("Wifi connect");
436         auto cmd = make_unique<DfsuCmd<NetworkAgentTemplate, const DeviceInfo>>(
437             &NetworkAgentTemplate::ConnectDeviceAsync, info);
438         cmd->UpdateOption({.tryTimes_ = MAX_RETRY_COUNT});
439         it->second->Recv(move(cmd));
440         LOGI("OnDeviceInfoChanged end");
441         return;
442     }
443 
444     if (!IsWifiNetworkType(newNetworkType) && IsWifiNetworkType(oldNetworkType)) {
445         LOGI("Wifi disconnect");
446         auto cmd = make_unique<DfsuCmd<NetworkAgentTemplate, const DeviceInfo>>
447             (&NetworkAgentTemplate::DisconnectDevice, info);
448         it->second->Recv(move(cmd));
449         LOGI("OnDeviceInfoChanged end");
450         return;
451     }
452 
453     LOGI("OnDeviceInfoChanged end");
454 }
455 
InitDeviceInfos()456 void DeviceManagerAgent::InitDeviceInfos()
457 {
458     string extra = "";
459     string pkgName = IDaemon::SERVICE_NAME;
460     vector<DistributedHardware::DmDeviceInfo> deviceInfoList;
461 
462     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
463     int errCode = deviceManager.GetTrustedDeviceList(pkgName, extra, deviceInfoList);
464     if (errCode) {
465         THROW_EXCEPTION(errCode, "Failed to get info of remote devices");
466     }
467 
468     for (const auto &deviceInfo : deviceInfoList) {
469         DeviceInfo info(deviceInfo);
470         QueryRelatedGroups(info.udid_, info.cid_);
471     }
472 }
473 
InitLocalNodeInfo()474 void DeviceManagerAgent::InitLocalNodeInfo()
475 {
476     NodeBasicInfo tmpNodeInfo;
477     int errCode = GetLocalNodeDeviceInfo(IDaemon::SERVICE_NAME.c_str(), &tmpNodeInfo);
478     if (errCode != 0) {
479         THROW_EXCEPTION(errCode, "Failed to get info of local devices");
480     }
481     localDeviceInfo_.SetCid(string(tmpNodeInfo.networkId));
482 }
483 
OnRemoteDied()484 void DeviceManagerAgent::OnRemoteDied()
485 {
486     LOGI("device manager service died");
487 }
488 
GetLocalDeviceInfo()489 DeviceInfo &DeviceManagerAgent::GetLocalDeviceInfo()
490 {
491     return localDeviceInfo_;
492 }
493 
GetRemoteDevicesInfo()494 vector<DeviceInfo> DeviceManagerAgent::GetRemoteDevicesInfo()
495 {
496     string extra = "";
497     string pkgName = IDaemon::SERVICE_NAME;
498     vector<DistributedHardware::DmDeviceInfo> deviceList;
499 
500     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
501     int errCode = deviceManager.GetTrustedDeviceList(pkgName, extra, deviceList);
502     if (errCode) {
503         THROW_EXCEPTION(errCode, "Failed to get info of remote devices");
504     }
505 
506     vector<DeviceInfo> res;
507     for (const auto &item : deviceList) {
508         res.push_back(DeviceInfo(item));
509     }
510     return res;
511 }
512 
RegisterToExternalDm()513 void DeviceManagerAgent::RegisterToExternalDm()
514 {
515     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
516     string pkgName = IDaemon::SERVICE_NAME;
517     int errCode = deviceManager.InitDeviceManager(pkgName, shared_from_this());
518     if (errCode != 0) {
519         THROW_EXCEPTION(errCode, "Failed to InitDeviceManager");
520     }
521     string extra = "";
522     errCode = deviceManager.RegisterDevStateCallback(pkgName, extra, shared_from_this());
523     if (errCode != 0) {
524         THROW_EXCEPTION(errCode, "Failed to RegisterDevStateCallback");
525     }
526     LOGI("RegisterToExternalDm Succeed");
527 }
528 
UnregisterFromExternalDm()529 void DeviceManagerAgent::UnregisterFromExternalDm()
530 {
531     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
532     string pkgName = IDaemon::SERVICE_NAME;
533     int errCode = deviceManager.UnRegisterDevStateCallback(pkgName);
534     if (errCode != 0) {
535         THROW_EXCEPTION(errCode, "Failed to UnRegisterDevStateCallback");
536     }
537     errCode = deviceManager.UnInitDeviceManager(pkgName);
538     if (errCode != 0) {
539         THROW_EXCEPTION(errCode, "Failed to UnInitDeviceManager");
540     }
541     LOGI("UnregisterFromExternalDm Succeed");
542 }
543 } // namespace DistributedFile
544 } // namespace Storage
545 } // namespace OHOS
546