• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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     auto smp = mp.lock();
82     if (!smp) {
83         stringstream ss("Failed to join group: Received empty mountpoint");
84         LOGE("%{public}s", ss.str().c_str());
85         throw runtime_error(ss.str());
86     }
87 
88     shared_ptr<SoftbusAgent> agent = nullptr;
89     {
90         unique_lock<mutex> lock(mpToNetworksMutex_);
91         agent = make_shared<SoftbusAgent>(mp);
92         auto [ignored, inserted] = mpToNetworks_.insert({ smp->GetID(), agent });
93         if (!inserted) {
94             stringstream ss;
95             ss << "Failed to join group: Mountpoint existed" << smp->ToString();
96             throw runtime_error(ss.str());
97         }
98     }
99     LOGI("smp id %{public}d, is account_less %{pubulic}d", smp->GetID(), agent->GetMountPoint()->isAccountLess());
100     agent->StartActor();
101 }
102 
QuitGroup(weak_ptr<MountPoint> mp)103 void DeviceManagerAgent::QuitGroup(weak_ptr<MountPoint> mp)
104 {
105     OfflineAllDevice();
106 
107     auto smp = mp.lock();
108     if (!smp) {
109         stringstream ss("Failed to quit group: Received empty mountpoint");
110         LOGE("%{public}s", ss.str().c_str());
111         throw runtime_error(ss.str());
112     }
113 
114     unique_lock<mutex> lock(mpToNetworksMutex_);
115     auto it = mpToNetworks_.find(smp->GetID());
116     if (it == mpToNetworks_.end()) {
117         stringstream ss;
118         ss << "Failed to quit group: Mountpoint didn't exist " << smp->ToString();
119         throw runtime_error(ss.str());
120     }
121 
122     it->second->StopActor();
123     mpToNetworks_.erase(smp->GetID());
124 }
125 
OfflineAllDevice()126 void DeviceManagerAgent::OfflineAllDevice()
127 {
128     unique_lock<mutex> lock(mpToNetworksMutex_);
129     for (auto [ignore, net] : cidNetTypeRecord_) {
130         auto cmd = make_unique<DfsuCmd<NetworkAgentTemplate>>(&NetworkAgentTemplate::DisconnectAllDevices);
131         net->Recv(move(cmd));
132     }
133 }
134 
ReconnectOnlineDevices()135 void DeviceManagerAgent::ReconnectOnlineDevices()
136 {
137     unique_lock<mutex> lock(mpToNetworksMutex_);
138     for (auto [ignore, net] : cidNetTypeRecord_) {
139         auto cmd = make_unique<DfsuCmd<NetworkAgentTemplate>>(&NetworkAgentTemplate::ConnectOnlineDevices);
140         cmd->UpdateOption({
141             .tryTimes_ = MAX_RETRY_COUNT,
142         });
143         net->Recv(move(cmd));
144     }
145 }
146 
FindNetworkBaseTrustRelation(bool isAccountless)147 std::shared_ptr<NetworkAgentTemplate> DeviceManagerAgent::FindNetworkBaseTrustRelation(bool isAccountless)
148 {
149     LOGI("enter: isAccountless %{public}d", isAccountless);
150     for (auto [ignore, net] : mpToNetworks_) {
151         if (net != nullptr) {
152             auto smp = net->GetMountPoint();
153             if (smp != nullptr && smp->isAccountLess() == isAccountless) {
154                 return net;
155             }
156         }
157     }
158     LOGE("not find this net in mpToNetworks, isAccountless %{public}d", isAccountless);
159     return nullptr;
160 }
161 
OnDeviceOnline(const DistributedHardware::DmDeviceInfo & deviceInfo)162 void DeviceManagerAgent::OnDeviceOnline(const DistributedHardware::DmDeviceInfo &deviceInfo)
163 {
164     LOGI("networkId %{public}s, OnDeviceOnline begin", deviceInfo.deviceId);
165 
166     // online first query this dev's trust info
167     DeviceInfo info(deviceInfo);
168     QueryRelatedGroups(info.udid_, info.cid_);
169 
170     // based on dev's trust info, choose corresponding network agent to obtain socket
171     unique_lock<mutex> lock(mpToNetworksMutex_);
172     auto networkAgent = cidNetTypeRecord_[info.cid_];
173     if (networkAgent == nullptr) {
174         LOGE("cid %{public}s network is null!", info.cid_.c_str());
175         return;
176     }
177     auto cmd =
178         make_unique<DfsuCmd<NetworkAgentTemplate, const DeviceInfo>>(&NetworkAgentTemplate::ConnectDeviceAsync, info);
179     cmd->UpdateOption({.tryTimes_ = MAX_RETRY_COUNT});
180     networkAgent->Recv(move(cmd));
181 
182     LOGI("OnDeviceOnline end");
183 }
184 
OnDeviceOffline(const DistributedHardware::DmDeviceInfo & deviceInfo)185 void DeviceManagerAgent::OnDeviceOffline(const DistributedHardware::DmDeviceInfo &deviceInfo)
186 {
187     LOGI("OnDeviceOffline begin");
188     DeviceInfo info(deviceInfo);
189 
190     unique_lock<mutex> lock(mpToNetworksMutex_);
191     auto networkAgent = cidNetTypeRecord_[info.cid_];
192     if (networkAgent == nullptr) {
193         LOGE("cid %{public}s network is null!", info.cid_.c_str());
194         return;
195     }
196 
197     auto cmd =
198         make_unique<DfsuCmd<NetworkAgentTemplate, const DeviceInfo>>(&NetworkAgentTemplate::DisconnectDevice, info);
199     networkAgent->Recv(move(cmd));
200     cidNetTypeRecord_.erase(info.cid_);
201     LOGI("OnDeviceOffline end");
202 }
203 
from_json(const nlohmann::json & jsonObject,GroupInfo & groupInfo)204 void from_json(const nlohmann::json &jsonObject, GroupInfo &groupInfo)
205 {
206     if (jsonObject.find(FIELD_GROUP_NAME) != jsonObject.end()) {
207         groupInfo.groupName = jsonObject.at(FIELD_GROUP_NAME).get<std::string>();
208     }
209 
210     if (jsonObject.find(FIELD_GROUP_ID) != jsonObject.end()) {
211         groupInfo.groupId = jsonObject.at(FIELD_GROUP_ID).get<std::string>();
212     }
213 
214     if (jsonObject.find(FIELD_GROUP_OWNER) != jsonObject.end()) {
215         groupInfo.groupOwner = jsonObject.at(FIELD_GROUP_OWNER).get<std::string>();
216     }
217 
218     if (jsonObject.find(FIELD_GROUP_TYPE) != jsonObject.end()) {
219         groupInfo.groupType = jsonObject.at(FIELD_GROUP_TYPE).get<int32_t>();
220     }
221 }
222 
QueryRelatedGroups(const std::string & udid,const std::string & networkId)223 void DeviceManagerAgent::QueryRelatedGroups(const std::string &udid, const std::string &networkId)
224 {
225     int ret = InitDeviceAuthService();
226     if (ret != 0) {
227         LOGE("InitDeviceAuthService failed, ret %{public}d", ret);
228         return;
229     }
230 
231     auto hichainDevGroupMgr_ = GetGmInstance();
232     if (hichainDevGroupMgr_ == nullptr) {
233         LOGE("failed to get hichain device group manager");
234         return;
235     }
236 
237     char *returnGroupVec = nullptr;
238     uint32_t groupNum = 0;
239     ret = hichainDevGroupMgr_->getRelatedGroups(ANY_OS_ACCOUNT, IDaemon::SERVICE_NAME.c_str(), udid.c_str(),
240         &returnGroupVec, &groupNum);
241     if (ret != 0 || returnGroupVec == nullptr) {
242         LOGE("failed to get related groups, ret %{public}d", ret);
243         return;
244     }
245 
246     if (groupNum == 0) {
247         LOGE("failed to get related groups, groupNum is %{public}u", groupNum);
248         return;
249     }
250 
251     std::string groups = std::string(returnGroupVec);
252     nlohmann::json jsonObject = nlohmann::json::parse(groups); // transform from cjson to cppjson
253     if (jsonObject.is_discarded()) {
254         LOGE("returnGroupVec parse failed");
255         return;
256     }
257 
258     std::vector<GroupInfo> groupList;
259     groupList = jsonObject.get<std::vector<GroupInfo>>();
260     for (auto &a : groupList) {
261         LOGI("group info:[groupName] %{public}s, [groupId] %{public}s, [groupOwner] %{public}s,[groupType] %{public}d,",
262              a.groupName.c_str(), a.groupId.c_str(), a.groupOwner.c_str(), a.groupType);
263     }
264 
265     unique_lock<mutex> lock(mpToNetworksMutex_);
266     for (const auto &group : groupList) {
267         if (CheckIsAccountless(group)) {
268             cidNetTypeRecord_.insert({ networkId, FindNetworkBaseTrustRelation(true) });
269         } else {
270             cidNetTypeRecord_.insert({ networkId, FindNetworkBaseTrustRelation(false) });
271         }
272     }
273 
274     return;
275 }
276 
CheckIsAccountless(const GroupInfo & group)277 bool DeviceManagerAgent::CheckIsAccountless(const GroupInfo &group)
278 {
279     // because of there no same_account, only for test, del later
280     LOGI("SAME_ACCOUNT_MARK val is %{public}d", system::GetBoolParameter(SAME_ACCOUNT_MARK, false));
281     if (system::GetBoolParameter(SAME_ACCOUNT_MARK, false) == true) { // isaccountless == false
282         LOGI("SAME_ACCOUNT_MARK val is true(same account)");
283         return false;
284     } else { // isaccountless == true
285         return true;
286     }
287 
288     if (group.groupType == PEER_TO_PEER_GROUP || group.groupType == ACROSS_ACCOUNT_AUTHORIZE_GROUP) {
289         return true;
290     }
291     return false;
292 }
293 
OnDeviceChanged(const DistributedHardware::DmDeviceInfo & deviceInfo)294 void DeviceManagerAgent::OnDeviceChanged(const DistributedHardware::DmDeviceInfo &deviceInfo)
295 {
296     (void)deviceInfo;
297     LOGI("OnDeviceInfoChanged");
298 }
299 
InitLocalNodeInfo()300 void DeviceManagerAgent::InitLocalNodeInfo()
301 {
302     NodeBasicInfo tmpNodeInfo;
303     int errCode = GetLocalNodeDeviceInfo(IDaemon::SERVICE_NAME.c_str(), &tmpNodeInfo);
304     if (errCode != 0) {
305         ThrowException(errCode, "Failed to get info of local devices");
306     }
307     localDeviceInfo_.SetCid(string(tmpNodeInfo.networkId));
308 }
309 
OnRemoteDied()310 void DeviceManagerAgent::OnRemoteDied()
311 {
312     LOGI("device manager service died");
313 }
314 
GetLocalDeviceInfo()315 DeviceInfo &DeviceManagerAgent::GetLocalDeviceInfo()
316 {
317     return localDeviceInfo_;
318 }
319 
GetRemoteDevicesInfo()320 vector<DeviceInfo> DeviceManagerAgent::GetRemoteDevicesInfo()
321 {
322     string extra = "";
323     string pkgName = IDaemon::SERVICE_NAME;
324     vector<DistributedHardware::DmDeviceInfo> deviceList;
325 
326     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
327     int errCode = deviceManager.GetTrustedDeviceList(pkgName, extra, deviceList);
328     if (errCode) {
329         ThrowException(errCode, "Failed to get info of remote devices");
330     }
331 
332     vector<DeviceInfo> res;
333     for (const auto &item : deviceList) {
334         res.push_back(DeviceInfo(item));
335     }
336     return res;
337 }
338 
RegisterToExternalDm()339 void DeviceManagerAgent::RegisterToExternalDm()
340 {
341     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
342     string pkgName = IDaemon::SERVICE_NAME;
343     int errCode = deviceManager.InitDeviceManager(pkgName, shared_from_this());
344     if (errCode != 0) {
345         ThrowException(errCode, "Failed to InitDeviceManager");
346     }
347     string extra = "";
348     errCode = deviceManager.RegisterDevStateCallback(pkgName, extra, shared_from_this());
349     if (errCode != 0) {
350         ThrowException(errCode, "Failed to RegisterDevStateCallback");
351     }
352     LOGI("RegisterToExternalDm Succeed");
353 }
354 
UnregisterFromExternalDm()355 void DeviceManagerAgent::UnregisterFromExternalDm()
356 {
357     auto &deviceManager = DistributedHardware::DeviceManager::GetInstance();
358     string pkgName = IDaemon::SERVICE_NAME;
359     int errCode = deviceManager.UnRegisterDevStateCallback(pkgName);
360     if (errCode != 0) {
361         ThrowException(errCode, "Failed to UnRegisterDevStateCallback");
362     }
363     errCode = deviceManager.UnInitDeviceManager(pkgName);
364     if (errCode != 0) {
365         ThrowException(errCode, "Failed to UnInitDeviceManager");
366     }
367     LOGI("UnregisterFromExternalDm Succeed");
368 }
369 } // namespace DistributedFile
370 } // namespace Storage
371 } // namespace OHOS
372