1 /*
2 * Copyright (c) 2021-2022 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 #include "mmi_client.h"
16
17 #include <cinttypes>
18 #include <condition_variable>
19
20 #include "mmi_log.h"
21 #include "proto.h"
22 #include "util.h"
23
24 #include "input_manager_impl.h"
25 #include "mmi_fd_listener.h"
26 #include "multimodal_event_handler.h"
27 #include "multimodal_input_connect_manager.h"
28
29 namespace OHOS {
30 namespace MMI {
31 namespace {
32 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "MMIClient" };
33 const std::string THREAD_NAME = "mmi_EventHdr";
34 } // namespace
35
36 using namespace AppExecFwk;
~MMIClient()37 MMIClient::~MMIClient()
38 {
39 CALL_DEBUG_ENTER;
40 Stop();
41 }
42
SetEventHandler(EventHandlerPtr eventHandler)43 void MMIClient::SetEventHandler(EventHandlerPtr eventHandler)
44 {
45 CHKPV(eventHandler);
46 eventHandler_ = eventHandler;
47 }
48
MarkIsEventHandlerChanged(EventHandlerPtr eventHandler)49 void MMIClient::MarkIsEventHandlerChanged(EventHandlerPtr eventHandler)
50 {
51 CHKPV(eventHandler);
52 CHKPV(eventHandler_);
53 auto currentRunner = eventHandler_->GetEventRunner();
54 CHKPV(currentRunner);
55 auto newRunner = eventHandler->GetEventRunner();
56 CHKPV(newRunner);
57 isEventHandlerChanged_ = false;
58 if (currentRunner->GetRunnerThreadName() != newRunner->GetRunnerThreadName()) {
59 isEventHandlerChanged_ = true;
60 MMI_HILOGD("Event handler changed");
61 }
62 MMI_HILOGD("Current handler name:%{public}s, New handler name:%{public}s",
63 currentRunner->GetRunnerThreadName().c_str(), newRunner->GetRunnerThreadName().c_str());
64 }
65
SendMessage(const NetPacket & pkt) const66 bool MMIClient::SendMessage(const NetPacket &pkt) const
67 {
68 return SendMsg(pkt);
69 }
70
GetCurrentConnectedStatus() const71 bool MMIClient::GetCurrentConnectedStatus() const
72 {
73 return GetConnectedStatus();
74 }
75
GetSharedPtr()76 MMIClientPtr MMIClient::GetSharedPtr()
77 {
78 return shared_from_this();
79 }
80
Start()81 bool MMIClient::Start()
82 {
83 CALL_DEBUG_ENTER;
84 msgHandler_.Init();
85 auto callback = std::bind(&ClientMsgHandler::OnMsgHandler, &msgHandler_,
86 std::placeholders::_1, std::placeholders::_2);
87 if (!StartClient(callback)) {
88 MMI_HILOGE("Client startup failed");
89 Stop();
90 return false;
91 }
92 if (!StartEventRunner()) {
93 MMI_HILOGE("Start runner failed");
94 Stop();
95 return false;
96 }
97 MMI_HILOGD("Client started successfully");
98 return true;
99 }
100
StartEventRunner()101 bool MMIClient::StartEventRunner()
102 {
103 CALL_DEBUG_ENTER;
104 CHK_PID_AND_TID();
105 if (eventHandler_ == nullptr) {
106 auto runner = AppExecFwk::EventRunner::Create(THREAD_NAME);
107 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
108 MMI_HILOGI("Create event handler, thread name:%{public}s", runner->GetRunnerThreadName().c_str());
109 }
110
111 if (isConnected_ && fd_ >= 0) {
112 if (isListening_) {
113 MMI_HILOGI("File fd is in listening");
114 return true;
115 }
116 if (!AddFdListener(fd_)) {
117 MMI_HILOGE("Add fd listener failed");
118 return false;
119 }
120 } else {
121 if (!eventHandler_->PostTask(std::bind(&MMIClient::OnReconnect, this), CLIENT_RECONNECT_COOLING_TIME)) {
122 MMI_HILOGE("Send reconnect event failed");
123 return false;
124 }
125 }
126 return true;
127 }
128
AddFdListener(int32_t fd)129 bool MMIClient::AddFdListener(int32_t fd)
130 {
131 CALL_DEBUG_ENTER;
132 if (fd < 0) {
133 MMI_HILOGE("Invalid fd:%{public}d", fd);
134 return false;
135 }
136 CHKPF(eventHandler_);
137 auto fdListener = std::make_shared<MMIFdListener>(GetSharedPtr());
138 auto errCode = eventHandler_->AddFileDescriptorListener(fd, FILE_DESCRIPTOR_INPUT_EVENT, fdListener);
139 if (errCode != ERR_OK) {
140 MMI_HILOGE("Add fd listener failed,fd:%{public}d code:%{public}u str:%{public}s", fd, errCode,
141 GetErrorStr(errCode).c_str());
142 return false;
143 }
144 isRunning_ = true;
145 MMI_HILOGI("serverFd:%{public}d was listening,mask:%{public}u pid:%{public}d threadId:%{public}" PRIu64,
146 fd, FILE_DESCRIPTOR_INPUT_EVENT, GetPid(), GetThisThreadId());
147 return true;
148 }
149
DelFdListener(int32_t fd)150 bool MMIClient::DelFdListener(int32_t fd)
151 {
152 CALL_DEBUG_ENTER;
153 CHKPF(eventHandler_);
154 if (fd >= 0) {
155 eventHandler_->RemoveFileDescriptorListener(fd);
156 } else {
157 MMI_HILOGE("Invalid fd:%{public}d", fd);
158 }
159 auto runner = eventHandler_->GetEventRunner();
160 CHKPF(runner);
161 if (runner->GetRunnerThreadName() == THREAD_NAME) {
162 eventHandler_->RemoveAllEvents();
163 }
164 isRunning_ = false;
165 return true;
166 }
167
OnPacket(NetPacket & pkt)168 void MMIClient::OnPacket(NetPacket& pkt)
169 {
170 recvFun_(*this, pkt);
171 }
172
OnRecvMsg(const char * buf,size_t size)173 void MMIClient::OnRecvMsg(const char *buf, size_t size)
174 {
175 CHKPV(buf);
176 if (size == 0 || size > MAX_PACKET_BUF_SIZE) {
177 MMI_HILOGE("Invalid input param size. size:%{public}zu", size);
178 return;
179 }
180 if (!circBuf_.Write(buf, size)) {
181 MMI_HILOGW("Write data failed. size:%{public}zu", size);
182 }
183 OnReadPackets(circBuf_, std::bind(&MMIClient::OnPacket, this, std::placeholders::_1));
184 }
185
Reconnect()186 int32_t MMIClient::Reconnect()
187 {
188 return ConnectTo();
189 }
190
OnReconnect()191 void MMIClient::OnReconnect()
192 {
193 if (Reconnect() == RET_OK) {
194 MMI_HILOGI("Reconnect ok");
195 return;
196 }
197 CHKPV(eventHandler_);
198 if (!eventHandler_->PostTask(std::bind(&MMIClient::OnReconnect, this), CLIENT_RECONNECT_COOLING_TIME)) {
199 MMI_HILOGE("Post reconnect event failed");
200 }
201 }
202
OnDisconnect()203 void MMIClient::OnDisconnect()
204 {
205 OnDisconnected();
206 }
207
RegisterConnectedFunction(ConnectCallback fun)208 void MMIClient::RegisterConnectedFunction(ConnectCallback fun)
209 {
210 funConnected_ = fun;
211 }
212
RegisterDisconnectedFunction(ConnectCallback fun)213 void MMIClient::RegisterDisconnectedFunction(ConnectCallback fun)
214 {
215 funDisconnected_ = fun;
216 }
217
OnDisconnected()218 void MMIClient::OnDisconnected()
219 {
220 CALL_DEBUG_ENTER;
221 MMI_HILOGI("Disconnected from server, fd:%{public}d", fd_);
222 isConnected_ = false;
223 isListening_ = false;
224 if (funDisconnected_) {
225 funDisconnected_(*this);
226 }
227 if (!DelFdListener(fd_)) {
228 MMI_HILOGE("Delete fd listener failed");
229 }
230 Close();
231 if (!isExit && eventHandler_ != nullptr) {
232 if (!eventHandler_->PostTask(std::bind(&MMIClient::OnReconnect, this), CLIENT_RECONNECT_COOLING_TIME)) {
233 MMI_HILOGE("Send reconnect event task failed");
234 }
235 }
236 }
237
OnConnected()238 void MMIClient::OnConnected()
239 {
240 CALL_DEBUG_ENTER;
241 MMI_HILOGI("Connection to server succeeded, fd:%{public}d", GetFd());
242 isConnected_ = true;
243 msgHandler_.InitProcessedCallback();
244 if (funConnected_) {
245 funConnected_(*this);
246 }
247 if (!isExit && !isRunning_ && fd_ >= 0 && eventHandler_ != nullptr) {
248 if (!AddFdListener(fd_)) {
249 MMI_HILOGE("Add fd listener failed");
250 return;
251 }
252 isListening_ = true;
253 }
254 }
255
Socket()256 int32_t MMIClient::Socket()
257 {
258 CALL_DEBUG_ENTER;
259 int32_t ret = MultimodalInputConnMgr->AllocSocketPair(IMultimodalInputConnect::CONNECT_MODULE_TYPE_MMI_CLIENT);
260 if (ret != RET_OK) {
261 MMI_HILOGE("Call AllocSocketPair return %{public}d", ret);
262 return RET_ERR;
263 }
264 fd_ = MultimodalInputConnMgr->GetClientSocketFdOfAllocedSocketPair();
265 if (fd_ == IMultimodalInputConnect::INVALID_SOCKET_FD) {
266 MMI_HILOGE("Call GetClientSocketFdOfAllocedSocketPair return invalid fd");
267 } else {
268 MMI_HILOGD("Call GetClientSocketFdOfAllocedSocketPair return fd:%{public}d", fd_);
269 }
270 return fd_;
271 }
272
Stop()273 void MMIClient::Stop()
274 {
275 CALL_DEBUG_ENTER;
276 UDSClient::Stop();
277 if (eventHandler_ != nullptr) {
278 auto runner = eventHandler_->GetEventRunner();
279 CHKPV(runner);
280 if (runner->GetRunnerThreadName() == THREAD_NAME) {
281 runner->Stop();
282 eventHandler_->RemoveAllEvents();
283 eventHandler_->RemoveAllFileDescriptorListeners();
284 }
285 }
286 }
287
GetErrorStr(ErrCode code) const288 const std::string& MMIClient::GetErrorStr(ErrCode code) const
289 {
290 const static std::string defErrString = "Unknown event handler error!";
291 const static std::map<ErrCode, std::string> mapStrings = {
292 {ERR_OK, "ERR_OK."},
293 {EVENT_HANDLER_ERR_INVALID_PARAM, "Invalid parameters"},
294 {EVENT_HANDLER_ERR_NO_EVENT_RUNNER, "Have not set event runner yet"},
295 {EVENT_HANDLER_ERR_FD_NOT_SUPPORT, "Not support to listen file descriptors"},
296 {EVENT_HANDLER_ERR_FD_ALREADY, "File descriptor is already in listening"},
297 {EVENT_HANDLER_ERR_FD_FAILED, "Failed to listen file descriptor"},
298 {EVENT_HANDLER_ERR_RUNNER_NO_PERMIT, "No permit to start or stop deposited event runner"},
299 {EVENT_HANDLER_ERR_RUNNER_ALREADY, "Event runner is already running"}
300 };
301 auto it = mapStrings.find(code);
302 if (it != mapStrings.end()) {
303 return it->second;
304 }
305 return defErrString;
306 }
307 } // namespace MMI
308 } // namespace OHOS
309