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 "dm_comm_tool.h"
17 #include "device_manager_service.h"
18 #include "dm_anonymous.h"
19 #include "dm_error_type.h"
20 #include "dm_transport.h"
21 #include "dm_transport_msg.h"
22 #include "dm_log.h"
23 #include "dm_softbus_cache.h"
24 #include "multiple_user_connector.h"
25 #include "parameter.h"
26
27 namespace OHOS {
28 namespace DistributedHardware {
29 // send local foreground userids msg
30 constexpr int32_t DM_COMM_SEND_LOCAL_USERIDS = 1;
31 // if receive remote device send foreground userids, response local foreground uerids
32 // This msg no need response
33 constexpr int32_t DM_COMM_RSP_LOCAL_USERIDS = 2;
34 constexpr int32_t DM_COMM_SEND_USER_STOP = 3;
35 constexpr int32_t DM_COMM_RSP_USER_STOP = 4;
36 constexpr int32_t DM_COMM_ACCOUNT_LOGOUT = 5;
37
38 const char* const USER_STOP_MSG_KEY = "stopUserId";
39
DMCommTool()40 DMCommTool::DMCommTool() : dmTransportPtr_(nullptr)
41 {
42 LOGI("Ctor DMCommTool");
43 }
44
Init()45 void DMCommTool::Init()
46 {
47 LOGI("Init DMCommTool");
48 dmTransportPtr_ = std::make_shared<DMTransport>(shared_from_this());
49 std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create(true);
50 eventHandler_ = std::make_shared<DMCommTool::DMCommToolEventHandler>(runner, shared_from_this());
51 dmTransportPtr_->Init();
52 }
53
UnInit()54 void DMCommTool::UnInit()
55 {
56 LOGI("UnInit DMCommTool");
57 if (dmTransportPtr_ == nullptr) {
58 LOGI("dmTransportPtr_ is null");
59 return;
60 }
61 dmTransportPtr_->UnInit();
62 }
63
GetInstance()64 std::shared_ptr<DMCommTool> DMCommTool::GetInstance()
65 {
66 static std::shared_ptr<DMCommTool> instance = std::make_shared<DMCommTool>();
67 return instance;
68 }
69
SendUserIds(const std::string rmtNetworkId,const std::vector<uint32_t> & foregroundUserIds,const std::vector<uint32_t> & backgroundUserIds)70 int32_t DMCommTool::SendUserIds(const std::string rmtNetworkId,
71 const std::vector<uint32_t> &foregroundUserIds, const std::vector<uint32_t> &backgroundUserIds)
72 {
73 if (!IsIdLengthValid(rmtNetworkId) || foregroundUserIds.empty() || dmTransportPtr_ == nullptr) {
74 LOGE("param invalid, networkId: %{public}s, foreground userids size: %{public}d",
75 GetAnonyString(rmtNetworkId).c_str(), static_cast<int32_t>(foregroundUserIds.size()));
76 return ERR_DM_INPUT_PARA_INVALID;
77 }
78 int32_t socketId;
79 if (dmTransportPtr_->StartSocket(rmtNetworkId, socketId) != DM_OK || socketId <= 0) {
80 LOGE("Start socket error");
81 return ERR_DM_FAILED;
82 }
83
84 UserIdsMsg userIdsMsg(foregroundUserIds, backgroundUserIds);
85 cJSON *root = cJSON_CreateObject();
86 if (root == nullptr) {
87 LOGE("Create cJSON object failed.");
88 return ERR_DM_FAILED;
89 }
90 ToJson(root, userIdsMsg);
91 char *msg = cJSON_PrintUnformatted(root);
92 if (msg == nullptr) {
93 cJSON_Delete(root);
94 return ERR_DM_FAILED;
95 }
96 std::string msgStr(msg);
97 cJSON_Delete(root);
98 cJSON_free(msg);
99 CommMsg commMsg(DM_COMM_SEND_LOCAL_USERIDS, msgStr);
100 std::string payload = GetCommMsgString(commMsg);
101
102 int32_t ret = dmTransportPtr_->Send(rmtNetworkId, payload, socketId);
103 if (ret != DM_OK) {
104 LOGE("Send local foreground userids failed, ret: %{public}d", ret);
105 return ERR_DM_FAILED;
106 }
107 LOGI("Send local foreground userids success");
108 return DM_OK;
109 }
110
RspLocalFrontOrBackUserIds(const std::string rmtNetworkId,const std::vector<uint32_t> & foregroundUserIds,const std::vector<uint32_t> & backgroundUserIds,int32_t socketId)111 void DMCommTool::RspLocalFrontOrBackUserIds(const std::string rmtNetworkId,
112 const std::vector<uint32_t> &foregroundUserIds, const std::vector<uint32_t> &backgroundUserIds, int32_t socketId)
113 {
114 UserIdsMsg userIdsMsg(foregroundUserIds, backgroundUserIds);
115 cJSON *root = cJSON_CreateObject();
116 if (root == nullptr) {
117 LOGE("Create cJSON object failed.");
118 return;
119 }
120 ToJson(root, userIdsMsg);
121 char *msg = cJSON_PrintUnformatted(root);
122 if (msg == nullptr) {
123 cJSON_Delete(root);
124 return;
125 }
126 std::string msgStr(msg);
127 cJSON_Delete(root);
128 cJSON_free(msg);
129 CommMsg commMsg(DM_COMM_RSP_LOCAL_USERIDS, msgStr);
130 std::string payload = GetCommMsgString(commMsg);
131
132 int32_t ret = dmTransportPtr_->Send(rmtNetworkId, payload, socketId);
133 if (ret != DM_OK) {
134 LOGE("Response local foreground userids failed, ret: %{public}d", ret);
135 return;
136 }
137 LOGI("Response local foreground userids success");
138 }
139
DMCommToolEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> runner,std::shared_ptr<DMCommTool> dmCommToolPtr)140 DMCommTool::DMCommToolEventHandler::DMCommToolEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> runner,
141 std::shared_ptr<DMCommTool> dmCommToolPtr) : AppExecFwk::EventHandler(runner), dmCommToolWPtr_(dmCommToolPtr)
142 {
143 LOGI("Ctor DMCommToolEventHandler");
144 }
145
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)146 void DMCommTool::DMCommToolEventHandler::ProcessEvent(
147 const AppExecFwk::InnerEvent::Pointer &event)
148 {
149 uint32_t eventId = event->GetInnerEventId();
150 std::shared_ptr<InnerCommMsg> commMsg = event->GetSharedObject<InnerCommMsg>();
151 if (commMsg == nullptr) {
152 LOGE("ProcessEvent commMsg is null");
153 return;
154 }
155 if (dmCommToolWPtr_.expired()) {
156 LOGE("dmCommToolWPtr_ is expired");
157 return;
158 }
159 std::shared_ptr<DMCommTool> dmCommToolPtr = dmCommToolWPtr_.lock();
160 if (dmCommToolPtr == nullptr) {
161 LOGE("dmCommToolPtr is null");
162 return;
163 }
164 switch (eventId) {
165 case DM_COMM_SEND_LOCAL_USERIDS: {
166 // Process remote foreground userids and send back local user ids
167 dmCommToolPtr->ProcessReceiveUserIdsEvent(commMsg);
168 break;
169 }
170 case DM_COMM_RSP_LOCAL_USERIDS: {
171 // Process remote foreground userids and close session
172 dmCommToolPtr->ProcessResponseUserIdsEvent(commMsg);
173 break;
174 }
175 case DM_COMM_SEND_USER_STOP: {
176 dmCommToolPtr->ProcessReceiveUserStopEvent(commMsg);
177 break;
178 }
179 case DM_COMM_RSP_USER_STOP: {
180 dmCommToolPtr->ProcessResponseUserStopEvent(commMsg);
181 break;
182 }
183 case DM_COMM_ACCOUNT_LOGOUT: {
184 dmCommToolPtr->ProcessReceiveLogoutEvent(commMsg);
185 break;
186 }
187 default:
188 LOGE("event is undefined, id is %{public}d", eventId);
189 break;
190 }
191 }
192
ProcessReceiveUserIdsEvent(const std::shared_ptr<InnerCommMsg> commMsg)193 void DMCommTool::ProcessReceiveUserIdsEvent(const std::shared_ptr<InnerCommMsg> commMsg)
194 {
195 LOGI("Receive remote userids, process and rsp local userid");
196 std::string rmtUdid = "";
197 SoftbusCache::GetInstance().GetUdidFromCache(commMsg->remoteNetworkId.c_str(), rmtUdid);
198 if (rmtUdid.empty()) {
199 LOGE("Can not find remote udid by networkid: %{public}s", commMsg->remoteNetworkId.c_str());
200 return;
201 }
202
203 std::string payload = commMsg->commMsg->msg;
204 cJSON *root = cJSON_Parse(payload.c_str());
205 if (root == NULL) {
206 LOGE("the msg is not json format");
207 return;
208 }
209 UserIdsMsg userIdsMsg;
210 FromJson(root, userIdsMsg);
211 cJSON_Delete(root);
212 uint32_t totalUserNum = static_cast<uint32_t>(userIdsMsg.foregroundUserIds.size()) +
213 static_cast<uint32_t>(userIdsMsg.backgroundUserIds.size());
214
215 // step1: send back local userids
216 std::vector<int32_t> foregroundUserIds;
217 std::vector<int32_t> backgroundUserIds;
218 MultipleUserConnector::GetForegroundUserIds(foregroundUserIds);
219 MultipleUserConnector::GetBackgroundUserIds(backgroundUserIds);
220 if (DeviceManagerService::GetInstance().IsPC()) {
221 MultipleUserConnector::ClearLockedUser(foregroundUserIds, backgroundUserIds);
222 }
223 std::vector<uint32_t> foregroundUserIdsU32;
224 std::vector<uint32_t> backgroundUserIdsU32;
225 for (auto const &u : foregroundUserIds) {
226 foregroundUserIdsU32.push_back(static_cast<uint32_t>(u));
227 }
228 for (auto const &u : backgroundUserIds) {
229 backgroundUserIdsU32.push_back(static_cast<uint32_t>(u));
230 }
231 RspLocalFrontOrBackUserIds(commMsg->remoteNetworkId, foregroundUserIdsU32, backgroundUserIdsU32,
232 commMsg->socketId);
233
234 if (userIdsMsg.foregroundUserIds.empty()) {
235 LOGE("Parse but get none remote foreground userids");
236 } else {
237 // step2: process remote foreground/background userids
238 DeviceManagerService::GetInstance().ProcessSyncUserIds(userIdsMsg.foregroundUserIds,
239 userIdsMsg.backgroundUserIds, rmtUdid);
240 }
241 }
242
ProcessResponseUserIdsEvent(const std::shared_ptr<InnerCommMsg> commMsg)243 void DMCommTool::ProcessResponseUserIdsEvent(const std::shared_ptr<InnerCommMsg> commMsg)
244 {
245 LOGI("process receive remote userids response");
246 // step1: close socket
247 this->dmTransportPtr_->StopSocket(commMsg->remoteNetworkId);
248
249 std::string rmtUdid = "";
250 SoftbusCache::GetInstance().GetUdidFromCache(commMsg->remoteNetworkId.c_str(), rmtUdid);
251 if (rmtUdid.empty()) {
252 LOGE("Can not find remote udid by networkid: %{public}s", commMsg->remoteNetworkId.c_str());
253 return;
254 }
255
256 std::string payload = commMsg->commMsg->msg;
257 cJSON *root = cJSON_Parse(payload.c_str());
258 if (root == NULL) {
259 LOGE("the msg is not json format");
260 return;
261 }
262 UserIdsMsg userIdsMsg;
263 FromJson(root, userIdsMsg);
264 cJSON_Delete(root);
265 if (userIdsMsg.foregroundUserIds.empty()) {
266 LOGE("Parse but get none remote userids");
267 return;
268 }
269 // step2: process remote foreground/background userids
270 if (!userIdsMsg.foregroundUserIds.empty()) {
271 DeviceManagerService::GetInstance().ProcessSyncUserIds(userIdsMsg.foregroundUserIds,
272 userIdsMsg.backgroundUserIds, rmtUdid);
273 } else {
274 LOGE("Receive remote foreground userid empty");
275 }
276 }
277
GetEventHandler()278 std::shared_ptr<DMCommTool::DMCommToolEventHandler> DMCommTool::GetEventHandler()
279 {
280 return this->eventHandler_;
281 }
282
GetDMTransportPtr()283 const std::shared_ptr<DMTransport> DMCommTool::GetDMTransportPtr()
284 {
285 return this->dmTransportPtr_;
286 }
287
CreateUserStopMessage(int32_t stopUserId,std::string & msgStr)288 int32_t DMCommTool::CreateUserStopMessage(int32_t stopUserId, std::string &msgStr)
289 {
290 cJSON *root = cJSON_CreateObject();
291 if (root == nullptr) {
292 LOGE("Create cJSON object failed.");
293 return ERR_DM_FAILED;
294 }
295 cJSON *numberObj = cJSON_CreateNumber(stopUserId);
296 if (numberObj == nullptr) {
297 cJSON_Delete(root);
298 return ERR_DM_FAILED;
299 }
300 cJSON_AddItemToObject(root, USER_STOP_MSG_KEY, numberObj);
301 char *msg = cJSON_PrintUnformatted(root);
302 if (msg == nullptr) {
303 cJSON_Delete(root);
304 return ERR_DM_FAILED;
305 }
306 msgStr = std::string(msg);
307 cJSON_free(msg);
308 cJSON_Delete(root);
309 return DM_OK;
310 }
311
ParseUserStopMessage(const std::string & msgStr,int32_t & stopUserId)312 int32_t DMCommTool::ParseUserStopMessage(const std::string &msgStr, int32_t &stopUserId)
313 {
314 cJSON *root = cJSON_Parse(msgStr.c_str());
315 if (root == NULL) {
316 LOGE("the msg is not json format");
317 return ERR_DM_FAILED;
318 }
319 cJSON *stopUserIdObj = cJSON_GetObjectItem(root, USER_STOP_MSG_KEY);
320 if (stopUserIdObj == NULL || !cJSON_IsNumber(stopUserIdObj)) {
321 LOGE("parse stopUserId id failed.");
322 cJSON_Delete(root);
323 return ERR_DM_FAILED;
324 }
325 stopUserId = static_cast<int32_t>(stopUserIdObj->valueint);
326 cJSON_Delete(root);
327 return DM_OK;
328 }
329
SendUserStop(const std::string rmtNetworkId,int32_t stopUserId)330 int32_t DMCommTool::SendUserStop(const std::string rmtNetworkId, int32_t stopUserId)
331 {
332 std::string msgStr;
333 int32_t ret = CreateUserStopMessage(stopUserId, msgStr);
334 if (ret != DM_OK) {
335 LOGE("error ret: %{public}d", ret);
336 return ret;
337 }
338 return SendMsg(rmtNetworkId, DM_COMM_SEND_USER_STOP, msgStr);
339 }
340
SendMsg(const std::string rmtNetworkId,int32_t msgType,const std::string & msg)341 int32_t DMCommTool::SendMsg(const std::string rmtNetworkId, int32_t msgType, const std::string &msg)
342 {
343 if (!IsIdLengthValid(rmtNetworkId) || dmTransportPtr_ == nullptr) {
344 LOGE("param invalid, networkId: %{public}s", GetAnonyString(rmtNetworkId).c_str());
345 return ERR_DM_INPUT_PARA_INVALID;
346 }
347 int32_t socketId;
348 if (dmTransportPtr_->StartSocket(rmtNetworkId, socketId) != DM_OK || socketId <= 0) {
349 LOGE("Start socket error");
350 return ERR_DM_FAILED;
351 }
352 CommMsg commMsg(msgType, msg);
353 std::string payload = GetCommMsgString(commMsg);
354 int32_t ret = dmTransportPtr_->Send(rmtNetworkId, payload, socketId);
355 if (ret != DM_OK) {
356 LOGE("SendMsg failed, ret: %{public}d", ret);
357 return ERR_DM_FAILED;
358 }
359 LOGI("SendMsg success");
360 return DM_OK;
361 }
362
ProcessReceiveUserStopEvent(const std::shared_ptr<InnerCommMsg> commMsg)363 void DMCommTool::ProcessReceiveUserStopEvent(const std::shared_ptr<InnerCommMsg> commMsg)
364 {
365 LOGI("start");
366 CHECK_NULL_VOID(commMsg);
367 std::string rmtUdid = "";
368 SoftbusCache::GetInstance().GetUdidFromCache(commMsg->remoteNetworkId.c_str(), rmtUdid);
369 if (rmtUdid.empty()) {
370 LOGE("Can not find remote udid by networkid: %{public}s", GetAnonyString(commMsg->remoteNetworkId).c_str());
371 return;
372 }
373 int32_t stopUserId = -1;
374 int32_t ret = ParseUserStopMessage(commMsg->commMsg->msg, stopUserId);
375 if (ret != DM_OK) {
376 LOGE("ParseUserStopMessage error ret: %{public}d", ret);
377 return;
378 }
379 RspUserStop(commMsg->remoteNetworkId, commMsg->socketId, stopUserId);
380 DeviceManagerService::GetInstance().HandleUserStop(stopUserId, rmtUdid);
381 }
382
RspUserStop(const std::string rmtNetworkId,int32_t socketId,int32_t stopUserId)383 void DMCommTool::RspUserStop(const std::string rmtNetworkId, int32_t socketId, int32_t stopUserId)
384 {
385 std::string msgStr = "";
386 CHECK_NULL_VOID(dmTransportPtr_);
387 int32_t ret = CreateUserStopMessage(stopUserId, msgStr);
388 if (ret != DM_OK || msgStr.empty()) {
389 LOGE("error ret: %{public}d", ret);
390 return;
391 }
392 CommMsg commMsg(DM_COMM_RSP_USER_STOP, msgStr);
393 std::string payload = GetCommMsgString(commMsg);
394 ret = dmTransportPtr_->Send(rmtNetworkId, payload, socketId);
395 if (ret != DM_OK) {
396 LOGE("failed, ret: %{public}d", ret);
397 return;
398 }
399 LOGI("success");
400 }
401
ProcessResponseUserStopEvent(const std::shared_ptr<InnerCommMsg> commMsg)402 void DMCommTool::ProcessResponseUserStopEvent(const std::shared_ptr<InnerCommMsg> commMsg)
403 {
404 LOGI("start");
405 CHECK_NULL_VOID(commMsg);
406 this->dmTransportPtr_->StopSocket(commMsg->remoteNetworkId);
407 std::string rmtUdid = "";
408 SoftbusCache::GetInstance().GetUdidFromCache(commMsg->remoteNetworkId.c_str(), rmtUdid);
409 if (rmtUdid.empty()) {
410 LOGE("Can not find remote udid by networkid: %{public}s", GetAnonyString(commMsg->remoteNetworkId).c_str());
411 return;
412 }
413 int32_t stopUserId = -1;
414 int32_t ret = ParseUserStopMessage(commMsg->commMsg->msg, stopUserId);
415 if (ret != DM_OK) {
416 LOGE("ParseUserStopMessage error ret: %{public}d", ret);
417 return;
418 }
419 std::vector<std::string> acceptEventUdids;
420 acceptEventUdids.push_back(rmtUdid);
421 char localDeviceId[DEVICE_UUID_LENGTH] = {0};
422 GetDevUdid(localDeviceId, DEVICE_UUID_LENGTH);
423 std::string localUdid = static_cast<std::string>(localDeviceId);
424 DeviceManagerService::GetInstance().HandleUserStop(stopUserId, localUdid, acceptEventUdids);
425 }
426
SendLogoutAccountInfo(const std::string & rmtNetworkId,const std::string & accountId,int32_t userId)427 int32_t DMCommTool::SendLogoutAccountInfo(const std::string &rmtNetworkId,
428 const std::string &accountId, int32_t userId)
429 {
430 if (!IsIdLengthValid(rmtNetworkId) || accountId.empty() || dmTransportPtr_ == nullptr) {
431 LOGE("param invalid, networkId: %{public}s, userId: %{public}d",
432 GetAnonyString(rmtNetworkId).c_str(), userId);
433 return ERR_DM_INPUT_PARA_INVALID;
434 }
435 LOGI("Start, send networkId: %{public}s", GetAnonyString(rmtNetworkId).c_str());
436 int32_t socketId = 0;
437 if (dmTransportPtr_->StartSocket(rmtNetworkId, socketId) != DM_OK || socketId <= 0) {
438 LOGE("Start socket error");
439 return ERR_DM_FAILED;
440 }
441
442 cJSON *root = cJSON_CreateObject();
443 if (root == nullptr) {
444 LOGE("Create cJSON object failed.");
445 return ERR_DM_FAILED;
446 }
447 LogoutAccountMsg LogoutAccountMsg(accountId, userId);
448 ToJson(root, LogoutAccountMsg);
449 char *msg = cJSON_PrintUnformatted(root);
450 if (msg == nullptr) {
451 cJSON_Delete(root);
452 return ERR_DM_FAILED;
453 }
454 std::string msgStr(msg);
455 cJSON_Delete(root);
456 cJSON_free(msg);
457 CommMsg commMsg(DM_COMM_ACCOUNT_LOGOUT, msgStr);
458 std::string payload = GetCommMsgString(commMsg);
459
460 int32_t ret = dmTransportPtr_->Send(rmtNetworkId, payload, socketId);
461 if (ret != DM_OK) {
462 LOGE("Send account logout failed, ret: %{public}d", ret);
463 return ERR_DM_FAILED;
464 }
465 LOGI("Send account logout success");
466 return DM_OK;
467 }
468
ProcessReceiveLogoutEvent(const std::shared_ptr<InnerCommMsg> commMsg)469 void DMCommTool::ProcessReceiveLogoutEvent(const std::shared_ptr<InnerCommMsg> commMsg)
470 {
471 CHECK_NULL_VOID(commMsg);
472 LOGI("Receive remote logout, networkId: %{public}s", GetAnonyString(commMsg->remoteNetworkId).c_str());
473 std::string rmtUdid = "";
474 SoftbusCache::GetInstance().GetUdidFromCache(commMsg->remoteNetworkId.c_str(), rmtUdid);
475 if (rmtUdid.empty()) {
476 LOGE("Can not find remote udid by networkid: %{public}s", GetAnonyString(commMsg->remoteNetworkId).c_str());
477 return;
478 }
479
480 CHECK_NULL_VOID(commMsg->commMsg);
481 std::string payload = commMsg->commMsg->msg;
482 cJSON *root = cJSON_Parse(payload.c_str());
483 if (root == NULL) {
484 LOGE("the msg is not json format");
485 return;
486 }
487 LogoutAccountMsg logoutAccountMsg;
488 FromJson(root, logoutAccountMsg);
489 cJSON_Delete(root);
490
491 if (logoutAccountMsg.accountId.empty() || logoutAccountMsg.userId == -1) {
492 LOGE("param invalid, accountId: %{public}s, userId: %{public}d",
493 GetAnonyString(logoutAccountMsg.accountId).c_str(), logoutAccountMsg.userId);
494 return;
495 }
496 DeviceManagerService::GetInstance().ProcessSyncAccountLogout(logoutAccountMsg.accountId,
497 rmtUdid, logoutAccountMsg.userId);
498 LOGI("process remote logout success.");
499 }
500 } // DistributedHardware
501 } // OHOS