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