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