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