• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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     if (eventHandler == nullptr) {
47         MMI_HILOGW("eventHandler is null");
48         return;
49     }
50     // use the new thread untill eventhandler use poll thread
51     eventHandler_ = eventHandler;
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_INFO_TRACE;
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     bool selfCreateEventHandle = false;
116     if (USE_ISOLATE_DISPATCH_THREAD || eventHandler_ == nullptr || !USE_FILE_DESCRIPTION) {
117         MMI_HILOGI("USE_ISOLATE_DISPATCH_THREAD:%{public}d, eventHandler_:%{public}d",
118             USE_ISOLATE_DISPATCH_THREAD, (eventHandler_ == nullptr));
119         auto runner = AppExecFwk::EventRunner::Create(THREAD_NAME);
120         eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
121         eventHandler_->PostTask([this] { this->SetScheduler(); });
122         selfCreateEventHandle = true;
123     }
124 
125     auto runner = eventHandler_->GetEventRunner();
126     MMI_HILOGI("Current event handler, thread name:%{public}s",
127         runner->GetRunnerThreadName().c_str());
128     if (isConnected_ && fd_ >= 0) {
129         if (isListening_) {
130             MMI_HILOGI("File fd is in listening");
131             return true;
132         }
133         if (!AddFdListener(fd_, selfCreateEventHandle)) {
134             MMI_HILOGE("Add fd listener failed");
135             return false;
136         }
137     } else {
138         if (!eventHandler_->PostTask([this] { return this->OnReconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) {
139             MMI_HILOGE("Send reconnect event failed");
140             return false;
141         }
142     }
143     return true;
144 }
145 
AddFdListener(int32_t fd,bool selfCreate)146 bool MMIClient::AddFdListener(int32_t fd, bool selfCreate)
147 {
148     CALL_DEBUG_ENTER;
149     if (fd < 0) {
150         MMI_HILOGE("Invalid fd:%{public}d", fd);
151         return false;
152     }
153     CHKPF(eventHandler_);
154     auto fdListener = std::make_shared<MMIFdListener>(GetSharedPtr());
155     if (!USE_ISOLATE_DISPATCH_THREAD && !selfCreate && USE_FILE_DESCRIPTION) {
156         fdListener->SetDeamonWaiter();
157     }
158 
159     auto errCode = eventHandler_->AddFileDescriptorListener(fd, FILE_DESCRIPTOR_INPUT_EVENT, fdListener, "MMITask",
160         AppExecFwk::EventQueue::Priority::VIP);
161     if (errCode != ERR_OK) {
162         MMI_HILOGE("Add fd listener failed,fd:%{public}d code:%{public}u str:%{public}s", fd, errCode,
163             GetErrorStr(errCode).c_str());
164         return false;
165     }
166     isRunning_ = true;
167     MMI_HILOGI("Server was listening");
168     return true;
169 }
170 
DelFdListener(int32_t fd)171 bool MMIClient::DelFdListener(int32_t fd)
172 {
173     CALL_DEBUG_ENTER;
174     CHKPF(eventHandler_);
175     if (fd >= 0) {
176         eventHandler_->RemoveFileDescriptorListener(fd);
177         MMI_HILOGI("Remove file descriptor listener success");
178     } else {
179         MMI_HILOGE("Invalid fd:%{public}d", fd);
180     }
181     eventHandler_->RemoveAllEvents();
182     MMI_HILOGI("Remove all events success");
183     isRunning_ = false;
184     return true;
185 }
186 
OnPacket(NetPacket & pkt)187 void MMIClient::OnPacket(NetPacket& pkt)
188 {
189     recvFun_(*this, pkt);
190 }
191 
OnRecvMsg(const char * buf,size_t size)192 void MMIClient::OnRecvMsg(const char *buf, size_t size)
193 {
194     CHKPV(buf);
195     if (size == 0 || size > MAX_PACKET_BUF_SIZE) {
196         MMI_HILOGE("Invalid input param size. size:%{public}zu", size);
197         return;
198     }
199     if (!circBuf_.Write(buf, size)) {
200         MMI_HILOGW("Write data failed. size:%{public}zu", size);
201     }
202     OnReadPackets(circBuf_, [this] (NetPacket& pkt) { return this->OnPacket(pkt); });
203 }
204 
Reconnect()205 int32_t MMIClient::Reconnect()
206 {
207     if (ConnectTo() != RET_OK) {
208         MMI_HILOGE("Client connection failed");
209         return RET_ERR;
210     }
211     if (funConnected_) {
212         funConnected_(*this);
213     }
214     return RET_OK;
215 }
216 
OnReconnect()217 void MMIClient::OnReconnect()
218 {
219     if (Reconnect() == RET_OK) {
220         MMI_HILOGI("Reconnect ok");
221         return;
222     }
223     CHKPV(eventHandler_);
224     if (!eventHandler_->PostTask([this] { return this->OnReconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) {
225         MMI_HILOGE("Post reconnect event failed");
226     }
227 }
228 
OnDisconnect()229 void MMIClient::OnDisconnect()
230 {
231     OnDisconnected();
232 }
233 
RegisterConnectedFunction(ConnectCallback fun)234 void MMIClient::RegisterConnectedFunction(ConnectCallback fun)
235 {
236     funConnected_ = fun;
237 }
238 
RegisterDisconnectedFunction(ConnectCallback fun)239 void MMIClient::RegisterDisconnectedFunction(ConnectCallback fun)
240 {
241     funDisconnected_ = fun;
242 }
243 
OnDisconnected()244 void MMIClient::OnDisconnected()
245 {
246     CALL_DEBUG_ENTER;
247     MMI_HILOGI("Disconnected from server, fd:%{public}d", fd_);
248     isConnected_ = false;
249     isListening_ = false;
250     ANRHDL->ResetAnrArray();
251     if (funDisconnected_) {
252         funDisconnected_(*this);
253     }
254     if (!DelFdListener(fd_)) {
255         MMI_HILOGE("Delete fd listener failed");
256     }
257     Close();
258     if (!isExit && eventHandler_ != nullptr) {
259         if (!eventHandler_->PostTask([this] { return this->OnReconnect(); }, CLIENT_RECONNECT_COOLING_TIME)) {
260             MMI_HILOGE("Send reconnect event task failed");
261         }
262     }
263 }
264 
OnConnected()265 void MMIClient::OnConnected()
266 {
267     CALL_DEBUG_ENTER;
268     MMI_HILOGI("Connection to server succeeded, fd:%{public}d", GetFd());
269     isConnected_ = true;
270     msgHandler_.InitProcessedCallback();
271     if (!isExit && !isRunning_ && fd_ >= 0 && eventHandler_ != nullptr) {
272         if (!AddFdListener(fd_)) {
273             MMI_HILOGE("Add fd listener failed");
274             return;
275         }
276         isListening_ = true;
277     }
278 }
279 
Socket()280 int32_t MMIClient::Socket()
281 {
282     CALL_DEBUG_ENTER;
283     int32_t ret =
284         MULTIMODAL_INPUT_CONNECT_MGR->AllocSocketPair(MultimodalInputConnectManager::CONNECT_MODULE_TYPE_MMI_CLIENT);
285     if (ret != RET_OK) {
286         MMI_HILOGE("Call AllocSocketPair return %{public}d", ret);
287         return MultimodalInputConnectManager::INVALID_SOCKET_FD;
288     }
289     fd_ = MULTIMODAL_INPUT_CONNECT_MGR->GetClientSocketFdOfAllocedSocketPair();
290     if (fd_ == MultimodalInputConnectManager::INVALID_SOCKET_FD) {
291         MMI_HILOGE("Call GetClientSocketFdOfAllocedSocketPair return invalid fd");
292     } else {
293         MMI_HILOGD("Call GetClientSocketFdOfAllocedSocketPair return fd:%{public}d", fd_);
294     }
295     fdsan_exchange_owner_tag(fd_, 0, TAG);
296     return fd_;
297 }
298 
GetEventHandler() const299 EventHandlerPtr MMIClient::GetEventHandler() const
300 {
301     CHKPP(eventHandler_);
302     return eventHandler_;
303 }
304 
Stop()305 void MMIClient::Stop()
306 {
307     CALL_DEBUG_ENTER;
308     UDSClient::Stop();
309     if (eventHandler_ != nullptr) {
310         auto runner = eventHandler_->GetEventRunner();
311         CHKPV(runner);
312         if (runner->GetRunnerThreadName() == THREAD_NAME) {
313             runner->Stop();
314             eventHandler_->RemoveAllEvents();
315             eventHandler_->RemoveAllFileDescriptorListeners();
316             MMI_HILOGI("Remove all file descriptor listeners success");
317         }
318     }
319 }
320 
GetErrorStr(ErrCode code) const321 const std::string& MMIClient::GetErrorStr(ErrCode code) const
322 {
323     const static std::string defErrString = "Unknown event handler error!";
324     const static std::map<ErrCode, std::string> mapStrings = {
325         {ERR_OK, "ERR_OK."},
326         {EVENT_HANDLER_ERR_INVALID_PARAM, "Invalid parameters"},
327         {EVENT_HANDLER_ERR_NO_EVENT_RUNNER, "Have not set event runner yet"},
328         {EVENT_HANDLER_ERR_FD_NOT_SUPPORT, "Not support to listen file descriptors"},
329         {EVENT_HANDLER_ERR_FD_ALREADY, "File descriptor is already in listening"},
330         {EVENT_HANDLER_ERR_FD_FAILED, "Failed to listen file descriptor"},
331         {EVENT_HANDLER_ERR_RUNNER_NO_PERMIT, "No permit to start or stop deposited event runner"},
332         {EVENT_HANDLER_ERR_RUNNER_ALREADY, "Event runner is already running"}
333     };
334     auto it = mapStrings.find(code);
335     if (it != mapStrings.end()) {
336         return it->second;
337     }
338     return defErrString;
339 }
340 } // namespace MMI
341 } // namespace OHOS
342