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