• 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 "multimodal_event_handler.h"
17 
18 #include <fstream>
19 
20 #include "cJSON.h"
21 #include "config_policy_utils.h"
22 
23 #include "event_log_helper.h"
24 #include "input_manager_impl.h"
25 #include "mmi_client.h"
26 #include "multimodal_input_connect_manager.h"
27 #include "proto.h"
28 #include "tablet_event_input_subscribe_manager.h"
29 #include "pre_monitor_manager.h"
30 #include "util.h"
31 
32 #undef MMI_LOG_DOMAIN
33 #define MMI_LOG_DOMAIN MMI_LOG_HANDLER
34 #undef MMI_LOG_TAG
35 #define MMI_LOG_TAG "MultimodalEventHandler"
36 
37 namespace OHOS {
38 namespace MMI {
39 namespace {
40 constexpr int32_t MIN_MULTI_TOUCH_POINT_NUM { 0 };
41 constexpr int32_t MAX_MULTI_TOUCH_POINT_NUM { 10 };
42 constexpr int32_t UNKNOWN_MULTI_TOUCH_POINT_NUM { -1 };
43 constexpr std::uintmax_t MAX_SIZE_OF_INPUT_PRODUCT_CONFIG { 4096 };
44 }
45 
OnConnected(const IfMMIClient & client)46 void OnConnected(const IfMMIClient& client)
47 {
48     CALL_DEBUG_ENTER;
49     InputMgrImpl.OnConnected();
50     INPUT_DEVICE_IMPL.OnConnected();
51 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
52     KeyEventInputSubscribeMgr.OnConnected();
53 #endif // OHOS_BUILD_ENABLE_KEYBOARD
54 #ifdef OHOS_BUILD_ENABLE_SWITCH
55     SWITCH_EVENT_INPUT_SUBSCRIBE_MGR.OnConnected();
56 #endif // OHOS_BUILD_ENABLE_SWITCH
57     TABLET_EVENT_INPUT_SUBSCRIBE_MGR.OnConnected();
58 #ifdef OHOS_BUILD_ENABLE_MONITOR
59     IMonitorMgr.OnConnected();
60     PRE_MONITOR_MGR.OnConnected();
61 #endif // OHOS_BUILD_ENABLE_MONITOR
62 #ifdef OHOS_BUILD_ENABLE_INTERCEPTOR
63     InputInterMgr->OnConnected();
64 #endif // OHOS_BUILD_ENABLE_INTERCEPTOR
65     INPUT_ACTIVE_SUBSCRIBE_MGR.OnConnected();
66     DEVICE_CONSUMER.OnConnected();
67 }
68 
OnDisconnected(const IfMMIClient & client)69 void OnDisconnected(const IfMMIClient &client)
70 {
71     CALL_DEBUG_ENTER;
72     InputMgrImpl.OnDisconnected();
73     INPUT_DEVICE_IMPL.OnDisconnected();
74 #ifdef OHOS_BUILD_ENABLE_MONITOR
75     IMonitorMgr.OnDisconnected();
76 #endif // OHOS_BUILD_ENABLE_MONITOR
77 }
78 
MultimodalEventHandler()79 MultimodalEventHandler::MultimodalEventHandler() {}
~MultimodalEventHandler()80 MultimodalEventHandler::~MultimodalEventHandler() {}
81 
82 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
SubscribeKeyEvent(const KeyEventInputSubscribeManager::SubscribeKeyEventInfo & subscribeInfo)83 int32_t MultimodalEventHandler::SubscribeKeyEvent(
84     const KeyEventInputSubscribeManager::SubscribeKeyEventInfo &subscribeInfo)
85 {
86     CALL_DEBUG_ENTER;
87     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
88     return MULTIMODAL_INPUT_CONNECT_MGR->SubscribeKeyEvent(subscribeInfo.GetSubscribeId(),
89         subscribeInfo.GetKeyOption());
90 }
91 
UnsubscribeKeyEvent(int32_t subscribeId)92 int32_t MultimodalEventHandler::UnsubscribeKeyEvent(int32_t subscribeId)
93 {
94     CALL_DEBUG_ENTER;
95     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
96     return MULTIMODAL_INPUT_CONNECT_MGR->UnsubscribeKeyEvent(subscribeId);
97 }
98 
SubscribeHotkey(const KeyEventInputSubscribeManager::SubscribeKeyEventInfo & subscribeInfo)99 int32_t MultimodalEventHandler::SubscribeHotkey(
100     const KeyEventInputSubscribeManager::SubscribeKeyEventInfo &subscribeInfo)
101 {
102     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
103     return MULTIMODAL_INPUT_CONNECT_MGR->SubscribeHotkey(
104         subscribeInfo.GetSubscribeId(), subscribeInfo.GetKeyOption());
105 }
106 
UnsubscribeHotkey(int32_t subscribeId)107 int32_t MultimodalEventHandler::UnsubscribeHotkey(int32_t subscribeId)
108 {
109     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
110     return MULTIMODAL_INPUT_CONNECT_MGR->UnsubscribeHotkey(subscribeId);
111 }
112 
InjectEvent(const std::shared_ptr<KeyEvent> keyEvent,bool isNativeInject)113 int32_t MultimodalEventHandler::InjectEvent(const std::shared_ptr<KeyEvent> keyEvent, bool isNativeInject)
114 {
115     CALL_DEBUG_ENTER;
116     CHKPR(keyEvent, ERROR_NULL_POINTER);
117     EndLogTraceId(keyEvent->GetId());
118     keyEvent->UpdateId();
119     LogTracer lt(keyEvent->GetId(), keyEvent->GetEventType(), keyEvent->GetKeyAction());
120     if (keyEvent->GetKeyCode() < 0) {
121         if (EventLogHelper::IsBetaVersion()) {
122             MMI_HILOGE("KeyCode is invalid:%{private}u", keyEvent->GetKeyCode());
123         }
124         return RET_ERR;
125     }
126     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
127     int32_t ret = MULTIMODAL_INPUT_CONNECT_MGR->InjectKeyEvent(keyEvent, isNativeInject);
128     if (ret != 0) {
129         MMI_HILOGE("Send to server failed, ret:%{public}d", ret);
130         return RET_ERR;
131     }
132     return RET_OK;
133 }
134 #endif // OHOS_BUILD_ENABLE_KEYBOARD
135 
136 #ifdef OHOS_BUILD_ENABLE_KEY_PRESSED_HANDLER
SubscribeKeyMonitor(const KeyMonitorOption & keyOption)137 int32_t MultimodalEventHandler::SubscribeKeyMonitor(const KeyMonitorOption &keyOption)
138 {
139     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
140     return MULTIMODAL_INPUT_CONNECT_MGR->SubscribeKeyMonitor(keyOption);
141 }
142 
UnsubscribeKeyMonitor(const KeyMonitorOption & keyOption)143 int32_t MultimodalEventHandler::UnsubscribeKeyMonitor(const KeyMonitorOption &keyOption)
144 {
145     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
146     return MULTIMODAL_INPUT_CONNECT_MGR->UnsubscribeKeyMonitor(keyOption);
147 }
148 #endif // OHOS_BUILD_ENABLE_KEY_PRESSED_HANDLER
149 
150 #ifdef OHOS_BUILD_ENABLE_SWITCH
SubscribeSwitchEvent(int32_t subscribeId,int32_t switchType)151 int32_t MultimodalEventHandler::SubscribeSwitchEvent(int32_t subscribeId, int32_t switchType)
152 {
153     CALL_DEBUG_ENTER;
154     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
155     return MULTIMODAL_INPUT_CONNECT_MGR->SubscribeSwitchEvent(subscribeId, switchType);
156 }
157 
UnsubscribeSwitchEvent(int32_t subscribeId)158 int32_t MultimodalEventHandler::UnsubscribeSwitchEvent(int32_t subscribeId)
159 {
160     CALL_DEBUG_ENTER;
161     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
162     return MULTIMODAL_INPUT_CONNECT_MGR->UnsubscribeSwitchEvent(subscribeId);
163 }
164 #endif // OHOS_BUILD_ENABLE_SWITCH
165 
SubscribeTabletProximity(int32_t subscribeId)166 int32_t MultimodalEventHandler::SubscribeTabletProximity(int32_t subscribeId)
167 {
168     CALL_DEBUG_ENTER;
169     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
170     return MULTIMODAL_INPUT_CONNECT_MGR->SubscribeTabletProximity(subscribeId);
171 }
172 
UnsubscribetabletProximity(int32_t subscribeId)173 int32_t MultimodalEventHandler::UnsubscribetabletProximity(int32_t subscribeId)
174 {
175     CALL_DEBUG_ENTER;
176     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
177     return MULTIMODAL_INPUT_CONNECT_MGR->UnsubscribetabletProximity(subscribeId);
178 }
179 
SubscribeLongPressEvent(int32_t subscribeId,const LongPressRequest & longPressRequest)180 int32_t MultimodalEventHandler::SubscribeLongPressEvent(int32_t subscribeId,
181     const LongPressRequest &longPressRequest)
182 {
183     CALL_DEBUG_ENTER;
184     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
185     return MULTIMODAL_INPUT_CONNECT_MGR->SubscribeLongPressEvent(subscribeId, longPressRequest);
186 }
187 
UnsubscribeLongPressEvent(int32_t subscribeId)188 int32_t MultimodalEventHandler::UnsubscribeLongPressEvent(int32_t subscribeId)
189 {
190     CALL_DEBUG_ENTER;
191     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
192     return MULTIMODAL_INPUT_CONNECT_MGR->UnsubscribeLongPressEvent(subscribeId);
193 }
194 
InitClient(EventHandlerPtr eventHandler)195 bool MultimodalEventHandler::InitClient(EventHandlerPtr eventHandler)
196 {
197     CALL_DEBUG_ENTER;
198     std::lock_guard<std::mutex> guard(mtx_);
199     if (client_ != nullptr) {
200         if (eventHandler != nullptr) {
201             client_->MarkIsEventHandlerChanged(eventHandler);
202         }
203         return true;
204     }
205     client_ = std::make_shared<MMIClient>();
206     client_->SetEventHandler(eventHandler);
207     client_->RegisterConnectedFunction(&OnConnected);
208     client_->RegisterDisconnectedFunction(&OnDisconnected);
209     if (!client_->Start()) {
210         client_ = nullptr;
211         MMI_HILOGE("The client fails to start");
212         return false;
213     }
214     EventHandlerPtr eventHandlerPtr = client_->GetEventHandler();
215     CHKPF(eventHandlerPtr);
216     if (!eventHandlerPtr->PostTask([this] { SetClientInfo(GetPid(), GetThisThreadId()); })) {
217         MMI_HILOGE("Send reconnect event failed");
218         return false;
219     }
220     return true;
221 }
222 
GetMMIClient()223 MMIClientPtr MultimodalEventHandler::GetMMIClient()
224 {
225     std::lock_guard<std::mutex> guard(mtx_);
226     CHKPP(client_);
227     return client_->GetSharedPtr();
228 }
229 
230 #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)
InjectPointerEvent(std::shared_ptr<PointerEvent> pointerEvent,bool isNativeInject,int32_t useCoordinate)231 int32_t MultimodalEventHandler::InjectPointerEvent(std::shared_ptr<PointerEvent> pointerEvent, bool isNativeInject,
232     int32_t useCoordinate)
233 {
234     CHKPR(pointerEvent, ERROR_NULL_POINTER);
235     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
236     int32_t ret = MULTIMODAL_INPUT_CONNECT_MGR->InjectPointerEvent(pointerEvent, isNativeInject, useCoordinate);
237     if (ret != 0) {
238         MMI_HILOGE("Send to server failed, ret:%{public}d", ret);
239         return RET_ERR;
240     }
241     return RET_OK;
242 }
243 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
244 
245 #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)
InjectTouchPadEvent(std::shared_ptr<PointerEvent> pointerEvent,const TouchpadCDG & touchpadCDG,bool isNativeInject)246 int32_t MultimodalEventHandler::InjectTouchPadEvent(std::shared_ptr<PointerEvent> pointerEvent,
247     const TouchpadCDG &touchpadCDG, bool isNativeInject)
248 {
249     CHKPR(pointerEvent, ERROR_NULL_POINTER);
250     EventLogHelper::PrintEventData(pointerEvent, MMI_LOG_HEADER);
251     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
252     int32_t ret = MULTIMODAL_INPUT_CONNECT_MGR->InjectTouchPadEvent(pointerEvent, touchpadCDG, isNativeInject);
253     if (ret != 0) {
254         MMI_HILOGE("Send to server failed, ret:%{public}d", ret);
255         return RET_ERR;
256     }
257     return RET_OK;
258 }
259 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
260 
261 #if defined(OHOS_BUILD_ENABLE_POINTER) && defined(OHOS_BUILD_ENABLE_POINTER_DRAWING)
MoveMouseEvent(int32_t offsetX,int32_t offsetY)262 int32_t MultimodalEventHandler::MoveMouseEvent(int32_t offsetX, int32_t offsetY)
263 {
264     CALL_DEBUG_ENTER;
265     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
266     int32_t ret = MULTIMODAL_INPUT_CONNECT_MGR->MoveMouseEvent(offsetX, offsetY);
267     if (ret != 0) {
268         MMI_HILOGE("Send to server failed, ret:%{public}d", ret);
269         return RET_ERR;
270     }
271     return RET_OK;
272 }
273 #endif // OHOS_BUILD_ENABLE_POINTER && OHOS_BUILD_ENABLE_POINTER_DRAWING
274 
Authorize(bool isAuthorize)275 int32_t MultimodalEventHandler::Authorize(bool isAuthorize)
276 {
277     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
278     int32_t ret = MULTIMODAL_INPUT_CONNECT_MGR->Authorize(isAuthorize);
279     if (ret != RET_OK) {
280         MMI_HILOGE("Send to server failed, ret:%{public}d", ret);
281         return RET_ERR;
282     }
283     return RET_OK;
284 }
285 
CancelInjection()286 int32_t MultimodalEventHandler::CancelInjection()
287 {
288     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
289     int32_t ret = MULTIMODAL_INPUT_CONNECT_MGR->CancelInjection();
290     if (ret != RET_OK) {
291         MMI_HILOGE("Send to server failed, ret:%{public}d", ret);
292         return RET_ERR;
293     }
294     return RET_OK;
295 }
296 
SetClientInfo(int32_t pid,uint64_t readThreadId)297 int32_t MultimodalEventHandler::SetClientInfo(int32_t pid, uint64_t readThreadId)
298 {
299     CALL_DEBUG_ENTER;
300     CHKPR(MULTIMODAL_INPUT_CONNECT_MGR, RET_ERR);
301     return MULTIMODAL_INPUT_CONNECT_MGR->SetClientInfo(pid, readThreadId);
302 }
303 
ReadMaxTouchPoints(cJSON * jsonProductCfg,int32_t & maxMultiTouchPointNum)304 static void ReadMaxTouchPoints(cJSON *jsonProductCfg, int32_t &maxMultiTouchPointNum)
305 {
306     if (!cJSON_IsObject(jsonProductCfg)) {
307         MMI_HILOGE("Not json format");
308         return;
309     }
310     cJSON *jsonTouchscreen = cJSON_GetObjectItemCaseSensitive(jsonProductCfg, "touchscreen");
311     if (!cJSON_IsObject(jsonTouchscreen)) {
312         MMI_HILOGE("The jsonTouchscreen is not object");
313         return;
314     }
315     cJSON *jsonMaxTouchPoints = cJSON_GetObjectItemCaseSensitive(jsonTouchscreen, "MaxTouchPoints");
316     if (!cJSON_IsNumber(jsonMaxTouchPoints)) {
317         MMI_HILOGE("The jsonMaxTouchPoints is not number");
318         return;
319     }
320     auto sMaxTouchPoints = std::unique_ptr<char, std::function<void(char *)>>(
321         cJSON_Print(jsonMaxTouchPoints),
322         [](char *sMaxTouchPoints) {
323             if (sMaxTouchPoints != nullptr) {
324                 cJSON_free(sMaxTouchPoints);
325             }
326         });
327     CHKPV(sMaxTouchPoints);
328     MMI_HILOGI("Config of touchscreen.MaxTouchPoints:%{public}s", sMaxTouchPoints.get());
329     if (!IsInteger(sMaxTouchPoints.get())) {
330         MMI_HILOGE("Config of touchscreen.MaxTouchPoints is not integer");
331         return;
332     }
333     auto num = static_cast<int32_t>(cJSON_GetNumberValue(jsonMaxTouchPoints));
334     if ((num < MIN_MULTI_TOUCH_POINT_NUM) || (num > MAX_MULTI_TOUCH_POINT_NUM)) {
335         MMI_HILOGW("Invalid config: MaxTouchPoints(%{public}d) is out of range[%{public}d, %{public}d]",
336             num, MIN_MULTI_TOUCH_POINT_NUM, MAX_MULTI_TOUCH_POINT_NUM);
337         return;
338     }
339     maxMultiTouchPointNum = num;
340     MMI_HILOGI("touchscreen.MaxTouchPoints:%{public}d", maxMultiTouchPointNum);
341 }
342 
ReadMaxTouchPoints(std::ifstream & ifs,int32_t & maxMultiTouchPointNum)343 static void ReadMaxTouchPoints(std::ifstream &ifs, int32_t &maxMultiTouchPointNum)
344 {
345     std::string cfg { std::istream_iterator<char>(ifs), std::istream_iterator<char>() };
346     auto jsonProductCfg = std::unique_ptr<cJSON, std::function<void(cJSON *)>>(
347         cJSON_Parse(cfg.c_str()),
348         [](cJSON *productCfg) {
349             if (productCfg != nullptr) {
350                 cJSON_Delete(productCfg);
351             }
352         });
353     CHKPV(jsonProductCfg);
354     ReadMaxTouchPoints(jsonProductCfg.get(), maxMultiTouchPointNum);
355 }
356 
ReadMaxTouchPoints(const char * cfgPath,int32_t & maxMultiTouchPointNum)357 static void ReadMaxTouchPoints(const char *cfgPath, int32_t &maxMultiTouchPointNum)
358 {
359     std::error_code ec {};
360     auto fsize = std::filesystem::file_size(cfgPath, ec);
361     if (ec || (fsize > MAX_SIZE_OF_INPUT_PRODUCT_CONFIG)) {
362         MMI_HILOGE("Unexpected size of InputProductConfig");
363         return;
364     }
365     std::ifstream ifs(cfgPath);
366     if (!ifs.is_open()) {
367         MMI_HILOGE("Can not open config");
368         return;
369     }
370     ReadMaxTouchPoints(ifs, maxMultiTouchPointNum);
371     ifs.close();
372 }
373 
ReadMaxMultiTouchPointNum(int32_t & maxMultiTouchPointNum)374 void MultimodalEventHandler::ReadMaxMultiTouchPointNum(int32_t &maxMultiTouchPointNum)
375 {
376     maxMultiTouchPointNum = -1;
377     char cfgName[] { "etc/input/input_product_config.json" };
378     char buf[MAX_PATH_LEN] {};
379     char *cfgPath = ::GetOneCfgFile(cfgName, buf, sizeof(buf));
380     if (cfgPath == nullptr) {
381         MMI_HILOGE("No input product config was found");
382         return;
383     }
384     auto realPath = std::unique_ptr<char, std::function<void(char *)>>(
385         ::realpath(cfgPath, nullptr),
386         [](auto arr) {
387             if (arr != nullptr) {
388                 ::free(arr);
389             }
390         });
391     if (realPath == nullptr) {
392         MMI_HILOGI("No input product config");
393         return;
394     }
395     ReadMaxTouchPoints(realPath.get(), maxMultiTouchPointNum);
396 }
397 
GetMaxMultiTouchPointNum(int32_t & pointNum)398 int32_t MultimodalEventHandler::GetMaxMultiTouchPointNum(int32_t &pointNum)
399 {
400     static int32_t maxMultiTouchPointNum { UNKNOWN_MULTI_TOUCH_POINT_NUM };
401     static std::once_flag flag;
402 
403     std::call_once(flag, []() {
404         ReadMaxMultiTouchPointNum(maxMultiTouchPointNum);
405     });
406     if (maxMultiTouchPointNum < 0) {
407         pointNum = UNKNOWN_MULTI_TOUCH_POINT_NUM;
408         return MMI_ERR_NO_PRODUCT_CONFIG;
409     }
410     pointNum = maxMultiTouchPointNum;
411     return RET_OK;
412 }
413 } // namespace MMI
414 } // namespace OHOS
415