1 /*
2 * Copyright (c) 2024 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
20 #include "anonymous_string.h"
21 #include "capability_info_manager.h"
22 #include "component_manager.h"
23 #include "dh_context.h"
24 #include "dh_transport_obj.h"
25 #include "dh_utils_tool.h"
26 #include "distributed_hardware_errno.h"
27 #include "distributed_hardware_log.h"
28 #include "local_capability_info_manager.h"
29 #include "task_executor.h"
30
31 namespace OHOS {
32 namespace DistributedHardware {
33 #undef DH_LOG_TAG
34 #define DH_LOG_TAG "DHCommTool"
35
DHCommTool()36 DHCommTool::DHCommTool() : dhTransportPtr_(nullptr)
37 {
38 DHLOGI("Ctor DHCommTool");
39 }
40
Init()41 void DHCommTool::Init()
42 {
43 DHLOGI("Init DHCommTool");
44 dhTransportPtr_ = std::make_shared<DHTransport>(shared_from_this());
45 std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create(true);
46 eventHandler_ = std::make_shared<DHCommTool::DHCommToolEventHandler>(runner, shared_from_this());
47 dhTransportPtr_->Init();
48 }
49
UnInit()50 void DHCommTool::UnInit()
51 {
52 DHLOGI("UnInit DHCommTool");
53 if (dhTransportPtr_ == nullptr) {
54 DHLOGI("dhTransportPtr_ is null");
55 return;
56 }
57 dhTransportPtr_->UnInit();
58 }
59
GetInstance()60 std::shared_ptr<DHCommTool> DHCommTool::GetInstance()
61 {
62 static std::shared_ptr<DHCommTool> instance = std::make_shared<DHCommTool>();
63 return instance;
64 }
65
TriggerReqFullDHCaps(const std::string & remoteNetworkId)66 void DHCommTool::TriggerReqFullDHCaps(const std::string &remoteNetworkId)
67 {
68 DHLOGI("TriggerReqFullDHCaps, remote networkId: %{public}s", GetAnonyString(remoteNetworkId).c_str());
69 if (remoteNetworkId.empty() || dhTransportPtr_ == nullptr) {
70 DHLOGE("remoteNetworkId or transport is null");
71 return;
72 }
73 std::string localNetworkId = GetLocalNetworkId();
74 if (localNetworkId.empty()) {
75 DHLOGE("Get local network id error");
76 return;
77 }
78 if (dhTransportPtr_->StartSocket(remoteNetworkId) != DH_FWK_SUCCESS) {
79 DHLOGE("Start socket error");
80 return;
81 }
82 CommMsg commMsg(DH_COMM_REQ_FULL_CAPS, localNetworkId);
83 std::string payload = GetCommMsgString(commMsg);
84
85 int32_t ret = dhTransportPtr_->Send(remoteNetworkId, payload);
86 if (ret != DH_FWK_SUCCESS) {
87 DHLOGE("Trigger req remote full attrs error");
88 return;
89 }
90 DHLOGI("Trigger req remote full attrs success.");
91 }
92
GetAndSendLocalFullCaps(const std::string & reqNetworkId)93 void DHCommTool::GetAndSendLocalFullCaps(const std::string &reqNetworkId)
94 {
95 DHLOGI("GetAndSendLocalFullCaps, reqNetworkId: %{public}s", GetAnonyString(reqNetworkId).c_str());
96 if (dhTransportPtr_ == nullptr) {
97 DHLOGE("transport is null");
98 return;
99 }
100 std::string localDeviceId = DHContext::GetInstance().GetDeviceInfo().deviceId;
101 std::vector<std::shared_ptr<CapabilityInfo>> resInfos;
102 CapabilityInfoManager::GetInstance()->GetCapabilitiesByDeviceId(localDeviceId, resInfos);
103 FullCapsRsp capsRsp;
104 capsRsp.networkId = GetLocalNetworkId();
105 capsRsp.caps = resInfos;
106 cJSON *root = cJSON_CreateObject();
107 if (root == nullptr) {
108 DHLOGE("Create cJSON object failed.");
109 return;
110 }
111 ToJson(root, capsRsp);
112 char *msg = cJSON_PrintUnformatted(root);
113 if (msg == nullptr) {
114 cJSON_Delete(root);
115 return;
116 }
117 std::string fullCapsMsg(msg);
118 cJSON_free(msg);
119 cJSON_Delete(root);
120
121 CommMsg commMsg(DH_COMM_RSP_FULL_CAPS, fullCapsMsg);
122 std::string payload = GetCommMsgString(commMsg);
123
124 int32_t ret = dhTransportPtr_->Send(reqNetworkId, payload);
125 if (ret != DH_FWK_SUCCESS) {
126 DHLOGE("Send back Caps failed, ret: %{public}d", ret);
127 return;
128 }
129 DHLOGI("Send back Caps success");
130 }
131
ParseAndSaveRemoteDHCaps(const std::string & remoteCaps)132 FullCapsRsp DHCommTool::ParseAndSaveRemoteDHCaps(const std::string &remoteCaps)
133 {
134 FullCapsRsp capsRsp;
135 DHLOGI("ParseAndSaveRemoteDHCaps enter");
136 cJSON *root = cJSON_Parse(remoteCaps.c_str());
137 if (root == NULL) {
138 DHLOGE("Parse remote Caps failed");
139 return capsRsp;
140 }
141
142 FromJson(root, capsRsp);
143 cJSON_Delete(root);
144 int32_t ret = LocalCapabilityInfoManager::GetInstance()->AddCapability(capsRsp.caps);
145 if (ret != DH_FWK_SUCCESS) {
146 DHLOGE("Save local capabilities error, ret: %{public}d", ret);
147 return capsRsp;
148 }
149 DHLOGE("Save local capabilities success");
150 return capsRsp;
151 }
152
DHCommToolEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> runner,std::shared_ptr<DHCommTool> dhCommToolPtr)153 DHCommTool::DHCommToolEventHandler::DHCommToolEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> runner,
154 std::shared_ptr<DHCommTool> dhCommToolPtr) : AppExecFwk::EventHandler(runner), dhCommToolWPtr_(dhCommToolPtr)
155 {
156 DHLOGI("Ctor DHCommToolEventHandler");
157 }
158
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)159 void DHCommTool::DHCommToolEventHandler::ProcessEvent(
160 const AppExecFwk::InnerEvent::Pointer &event)
161 {
162 uint32_t eventId = event->GetInnerEventId();
163 std::shared_ptr<CommMsg> commMsg = event->GetSharedObject<CommMsg>();
164 if (commMsg == nullptr) {
165 DHLOGE("ProcessEvent commMsg is null");
166 return;
167 }
168 if (dhCommToolWPtr_.expired()) {
169 DHLOGE("dhCommToolWPtr_ is expired");
170 return;
171 }
172 std::shared_ptr<DHCommTool> dhCommToolPtr = dhCommToolWPtr_.lock();
173 if (dhCommToolPtr == nullptr) {
174 DHLOGE("dhCommToolPtr is null");
175 return;
176 }
177 switch (eventId) {
178 case DH_COMM_REQ_FULL_CAPS: {
179 dhCommToolPtr->GetAndSendLocalFullCaps(commMsg->msg);
180 break;
181 }
182 case DH_COMM_RSP_FULL_CAPS: {
183 // parse remote rsp full attrs and save to local db
184 FullCapsRsp capsRsp = dhCommToolPtr->ParseAndSaveRemoteDHCaps(commMsg->msg);
185 DHLOGI("Receive full remote capabilities, remote networkid: %{public}s, caps size: %{public}" PRIu32,
186 GetAnonyString(capsRsp.networkId).c_str(), static_cast<uint32_t>(capsRsp.caps.size()));
187 ProcessFullCapsRsp(capsRsp, dhCommToolPtr);
188 break;
189 }
190 default:
191 DHLOGE("event is undefined, id is %{public}d", eventId);
192 break;
193 }
194 }
195
ProcessFullCapsRsp(const FullCapsRsp & capsRsp,const std::shared_ptr<DHCommTool> dhCommToolPtr)196 void DHCommTool::DHCommToolEventHandler::ProcessFullCapsRsp(const FullCapsRsp &capsRsp,
197 const std::shared_ptr<DHCommTool> dhCommToolPtr)
198 {
199 if (capsRsp.networkId.empty() || capsRsp.caps.empty()) {
200 DHLOGE("Receive remote caps info invalid!");
201 return;
202 }
203 // after receive rsp, close dsoftbus channel
204 DHLOGI("we receive full remote capabilities, close channel, remote networkId: %{public}s",
205 GetAnonyString(capsRsp.networkId).c_str());
206 dhCommToolPtr->GetDHTransportPtr()->StopSocket(capsRsp.networkId);
207
208 // trigger register dh by full attrs
209 std::string uuid = DHContext::GetInstance().GetUUIDByNetworkId(capsRsp.networkId);
210 if (uuid.empty()) {
211 DHLOGE("Can not find remote device uuid by networkid: %{public}s", GetAnonyString(capsRsp.networkId).c_str());
212 return;
213 }
214
215 for (auto const &cap : capsRsp.caps) {
216 BusinessState curState = ComponentManager::GetInstance().QueryBusinessState(capsRsp.networkId, cap->GetDHId());
217 DHLOGI("DH state: %{public}" PRIu32 ", networkId: %{public}s, dhId: %{public}s",
218 (uint32_t)curState, GetAnonyString(capsRsp.networkId).c_str(), GetAnonyString(cap->GetDHId()).c_str());
219 TaskParam taskParam = {
220 .networkId = capsRsp.networkId,
221 .uuid = uuid,
222 .dhId = cap->GetDHId(),
223 .dhType = cap->GetDHType()
224 };
225 if (curState != BusinessState::RUNNING && curState != BusinessState::PAUSING) {
226 DHLOGI("The dh not busy, refresh it");
227 auto task = TaskFactory::GetInstance().CreateTask(TaskType::ENABLE, taskParam, nullptr);
228 TaskExecutor::GetInstance().PushTask(task);
229 } else {
230 DHLOGI("The dh busy, save and refresh after idle");
231 ComponentManager::GetInstance().SaveNeedRefreshTask(taskParam);
232 }
233 }
234 }
235
GetEventHandler()236 std::shared_ptr<DHCommTool::DHCommToolEventHandler> DHCommTool::GetEventHandler()
237 {
238 return this->eventHandler_;
239 }
240
GetDHTransportPtr()241 const std::shared_ptr<DHTransport> DHCommTool::GetDHTransportPtr()
242 {
243 return this->dhTransportPtr_;
244 }
245
246 } // DistributedHardware
247 } // OHOS