1f857971dSopenharmony_ci/* 2f857971dSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3f857971dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4f857971dSopenharmony_ci * you may not use this file except in compliance with the License. 5f857971dSopenharmony_ci * You may obtain a copy of the License at 6f857971dSopenharmony_ci * 7f857971dSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8f857971dSopenharmony_ci * 9f857971dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10f857971dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11f857971dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12f857971dSopenharmony_ci * See the License for the specific language governing permissions and 13f857971dSopenharmony_ci * limitations under the License. 14f857971dSopenharmony_ci */ 15f857971dSopenharmony_ci 16f857971dSopenharmony_ci#include "stream_server.h" 17f857971dSopenharmony_ci 18f857971dSopenharmony_ci#include <cinttypes> 19f857971dSopenharmony_ci#include <list> 20f857971dSopenharmony_ci 21f857971dSopenharmony_ci#include <sys/socket.h> 22f857971dSopenharmony_ci 23f857971dSopenharmony_ci#include "devicestatus_service.h" 24f857971dSopenharmony_ci#include "fi_log.h" 25f857971dSopenharmony_ci 26f857971dSopenharmony_ci#undef LOG_TAG 27f857971dSopenharmony_ci#define LOG_TAG "StreamServer" 28f857971dSopenharmony_ci 29f857971dSopenharmony_cinamespace OHOS { 30f857971dSopenharmony_cinamespace Msdp { 31f857971dSopenharmony_cinamespace DeviceStatus { 32f857971dSopenharmony_ci 33f857971dSopenharmony_ciStreamServer::~StreamServer() 34f857971dSopenharmony_ci{ 35f857971dSopenharmony_ci CALL_DEBUG_ENTER; 36f857971dSopenharmony_ci UdsStop(); 37f857971dSopenharmony_ci} 38f857971dSopenharmony_ci 39f857971dSopenharmony_civoid StreamServer::UdsStop() 40f857971dSopenharmony_ci{ 41f857971dSopenharmony_ci if (epollFd_ != -1) { 42f857971dSopenharmony_ci if (close(epollFd_) < 0) { 43f857971dSopenharmony_ci FI_HILOGE("Close epoll fd failed, error:%{public}s, epollFd_:%{public}d", strerror(errno), epollFd_); 44f857971dSopenharmony_ci } 45f857971dSopenharmony_ci epollFd_ = -1; 46f857971dSopenharmony_ci } 47f857971dSopenharmony_ci 48f857971dSopenharmony_ci for (const auto &item : sessionss_) { 49f857971dSopenharmony_ci item.second->Close(); 50f857971dSopenharmony_ci } 51f857971dSopenharmony_ci sessionss_.clear(); 52f857971dSopenharmony_ci} 53f857971dSopenharmony_ci 54f857971dSopenharmony_ciint32_t StreamServer::GetClientFd(int32_t pid) const 55f857971dSopenharmony_ci{ 56f857971dSopenharmony_ci auto it = idxPids_.find(pid); 57f857971dSopenharmony_ci if (it == idxPids_.end()) { 58f857971dSopenharmony_ci return INVALID_FD; 59f857971dSopenharmony_ci } 60f857971dSopenharmony_ci return it->second; 61f857971dSopenharmony_ci} 62f857971dSopenharmony_ci 63f857971dSopenharmony_ciint32_t StreamServer::GetClientPid(int32_t fd) const 64f857971dSopenharmony_ci{ 65f857971dSopenharmony_ci auto it = sessionss_.find(fd); 66f857971dSopenharmony_ci if (it == sessionss_.end()) { 67f857971dSopenharmony_ci return INVALID_PID; 68f857971dSopenharmony_ci } 69f857971dSopenharmony_ci return it->second->GetPid(); 70f857971dSopenharmony_ci} 71f857971dSopenharmony_ci 72f857971dSopenharmony_cibool StreamServer::SendMsg(int32_t fd, NetPacket &pkt) 73f857971dSopenharmony_ci{ 74f857971dSopenharmony_ci if (fd < 0) { 75f857971dSopenharmony_ci FI_HILOGE("The fd is less than 0"); 76f857971dSopenharmony_ci return false; 77f857971dSopenharmony_ci } 78f857971dSopenharmony_ci auto ses = GetSession(fd); 79f857971dSopenharmony_ci if (ses == nullptr) { 80f857971dSopenharmony_ci FI_HILOGE("The fd:%{public}d not found, The message was discarded, errCode:%{public}d", 81f857971dSopenharmony_ci fd, SESSION_NOT_FOUND); 82f857971dSopenharmony_ci return false; 83f857971dSopenharmony_ci } 84f857971dSopenharmony_ci return ses->SendMsg(pkt); 85f857971dSopenharmony_ci} 86f857971dSopenharmony_ci 87f857971dSopenharmony_civoid StreamServer::Multicast(const std::vector<int32_t> &fdList, NetPacket &pkt) 88f857971dSopenharmony_ci{ 89f857971dSopenharmony_ci for (const auto &item : fdList) { 90f857971dSopenharmony_ci SendMsg(item, pkt); 91f857971dSopenharmony_ci } 92f857971dSopenharmony_ci} 93f857971dSopenharmony_ci 94f857971dSopenharmony_ciint32_t StreamServer::AddSocketPairInfo(const std::string &programName, int32_t moduleType, int32_t uid, int32_t pid, 95f857971dSopenharmony_ci int32_t &serverFd, int32_t &toReturnClientFd, int32_t &tokenType) 96f857971dSopenharmony_ci{ 97f857971dSopenharmony_ci CALL_DEBUG_ENTER; 98f857971dSopenharmony_ci int32_t sockFds[2] = { -1 }; 99f857971dSopenharmony_ci 100f857971dSopenharmony_ci if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockFds) != 0) { 101f857971dSopenharmony_ci FI_HILOGE("Call socketpair failed, errno:%{public}d", errno); 102f857971dSopenharmony_ci return RET_ERR; 103f857971dSopenharmony_ci } 104f857971dSopenharmony_ci serverFd = sockFds[0]; 105f857971dSopenharmony_ci toReturnClientFd = sockFds[1]; 106f857971dSopenharmony_ci if (serverFd < 0 || toReturnClientFd < 0) { 107f857971dSopenharmony_ci FI_HILOGE("Call fcntl failed, errno:%{public}d", errno); 108f857971dSopenharmony_ci return RET_ERR; 109f857971dSopenharmony_ci } 110f857971dSopenharmony_ci int32_t setSockOptResult = SetSockOpt(serverFd, toReturnClientFd, tokenType); 111f857971dSopenharmony_ci if (RET_OK != setSockOptResult) { 112f857971dSopenharmony_ci return setSockOptResult; 113f857971dSopenharmony_ci } 114f857971dSopenharmony_ci SessionPtr sess = nullptr; 115f857971dSopenharmony_ci sess = std::make_shared<StreamSession>(programName, moduleType, serverFd, uid, pid); 116f857971dSopenharmony_ci sess->SetTokenType(tokenType); 117f857971dSopenharmony_ci if (!AddSession(sess)) { 118f857971dSopenharmony_ci FI_HILOGE("AddSession fail errCode:%{public}d", ADD_SESSION_FAIL); 119f857971dSopenharmony_ci return CloseFd(serverFd, toReturnClientFd); 120f857971dSopenharmony_ci } 121f857971dSopenharmony_ci if (AddEpoll(EPOLL_EVENT_SOCKET, serverFd) != RET_OK) { 122f857971dSopenharmony_ci FI_HILOGE("epoll_ctl EPOLL_CTL_ADD failed, errCode:%{public}d", EPOLL_MODIFY_FAIL); 123f857971dSopenharmony_ci return CloseFd(serverFd, toReturnClientFd); 124f857971dSopenharmony_ci } 125f857971dSopenharmony_ci OnConnected(sess); 126f857971dSopenharmony_ci return RET_OK; 127f857971dSopenharmony_ci} 128f857971dSopenharmony_ci 129f857971dSopenharmony_ciint32_t StreamServer::SetSockOpt(int32_t &serverFd, int32_t &toReturnClientFd, int32_t &tokenType) 130f857971dSopenharmony_ci{ 131f857971dSopenharmony_ci CALL_DEBUG_ENTER; 132f857971dSopenharmony_ci static constexpr size_t bufferSize = 32 * 1024; 133f857971dSopenharmony_ci static constexpr size_t nativeBufferSize = 64 * 1024; 134f857971dSopenharmony_ci 135f857971dSopenharmony_ci if (setsockopt(serverFd, SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)) != 0) { 136f857971dSopenharmony_ci FI_HILOGE("setsockopt serverFd failed, errno:%{public}d", errno); 137f857971dSopenharmony_ci return CloseFd(serverFd, toReturnClientFd); 138f857971dSopenharmony_ci } 139f857971dSopenharmony_ci if (setsockopt(serverFd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)) != 0) { 140f857971dSopenharmony_ci FI_HILOGE("setsockopt serverFd failed, errno:%{public}d", errno); 141f857971dSopenharmony_ci return CloseFd(serverFd, toReturnClientFd); 142f857971dSopenharmony_ci } 143f857971dSopenharmony_ci if (tokenType == TokenType::TOKEN_NATIVE) { 144f857971dSopenharmony_ci if (setsockopt(toReturnClientFd, SOL_SOCKET, SO_SNDBUF, &nativeBufferSize, sizeof(nativeBufferSize)) != 0) { 145f857971dSopenharmony_ci FI_HILOGE("setsockopt toReturnClientFd failed, errno:%{public}d", errno); 146f857971dSopenharmony_ci return CloseFd(serverFd, toReturnClientFd); 147f857971dSopenharmony_ci } 148f857971dSopenharmony_ci if (setsockopt(toReturnClientFd, SOL_SOCKET, SO_RCVBUF, &nativeBufferSize, sizeof(nativeBufferSize)) != 0) { 149f857971dSopenharmony_ci FI_HILOGE("setsockopt toReturnClientFd failed, errno:%{public}d", errno); 150f857971dSopenharmony_ci return CloseFd(serverFd, toReturnClientFd); 151f857971dSopenharmony_ci } 152f857971dSopenharmony_ci } else { 153f857971dSopenharmony_ci if (setsockopt(toReturnClientFd, SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)) != 0) { 154f857971dSopenharmony_ci FI_HILOGE("setsockopt toReturnClientFd failed, errno:%{public}d", errno); 155f857971dSopenharmony_ci return CloseFd(serverFd, toReturnClientFd); 156f857971dSopenharmony_ci } 157f857971dSopenharmony_ci if (setsockopt(toReturnClientFd, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)) != 0) { 158f857971dSopenharmony_ci FI_HILOGE("setsockopt toReturnClientFd failed, errno:%{public}d", errno); 159f857971dSopenharmony_ci return CloseFd(serverFd, toReturnClientFd); 160f857971dSopenharmony_ci } 161f857971dSopenharmony_ci } 162f857971dSopenharmony_ci return RET_OK; 163f857971dSopenharmony_ci} 164f857971dSopenharmony_ci 165f857971dSopenharmony_ciint32_t StreamServer::CloseFd(int32_t &serverFd, int32_t &toReturnClientFd) 166f857971dSopenharmony_ci{ 167f857971dSopenharmony_ci if (close(serverFd) < 0) { 168f857971dSopenharmony_ci FI_HILOGE("Close server fd failed, error:%{public}s, serverFd:%{public}d", strerror(errno), serverFd); 169f857971dSopenharmony_ci } 170f857971dSopenharmony_ci serverFd = -1; 171f857971dSopenharmony_ci if (close(toReturnClientFd) < 0) { 172f857971dSopenharmony_ci FI_HILOGE("Close fd failed, error:%{public}s, toReturnClientFd:%{public}d", strerror(errno), toReturnClientFd); 173f857971dSopenharmony_ci } 174f857971dSopenharmony_ci toReturnClientFd = -1; 175f857971dSopenharmony_ci return RET_ERR; 176f857971dSopenharmony_ci} 177f857971dSopenharmony_ci 178f857971dSopenharmony_civoid StreamServer::SetRecvFun(MsgServerFunCallback fun) 179f857971dSopenharmony_ci{ 180f857971dSopenharmony_ci recvFun_ = fun; 181f857971dSopenharmony_ci} 182f857971dSopenharmony_ci 183f857971dSopenharmony_civoid StreamServer::ReleaseSession(int32_t fd, epoll_event &ev) 184f857971dSopenharmony_ci{ 185f857971dSopenharmony_ci auto secPtr = GetSession(fd); 186f857971dSopenharmony_ci if (secPtr != nullptr) { 187f857971dSopenharmony_ci OnDisconnected(secPtr); 188f857971dSopenharmony_ci DelSession(fd); 189f857971dSopenharmony_ci } 190f857971dSopenharmony_ci if (ev.data.ptr) { 191f857971dSopenharmony_ci free(ev.data.ptr); 192f857971dSopenharmony_ci ev.data.ptr = nullptr; 193f857971dSopenharmony_ci } 194f857971dSopenharmony_ci if (auto it = circleBufs_.find(fd); it != circleBufs_.end()) { 195f857971dSopenharmony_ci circleBufs_.erase(it); 196f857971dSopenharmony_ci } 197f857971dSopenharmony_ci auto DeviceStatusService = DeviceStatus::DelayedSpSingleton<DeviceStatus::DeviceStatusService>::GetInstance(); 198f857971dSopenharmony_ci DeviceStatusService->DelEpoll(EPOLL_EVENT_SOCKET, fd); 199f857971dSopenharmony_ci if (close(fd) < 0) { 200f857971dSopenharmony_ci FI_HILOGE("Close fd failed, error:%{public}s, fd:%{public}d", strerror(errno), fd); 201f857971dSopenharmony_ci } 202f857971dSopenharmony_ci} 203f857971dSopenharmony_ci 204f857971dSopenharmony_civoid StreamServer::OnPacket(int32_t fd, NetPacket &pkt) 205f857971dSopenharmony_ci{ 206f857971dSopenharmony_ci auto sess = GetSession(fd); 207f857971dSopenharmony_ci CHKPV(sess); 208f857971dSopenharmony_ci recvFun_(sess, pkt); 209f857971dSopenharmony_ci} 210f857971dSopenharmony_ci 211f857971dSopenharmony_civoid StreamServer::OnEpollRecv(int32_t fd, epoll_event &ev) 212f857971dSopenharmony_ci{ 213f857971dSopenharmony_ci if (fd < 0) { 214f857971dSopenharmony_ci FI_HILOGE("Invalid fd:%{public}d", fd); 215f857971dSopenharmony_ci return; 216f857971dSopenharmony_ci } 217f857971dSopenharmony_ci auto& buf = circleBufs_[fd]; 218f857971dSopenharmony_ci char szBuf[MAX_PACKET_BUF_SIZE] = { 0 }; 219f857971dSopenharmony_ci for (int32_t i = 0; i < MAX_RECV_LIMIT; i++) { 220f857971dSopenharmony_ci ssize_t size = recv(fd, szBuf, MAX_PACKET_BUF_SIZE, MSG_DONTWAIT | MSG_NOSIGNAL); 221f857971dSopenharmony_ci if (size > 0) { 222f857971dSopenharmony_ci if (!buf.Write(szBuf, size)) { 223f857971dSopenharmony_ci FI_HILOGW("Write data failed, size:%{public}zd", size); 224f857971dSopenharmony_ci } 225f857971dSopenharmony_ci OnReadPackets(buf, [this, fd](NetPacket &pkt) { this->OnPacket(fd, pkt); }); 226f857971dSopenharmony_ci } else if (size < 0) { 227f857971dSopenharmony_ci if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) { 228f857971dSopenharmony_ci FI_HILOGD("Continue for errno EAGAIN|EINTR|EWOULDBLOCK size:%{public}zd errno:%{public}d", 229f857971dSopenharmony_ci size, errno); 230f857971dSopenharmony_ci continue; 231f857971dSopenharmony_ci } 232f857971dSopenharmony_ci FI_HILOGE("Recv return %{public}zd, errno:%{public}d", size, errno); 233f857971dSopenharmony_ci break; 234f857971dSopenharmony_ci } else { 235f857971dSopenharmony_ci FI_HILOGE("The client side disconnect with the server, size:0, errno:%{public}d", errno); 236f857971dSopenharmony_ci ReleaseSession(fd, ev); 237f857971dSopenharmony_ci break; 238f857971dSopenharmony_ci } 239f857971dSopenharmony_ci if (static_cast<size_t>(size) < MAX_PACKET_BUF_SIZE) { 240f857971dSopenharmony_ci break; 241f857971dSopenharmony_ci } 242f857971dSopenharmony_ci } 243f857971dSopenharmony_ci} 244f857971dSopenharmony_ci 245f857971dSopenharmony_civoid StreamServer::OnEpollEvent(epoll_event &ev) 246f857971dSopenharmony_ci{ 247f857971dSopenharmony_ci CHKPV(ev.data.ptr); 248f857971dSopenharmony_ci int32_t fd = *static_cast<int32_t*>(ev.data.ptr); 249f857971dSopenharmony_ci if (fd < 0) { 250f857971dSopenharmony_ci FI_HILOGE("The fd less than 0, errCode:%{public}d", PARAM_INPUT_INVALID); 251f857971dSopenharmony_ci return; 252f857971dSopenharmony_ci } 253f857971dSopenharmony_ci if ((ev.events & EPOLLERR) || (ev.events & EPOLLHUP)) { 254f857971dSopenharmony_ci FI_HILOGI("EPOLLERR or EPOLLHUP, fd:%{public}d, ev.events:0x%{public}x", fd, ev.events); 255f857971dSopenharmony_ci ReleaseSession(fd, ev); 256f857971dSopenharmony_ci } else if (ev.events & EPOLLIN) { 257f857971dSopenharmony_ci OnEpollRecv(fd, ev); 258f857971dSopenharmony_ci } 259f857971dSopenharmony_ci} 260f857971dSopenharmony_ci 261f857971dSopenharmony_civoid StreamServer::DumpSession(const std::string &title) 262f857971dSopenharmony_ci{ 263f857971dSopenharmony_ci FI_HILOGD("in %{public}s:%{public}s", __func__, title.c_str()); 264f857971dSopenharmony_ci int32_t i = 0; 265f857971dSopenharmony_ci for (auto &[key, value] : sessionss_) { 266f857971dSopenharmony_ci CHKPV(value); 267f857971dSopenharmony_ci i++; 268f857971dSopenharmony_ci } 269f857971dSopenharmony_ci} 270f857971dSopenharmony_ci 271f857971dSopenharmony_ciSessionPtr StreamServer::GetSession(int32_t fd) const 272f857971dSopenharmony_ci{ 273f857971dSopenharmony_ci auto it = sessionss_.find(fd); 274f857971dSopenharmony_ci if (it == sessionss_.end()) { 275f857971dSopenharmony_ci FI_HILOGE("Session not found, fd:%{public}d", fd); 276f857971dSopenharmony_ci return nullptr; 277f857971dSopenharmony_ci } 278f857971dSopenharmony_ci CHKPP(it->second); 279f857971dSopenharmony_ci return it->second->GetSharedPtr(); 280f857971dSopenharmony_ci} 281f857971dSopenharmony_ci 282f857971dSopenharmony_ciSessionPtr StreamServer::GetSessionByPid(int32_t pid) const 283f857971dSopenharmony_ci{ 284f857971dSopenharmony_ci int32_t fd = GetClientFd(pid); 285f857971dSopenharmony_ci if (fd <= 0) { 286f857971dSopenharmony_ci FI_HILOGE("Session not found, pid:%{public}d", pid); 287f857971dSopenharmony_ci return nullptr; 288f857971dSopenharmony_ci } 289f857971dSopenharmony_ci return GetSession(fd); 290f857971dSopenharmony_ci} 291f857971dSopenharmony_ci 292f857971dSopenharmony_cibool StreamServer::AddSession(SessionPtr ses) 293f857971dSopenharmony_ci{ 294f857971dSopenharmony_ci CHKPF(ses); 295f857971dSopenharmony_ci FI_HILOGI("pid:%{public}d, fd:%{public}d", ses->GetPid(), ses->GetFd()); 296f857971dSopenharmony_ci int32_t fd = ses->GetFd(); 297f857971dSopenharmony_ci if (fd < 0) { 298f857971dSopenharmony_ci FI_HILOGE("The fd is less than 0"); 299f857971dSopenharmony_ci return false; 300f857971dSopenharmony_ci } 301f857971dSopenharmony_ci int32_t pid = ses->GetPid(); 302f857971dSopenharmony_ci if (pid <= 0) { 303f857971dSopenharmony_ci FI_HILOGE("Get process failed"); 304f857971dSopenharmony_ci return false; 305f857971dSopenharmony_ci } 306f857971dSopenharmony_ci if (sessionss_.size() > MAX_SESSION_ALARM) { 307f857971dSopenharmony_ci FI_HILOGE("Too many clients, Warning Value:%{public}zu, Current Value:%{public}zu", 308f857971dSopenharmony_ci MAX_SESSION_ALARM, sessionss_.size()); 309f857971dSopenharmony_ci return false; 310f857971dSopenharmony_ci } 311f857971dSopenharmony_ci DumpSession("AddSession"); 312f857971dSopenharmony_ci idxPids_[pid] = fd; 313f857971dSopenharmony_ci sessionss_[fd] = ses; 314f857971dSopenharmony_ci FI_HILOGI("Add session end"); 315f857971dSopenharmony_ci return true; 316f857971dSopenharmony_ci} 317f857971dSopenharmony_ci 318f857971dSopenharmony_civoid StreamServer::DelSession(int32_t fd) 319f857971dSopenharmony_ci{ 320f857971dSopenharmony_ci CALL_DEBUG_ENTER; 321f857971dSopenharmony_ci FI_HILOGI("fd:%{public}d", fd); 322f857971dSopenharmony_ci if (fd < 0) { 323f857971dSopenharmony_ci FI_HILOGE("The fd less than 0, errCode:%{public}d", PARAM_INPUT_INVALID); 324f857971dSopenharmony_ci return; 325f857971dSopenharmony_ci } 326f857971dSopenharmony_ci int32_t pid = GetClientPid(fd); 327f857971dSopenharmony_ci if (pid > 0) { 328f857971dSopenharmony_ci idxPids_.erase(pid); 329f857971dSopenharmony_ci } 330f857971dSopenharmony_ci auto it = sessionss_.find(fd); 331f857971dSopenharmony_ci if (it != sessionss_.end()) { 332f857971dSopenharmony_ci NotifySessionDeleted(it->second); 333f857971dSopenharmony_ci sessionss_.erase(it); 334f857971dSopenharmony_ci } 335f857971dSopenharmony_ci DumpSession("DelSession"); 336f857971dSopenharmony_ci} 337f857971dSopenharmony_ci 338f857971dSopenharmony_civoid StreamServer::AddSessionDeletedCallback(int32_t pid, std::function<void(SessionPtr)> callback) 339f857971dSopenharmony_ci{ 340f857971dSopenharmony_ci CALL_DEBUG_ENTER; 341f857971dSopenharmony_ci auto it = callbacks_.find(pid); 342f857971dSopenharmony_ci if (it != callbacks_.end()) { 343f857971dSopenharmony_ci FI_HILOGW("Deleted session already exists"); 344f857971dSopenharmony_ci return; 345f857971dSopenharmony_ci } 346f857971dSopenharmony_ci callbacks_[pid] = callback; 347f857971dSopenharmony_ci} 348f857971dSopenharmony_ci 349f857971dSopenharmony_civoid StreamServer::NotifySessionDeleted(SessionPtr ses) 350f857971dSopenharmony_ci{ 351f857971dSopenharmony_ci CALL_DEBUG_ENTER; 352f857971dSopenharmony_ci auto it = callbacks_.find(ses->GetPid()); 353f857971dSopenharmony_ci if (it != callbacks_.end()) { 354f857971dSopenharmony_ci it->second(ses); 355f857971dSopenharmony_ci callbacks_.erase(it); 356f857971dSopenharmony_ci } 357f857971dSopenharmony_ci} 358f857971dSopenharmony_ci} // namespace DeviceStatus 359f857971dSopenharmony_ci} // namespace Msdp 360f857971dSopenharmony_ci} // namespace OHOS 361