• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 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 "dh_comm_tool.h"
17 
18 #include "cJSON.h"
19 #include "device_manager.h"
20 #include "ipc_skeleton.h"
21 #include "ohos_account_kits.h"
22 #include "os_account_manager.h"
23 #include "token_setproc.h"
24 
25 #include "anonymous_string.h"
26 #include "capability_info_manager.h"
27 #include "component_manager.h"
28 #include "dh_context.h"
29 #include "dh_transport_obj.h"
30 #include "dh_utils_tool.h"
31 #include "distributed_hardware_errno.h"
32 #include "distributed_hardware_log.h"
33 #include "local_capability_info_manager.h"
34 #include "task_executor.h"
35 
36 namespace OHOS {
37 namespace DistributedHardware {
38 #undef DH_LOG_TAG
39 #define DH_LOG_TAG "DHCommTool"
40 
41 // request remote dh send back full dh capabilities
42 constexpr int32_t DH_COMM_REQ_FULL_CAPS = 1;
43 // send back full dh attributes to the requester
44 constexpr int32_t DH_COMM_RSP_FULL_CAPS = 2;
45 
DHCommTool()46 DHCommTool::DHCommTool() : dhTransportPtr_(nullptr)
47 {
48     DHLOGI("Ctor DHCommTool");
49 }
50 
Init()51 void DHCommTool::Init()
52 {
53     DHLOGI("Init DHCommTool");
54     dhTransportPtr_ = std::make_shared<DHTransport>(shared_from_this());
55     std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create(true);
56     eventHandler_ = std::make_shared<DHCommTool::DHCommToolEventHandler>(runner, shared_from_this());
57     dhTransportPtr_->Init();
58 }
59 
UnInit()60 void DHCommTool::UnInit()
61 {
62     DHLOGI("UnInit DHCommTool");
63     if (dhTransportPtr_ == nullptr) {
64         DHLOGI("dhTransportPtr_ is null");
65         return;
66     }
67     dhTransportPtr_->UnInit();
68 }
69 
GetInstance()70 std::shared_ptr<DHCommTool> DHCommTool::GetInstance()
71 {
72     static std::shared_ptr<DHCommTool> instance = std::make_shared<DHCommTool>();
73     return instance;
74 }
75 
CheckCallerAclRight(const std::string & localNetworkId,const std::string & remoteNetworkId)76 bool DHCommTool::CheckCallerAclRight(const std::string &localNetworkId, const std::string &remoteNetworkId)
77 {
78     if (!GetOsAccountInfo()) {
79         DHLOGE("GetOsAccountInfo failed.");
80         return false;
81     }
82     tokenId_ = IPCSkeleton::GetCallingTokenID();
83     DmAccessCaller dmSrcCaller = {
84         .accountId = accountId_,
85         .pkgName = DH_FWK_PKG_NAME,
86         .networkId = localNetworkId,
87         .userId = userId_,
88         .tokenId = tokenId_,
89     };
90     DmAccessCallee dmDstCallee = {
91         .networkId = remoteNetworkId,
92     };
93     DHLOGI("CheckAclRight dmSrcCaller localNetworkId: %{public}s, accountId: %{public}s, remoteNetworkId: %{public}s",
94         GetAnonyString(localNetworkId).c_str(), GetAnonyString(accountId_).c_str(),
95         GetAnonyString(remoteNetworkId).c_str());
96     if (!DeviceManager::GetInstance().CheckSrcAccessControl(dmSrcCaller, dmDstCallee)) {
97         DHLOGE("Caller ACL check failed.");
98         return false;
99     }
100     return true;
101 }
102 
GetOsAccountInfo()103 bool DHCommTool::GetOsAccountInfo()
104 {
105     DHLOGI("GetOsAccountInfo start.");
106 #ifdef OS_ACCOUNT_PART
107     std::vector<int32_t> ids;
108     int32_t ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
109     if (ret != DH_FWK_SUCCESS || ids.empty()) {
110         DHLOGE("Get userId from active os accountIds fail, ret: %{public}d", ret);
111         return false;
112     }
113     userId_ = ids[0];
114 
115     AccountSA::OhosAccountInfo osAccountInfo;
116     ret = AccountSA::OhosAccountKits::GetInstance().GetOhosAccountInfo(osAccountInfo);
117     if (ret != DH_FWK_SUCCESS) {
118         DHLOGE("Get accountId from ohos account info fail, ret: %{public}d", ret);
119         return false;
120     }
121     accountId_ = osAccountInfo.uid_;
122 #endif
123     return true;
124 }
125 
TriggerReqFullDHCaps(const std::string & remoteNetworkId)126 void DHCommTool::TriggerReqFullDHCaps(const std::string &remoteNetworkId)
127 {
128     DHLOGI("TriggerReqFullDHCaps, remote networkId: %{public}s", GetAnonyString(remoteNetworkId).c_str());
129     if (remoteNetworkId.empty() || dhTransportPtr_ == nullptr) {
130         DHLOGE("remoteNetworkId or transport is null");
131         return;
132     }
133     std::string localNetworkId = GetLocalNetworkId();
134     if (localNetworkId.empty()) {
135         DHLOGE("Get local network id error");
136         return;
137     }
138     if (!CheckCallerAclRight(localNetworkId, remoteNetworkId)) {
139         DHLOGE("ACL check failed.");
140         return;
141     }
142     if (dhTransportPtr_->StartSocket(remoteNetworkId) != DH_FWK_SUCCESS) {
143         DHLOGE("Start socket error");
144         return;
145     }
146     CommMsg commMsg(DH_COMM_REQ_FULL_CAPS, userId_, tokenId_, localNetworkId, accountId_);
147     std::string payload = GetCommMsgString(commMsg);
148 
149     int32_t ret = dhTransportPtr_->Send(remoteNetworkId, payload);
150     if (ret != DH_FWK_SUCCESS) {
151         DHLOGE("Trigger req remote full attrs error");
152         return;
153     }
154     DHLOGI("Trigger req remote full attrs success.");
155 }
156 
GetAndSendLocalFullCaps(const std::string & reqNetworkId)157 void DHCommTool::GetAndSendLocalFullCaps(const std::string &reqNetworkId)
158 {
159     DHLOGI("GetAndSendLocalFullCaps, reqNetworkId: %{public}s", GetAnonyString(reqNetworkId).c_str());
160     if (dhTransportPtr_ == nullptr) {
161         DHLOGE("transport is null");
162         return;
163     }
164     std::string localDeviceId = DHContext::GetInstance().GetDeviceInfo().deviceId;
165     std::vector<std::shared_ptr<CapabilityInfo>> resInfos;
166     CapabilityInfoManager::GetInstance()->GetCapabilitiesByDeviceId(localDeviceId, resInfos);
167     FullCapsRsp capsRsp;
168     capsRsp.networkId = GetLocalNetworkId();
169     capsRsp.caps = resInfos;
170     cJSON *root = cJSON_CreateObject();
171     if (root == nullptr) {
172         DHLOGE("Create cJSON object failed.");
173         return;
174     }
175     ToJson(root, capsRsp);
176     char *msg = cJSON_PrintUnformatted(root);
177     if (msg == nullptr) {
178         cJSON_Delete(root);
179         return;
180     }
181     std::string fullCapsMsg(msg);
182     cJSON_free(msg);
183     cJSON_Delete(root);
184 
185     CommMsg commMsg;
186     commMsg.code = DH_COMM_RSP_FULL_CAPS;
187     commMsg.msg = fullCapsMsg;
188     std::string payload = GetCommMsgString(commMsg);
189 
190     int32_t ret = dhTransportPtr_->Send(reqNetworkId, payload);
191     if (ret != DH_FWK_SUCCESS) {
192         DHLOGE("Send back Caps failed, ret: %{public}d", ret);
193         return;
194     }
195     DHLOGI("Send back Caps success");
196 }
197 
ParseAndSaveRemoteDHCaps(const std::string & remoteCaps)198 FullCapsRsp DHCommTool::ParseAndSaveRemoteDHCaps(const std::string &remoteCaps)
199 {
200     FullCapsRsp capsRsp;
201     DHLOGI("ParseAndSaveRemoteDHCaps enter");
202     cJSON *root = cJSON_Parse(remoteCaps.c_str());
203     if (root == NULL) {
204         DHLOGE("Parse remote Caps failed");
205         return capsRsp;
206     }
207 
208     FromJson(root, capsRsp);
209     cJSON_Delete(root);
210     int32_t ret = LocalCapabilityInfoManager::GetInstance()->AddCapability(capsRsp.caps);
211     if (ret != DH_FWK_SUCCESS) {
212         DHLOGE("Save local capabilities error, ret: %{public}d", ret);
213         return capsRsp;
214     }
215     DHLOGE("Save local capabilities success");
216     return capsRsp;
217 }
218 
DHCommToolEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> runner,std::shared_ptr<DHCommTool> dhCommToolPtr)219 DHCommTool::DHCommToolEventHandler::DHCommToolEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> runner,
220     std::shared_ptr<DHCommTool> dhCommToolPtr) : AppExecFwk::EventHandler(runner), dhCommToolWPtr_(dhCommToolPtr)
221 {
222     DHLOGI("Ctor DHCommToolEventHandler");
223 }
224 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)225 void DHCommTool::DHCommToolEventHandler::ProcessEvent(
226     const AppExecFwk::InnerEvent::Pointer &event)
227 {
228     if (event == nullptr) {
229         DHLOGE("event is null.");
230         return;
231     }
232     uint32_t eventId = event->GetInnerEventId();
233     std::shared_ptr<CommMsg> commMsg = event->GetSharedObject<CommMsg>();
234     if (commMsg == nullptr) {
235         DHLOGE("ProcessEvent commMsg is null");
236         return;
237     }
238     if (dhCommToolWPtr_.expired()) {
239         DHLOGE("dhCommToolWPtr_ is expired");
240         return;
241     }
242     std::shared_ptr<DHCommTool> dhCommToolPtr = dhCommToolWPtr_.lock();
243     if (dhCommToolPtr == nullptr) {
244         DHLOGE("dhCommToolPtr is null");
245         return;
246     }
247     switch (eventId) {
248         case DH_COMM_REQ_FULL_CAPS: {
249             dhCommToolPtr->GetAndSendLocalFullCaps(commMsg->msg);
250             break;
251         }
252         case DH_COMM_RSP_FULL_CAPS: {
253             // parse remote rsp full attrs and save to local db
254             FullCapsRsp capsRsp = dhCommToolPtr->ParseAndSaveRemoteDHCaps(commMsg->msg);
255             DHLOGI("Receive full remote capabilities, remote networkid: %{public}s, caps size: %{public}" PRIu32,
256                 GetAnonyString(capsRsp.networkId).c_str(), static_cast<uint32_t>(capsRsp.caps.size()));
257             ProcessFullCapsRsp(capsRsp, dhCommToolPtr);
258             break;
259         }
260         default:
261             DHLOGE("event is undefined, id is %{public}d", eventId);
262             break;
263     }
264 }
265 
ProcessFullCapsRsp(const FullCapsRsp & capsRsp,const std::shared_ptr<DHCommTool> dhCommToolPtr)266 void DHCommTool::DHCommToolEventHandler::ProcessFullCapsRsp(const FullCapsRsp &capsRsp,
267     const std::shared_ptr<DHCommTool> dhCommToolPtr)
268 {
269     if (capsRsp.networkId.empty() || capsRsp.caps.empty()) {
270         DHLOGE("Receive remote caps info invalid!");
271         return;
272     }
273     if (dhCommToolPtr == nullptr) {
274         DHLOGE("dhCommToolPtr is null");
275         return;
276     }
277     if (dhCommToolPtr->GetDHTransportPtr() == nullptr) {
278         DHLOGE("Can not get Transport ptr");
279         return;
280     }
281     // after receive rsp, close dsoftbus channel
282     DHLOGI("we receive full remote capabilities, close channel, remote networkId: %{public}s",
283         GetAnonyString(capsRsp.networkId).c_str());
284     dhCommToolPtr->GetDHTransportPtr()->StopSocket(capsRsp.networkId);
285 
286     // trigger register dh by full attrs
287     std::string uuid = DHContext::GetInstance().GetUUIDByNetworkId(capsRsp.networkId);
288     if (uuid.empty()) {
289         DHLOGE("Can not find remote device uuid by networkid: %{public}s", GetAnonyString(capsRsp.networkId).c_str());
290         return;
291     }
292 
293     for (auto const &cap : capsRsp.caps) {
294         if (cap == nullptr) {
295             continue;
296         }
297         BusinessState curState = ComponentManager::GetInstance().QueryBusinessState(capsRsp.networkId, cap->GetDHId());
298         DHLOGI("DH state: %{public}" PRIu32 ", networkId: %{public}s, dhId: %{public}s",
299             (uint32_t)curState, GetAnonyString(capsRsp.networkId).c_str(), GetAnonyString(cap->GetDHId()).c_str());
300         TaskParam taskParam = {
301             .networkId = capsRsp.networkId,
302             .uuid = uuid,
303             .dhId = cap->GetDHId(),
304             .dhType = cap->GetDHType()
305         };
306         if (curState != BusinessState::RUNNING && curState != BusinessState::PAUSING) {
307             DHLOGI("The dh not busy, refresh it");
308             auto task = TaskFactory::GetInstance().CreateTask(TaskType::ENABLE, taskParam, nullptr);
309             TaskExecutor::GetInstance().PushTask(task);
310         } else {
311             DHLOGI("The dh busy, save and refresh after idle");
312             ComponentManager::GetInstance().SaveNeedRefreshTask(taskParam);
313         }
314     }
315 }
316 
GetEventHandler()317 std::shared_ptr<DHCommTool::DHCommToolEventHandler> DHCommTool::GetEventHandler()
318 {
319     return this->eventHandler_;
320 }
321 
GetDHTransportPtr()322 const std::shared_ptr<DHTransport> DHCommTool::GetDHTransportPtr()
323 {
324     return this->dhTransportPtr_;
325 }
326 
327 } // DistributedHardware
328 } // OHOS