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