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