精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

OpenHarmony 源碼解析之多模輸入子系統(tǒng)(事件派發(fā)流程)

系統(tǒng)
本文可以了解多模輸入系統(tǒng)事件派發(fā)的流程,以及多模輸入系統(tǒng)的接口和注入事件的流程,結(jié)合以上的源碼分析會(huì)對(duì)多模輸入子系統(tǒng)會(huì)有更深入的理解。

[[424563]]

想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):

51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)

https://harmonyos.51cto.com

簡(jiǎn)介

多模輸入系統(tǒng)主要用于接收按鍵,觸摸等輸入事件,并且會(huì)對(duì)這些原始輸入事件進(jìn)行處理,之后再對(duì)這些事件進(jìn)行派發(fā)。同時(shí)多模輸入系統(tǒng)還提供了注入事件的接口,應(yīng)用可以通過(guò)調(diào)用這個(gè)接口產(chǎn)生輸入事件,然后將該輸入事件注入到輸入系統(tǒng)中進(jìn)行處理。

OpenHarmony 源碼解析之多模輸入子系統(tǒng)(事件派發(fā)流程)-鴻蒙HarmonyOS技術(shù)社區(qū)

輸入系統(tǒng)框架

OpenHarmony 源碼解析之多模輸入子系統(tǒng)(事件派發(fā)流程)-鴻蒙HarmonyOS技術(shù)社區(qū)

多模輸入系統(tǒng)主要是由InputManagerService, InputEventHub, InputEventDistributer來(lái)負(fù)責(zé)處理的。InputManagerService會(huì)啟動(dòng)InputEventHub,并且會(huì)通過(guò)創(chuàng)建子線程的方式來(lái)創(chuàng)建InputEventDistributer。當(dāng)?shù)讓觽鱽?lái)按鍵或觸摸事件的時(shí)候,InputEventHub就會(huì)進(jìn)行讀取,并且會(huì)對(duì)這些原始的輸入事件進(jìn)行處理,處理完后會(huì)交給InputEventDistributer進(jìn)行派發(fā)。InputEventDistributer又會(huì)通過(guò)InputEventClientProxy進(jìn)行IPC交互的方式發(fā)給應(yīng)用端。

多模輸入系統(tǒng)事件派發(fā)流程

事件派發(fā)流程圖

OpenHarmony 源碼解析之多模輸入子系統(tǒng)(事件派發(fā)流程)-鴻蒙HarmonyOS技術(shù)社區(qū)

源碼分析

下面就對(duì)多模輸入系統(tǒng)事件派發(fā)流程的源碼進(jìn)行分析。

InputManagerService

\foundation\graphic\wms\services\wms\wms.cpp

  1. int main() 
  2.     DEBUG_PERFORMANCE_REGISTER_SIG(); 
  3.     OHOS::HiFbdevInit(); 
  4.     OHOS::GfxEngines::GetInstance()->InitDriver(); 
  5.     HOS_SystemInit(); 
  6.     OHOS::InputManagerService::GetInstance()->Run(); 
  7.     while (1) { 
  8.         DEBUG_PERFORMANCE_PRINT_RESULT(); 
  9.         OHOS::LiteWM::GetInstance()->MainTaskHandler(); 
  10.         usleep(WMS_MAIN_TASK_PERIOD_IN_US); 
  11.     } 

InputManagerService的啟動(dòng)是在WMS的main函數(shù)中通過(guò)InputManagerService::GetInstance()->Run()執(zhí)行的。

\foundation\graphic\wms\services\ims\input_manager_service.cpp

  1. void InputManagerService::Run() 
  2.     hub_ = InputEventHub::GetInstance(); 
  3.  
  4.     hub_->RegisterReadCallback(ReadCallback); 
  5.     hub_->SetUp(); 
  6.     distributerThreadCreated_ = pthread_create(&distributerThread_, nullptr, Distribute, nullptr); 
  7.     if (!distributerThreadCreated_) { 
  8.         pthread_detach(distributerThread_); 
  9.     } 

在InputManagerService::Run()中首先會(huì)創(chuàng)建InputEventHub的對(duì)象并通過(guò)RegisterReadCallback來(lái)注冊(cè)InputEventHub的回調(diào),然后通過(guò)SetUp來(lái)啟動(dòng)InputEventHub, InputEventHub主要是用于對(duì)底層原始輸入事件的讀取和處理,該函數(shù)的最后會(huì)創(chuàng)建distributerThread子線程,用于對(duì)輸入事件的派發(fā)。

InputEventHub

\foundation\graphic\wms\services\ims\input_event_hub.cpp

  1. void InputEventHub::SetUp() 
  2.     int32_t ret = GetInputInterface(&inputInterface_); 
  3.     if (ret != INPUT_SUCCESS) { 
  4.         GRAPHIC_LOGE("get input driver interface failed!"); 
  5.         return
  6.     } 
  7.     uint8_t num = ScanInputDevice(); 
  8.     if (num == 0) { 
  9.         GRAPHIC_LOGE("There is no device!"); 
  10.         return
  11.     } 
  12.     for (uint8_t i = 0; i < num; i++) { 
  13.         if (inputInterface_ == nullptr || inputInterface_->iInputManager == nullptr) { 
  14.             GRAPHIC_LOGE("input interface or input manager is nullptr, open device failed!"); 
  15.             return
  16.         } 
  17.         ret = inputInterface_->iInputManager->OpenInputDevice(mountDevIndex_[i]); 
  18.         if (ret == INPUT_SUCCESS && inputInterface_->iInputReporter != nullptr) { 
  19.             callback_.EventPkgCallback = EventCallback; 
  20.             ret = inputInterface_->iInputReporter->RegisterReportCallback(mountDevIndex_[i], &callback_); 
  21.             if (ret != INPUT_SUCCESS) { 
  22.                 GRAPHIC_LOGE("device dose not exist, can't register callback to it!"); 
  23.                 return
  24.             } 
  25.             openDev_ = openDev_ | (1 << i); 
  26.         } 
  27.     } 

在這個(gè)函數(shù)中InputEventHub主要的工作就是通過(guò)調(diào)用驅(qū)動(dòng)層的OpenInputDevice來(lái)打開輸入設(shè)備,并且會(huì)將EventCallback的回調(diào)函數(shù)通過(guò)驅(qū)動(dòng)層的RegisterReportCallback進(jìn)行注冊(cè)。當(dāng)?shù)讓佑惺录鬟f上來(lái),EventCallback就會(huì)被調(diào)用。OpenInputDevice和RegisterReportCallback具體實(shí)現(xiàn)分別是在drivers/peripheral/input/hal/src/input_manager.c和drivers/peripheral/input/hal/src/input_reporter.c中。

\foundation\graphic\wms\services\ims\input_event_hub.cpp

  1. void InputEventHub::EventCallback(const EventPackage **pkgs, uint32_t count, uint32_t devIndex) 
  2.     if (pkgs == nullptr || readCallback_ == nullptr || count == 0) { 
  3.         return
  4.     } 
  5.  
  6.     RawEvent& data = InputEventHub::GetInstance()->data_; 
  7.     for (uint32_t i = 0; i < count; i++) { 
  8.         if (pkgs[i]->type == EV_REL) { 
  9.             data.type = InputDevType::INDEV_TYPE_MOUSE; 
  10.             if (pkgs[i]->code == REL_X) 
  11.                 data.x += pkgs[i]->value; 
  12.             else if (pkgs[i]->code == REL_Y) 
  13.                 data.y += pkgs[i]->value; 
  14.         } else if (pkgs[i]->type == EV_ABS) { 
  15.             data.type = InputDevType::INDEV_TYPE_TOUCH; 
  16.             if (pkgs[i]->code == ABS_MT_POSITION_X) 
  17.                 data.x = pkgs[i]->value; 
  18.             else if (pkgs[i]->code == ABS_MT_POSITION_Y) 
  19.                 data.y = pkgs[i]->value; 
  20.         } else if (pkgs[i]->type == EV_KEY) { 
  21.             if (pkgs[i]->code == BTN_MOUSE || pkgs[i]->code == BTN_TOUCH) { 
  22.                 if (pkgs[i]->value == 0) 
  23.                     data.state = 0; 
  24.                 else if (pkgs[i]->value == 1) 
  25.                     data.state = 1; 
  26.             } 
  27.         } else if (pkgs[i]->type == EV_SYN) { 
  28.             if (pkgs[i]->code == SYN_REPORT) { 
  29.                 break; 
  30.             } 
  31.         } 
  32.     } 
  33.  
  34.     readCallback_(&data); 

當(dāng)?shù)讓佑休斎胧录蟻?lái)的話,EventCallback就會(huì)被調(diào)用,在這個(gè)函數(shù)里會(huì)通過(guò)EventPackage->type來(lái)判斷輸入事件的類型,其中

EV_REL是相對(duì)坐標(biāo)的輸入事件,比如軌跡球,鼠標(biāo)事件

EV_ABS是絕對(duì)坐標(biāo)的輸入事件,比如觸屏觸摸事件

EV_KEY是按鍵輸入事件,比如設(shè)備上的物理按鍵的點(diǎn)擊事件

EV_SYN是Motion的一系列動(dòng)作結(jié)束標(biāo)志位

如果是鼠標(biāo)事件,會(huì)將相對(duì)坐標(biāo)值放入到data.x和data.y中,如果是觸屏觸摸事件,會(huì)將在觸屏上觸摸的坐標(biāo)位置放入到data.x和data.y中,如果是按鍵事件會(huì)將按鍵的點(diǎn)擊狀態(tài)放入到data.state中。

處理完輸入事件后,會(huì)將數(shù)據(jù)放入到data中,并通過(guò)readCallback傳給InputManagerService進(jìn)行處理,之后就會(huì)調(diào)用InputManagerService::ReadCallback。

\foundation\graphic\wms\services\ims\input_manager_service.cpp

  1. void InputManagerService::ReadCallback(const RawEvent* event) 
  2.     if (event == nullptr) { 
  3.         return
  4.     } 
  5.     pthread_mutex_lock(&lock_); 
  6.     while (eventQueue_.size() == MAX_EVENT_SIZE) { 
  7.         pthread_cond_wait(&nonFull_, &lock_); 
  8.     } 
  9.     // push events into queue 
  10.     eventQueue_.push(event[0]); 
  11.     pthread_mutex_unlock(&lock_); 
  12.     pthread_cond_signal(&nonEmpty_); 
  13.  
  14. void* InputManagerService::Distribute(void* args) 
  15.     GRAPHIC_LOGI("InputManagerService::Distribute Ready to read distribute!"); 
  16.     while (true) { 
  17.         pthread_mutex_lock(&lock_); 
  18.         while (eventQueue_.size() == 0) { 
  19.             pthread_cond_wait(&nonEmpty_, &lock_); 
  20.         } 
  21.         // pop events from queue 
  22.         RawEvent events[MAX_INPUT_DEVICE_NUM]; 
  23.         int32_t len = (eventQueue_.size() > MAX_EVENT_SIZE) ? MAX_EVENT_SIZE : eventQueue_.size(); 
  24.         for (int32_t i = 0; i < len; i++) { 
  25.             events[i] = eventQueue_.front(); 
  26.             eventQueue_.pop(); 
  27.         } 
  28.         distributer_.Distribute(events, len); 
  29.         pthread_mutex_unlock(&lock_); 
  30.         pthread_cond_signal(&nonFull_); 
  31.     } 
  32.     return nullptr; 

ReadCallback這個(gè)函數(shù)首先會(huì)判斷eventQueue這個(gè)事件隊(duì)列里事件數(shù)量是否達(dá)到最大數(shù)量,如果達(dá)到最大數(shù)量該線程就一直等待,否則就會(huì)把該事件放到eventQueue這個(gè)事件隊(duì)列里,并且同時(shí)也會(huì)發(fā)出nonEmpty的signal, 來(lái)讓Distribute中的線程停止等待。

Distribute函數(shù)中,當(dāng)eventQueue隊(duì)列里沒有事件的時(shí)候,就會(huì)一直等待,當(dāng)有事件來(lái)的時(shí)候就會(huì)停止線程等待,然后會(huì)遍歷整個(gè)eventQueue這個(gè)隊(duì)列,把每個(gè)事件獲取出來(lái)后放入到events這個(gè)數(shù)組中,并做為參數(shù)放入到InputEventDistributer::Distribute中進(jìn)行事件的派發(fā)。

InputEventDistributer

\foundation\graphic\wms\services\ims\input_event_distributer.cpp

  1. void InputEventDistributer::Distribute(const RawEvent* events, int32_t size
  2.     for (int32_t i = 0; i < size; i++) { 
  3.         for (auto listener : rawEventListeners_) { 
  4.             if (listener != nullptr) { 
  5.                 listener->OnRawEvent(events[i]); 
  6.             } 
  7.         } 
  8.     } 

這個(gè)函數(shù)比較簡(jiǎn)單,主要就是遍歷所有的InputEventClientProxy, 并且調(diào)用各自的onRawEvent進(jìn)行實(shí)際的派發(fā)工作。

InputEventClientProxy

\foundation\graphic\wms\services\ims\input_event_client_proxy.cpp

  1. void InputEventClientProxy::OnRawEvent(const RawEvent& event) 
  2.     IpcIo io; 
  3.     uint8_t tmpData[IMS_DEFAULT_IPC_SIZE]; 
  4.     IpcIoInit(&io, tmpData, IMS_DEFAULT_IPC_SIZE, 1); 
  5.     IpcIoPushFlatObj(&io, static_cast<const void*>(&event), sizeof(RawEvent)); 
  6.     pthread_mutex_lock(&lock_); 
  7.     std::map<pid_t, ClientInfo>::iterator it; 
  8.     for (it = clientInfoMap_.begin(); it != clientInfoMap_.end(); it++) { 
  9.         if (it->second.alwaysInvoke || (event.state != lastState_)) { 
  10.             SendRequest(nullptr, it->second.svc, 0, &io, nullptr, LITEIPC_FLAG_ONEWAY, nullptr); 
  11.         } 
  12.     } 
  13.     lastState_ = event.state; 
  14.     pthread_mutex_unlock(&lock_); 

這個(gè)函數(shù)主要就是通過(guò)ipc的交互方式把輸入事件傳給應(yīng)用端。

到此整個(gè)多模輸入系統(tǒng)的事件派發(fā)流程就結(jié)束了。

多模輸入系統(tǒng)接口說(shuō)明

模塊

  1. /foundation/multimodalinput/input 
  2. ├── common                       # 公共代碼 
  3. ├── interfaces                   # 對(duì)外接口存放目錄 
  4. │   └── native                   # 對(duì)外native層接口存放目錄 
  5. │       └── innerkits            # 對(duì)系統(tǒng)內(nèi)部子系統(tǒng)提供native層接口存放目錄 
  6. ├── service                      # 服務(wù)框架代碼 
  7. ├── sa_profile                   # 服務(wù)啟動(dòng)配置文件 
  8. ├── uinput                       # 輸入事件注入模塊 

通過(guò)每個(gè)目錄下的.gn文件可以看到每個(gè)目錄下的模塊都對(duì)應(yīng)動(dòng)態(tài)庫(kù)

\interfaces\native\innerkits\event下的文件編出來(lái)的是mmi_event.so

\interfaces\native\innerkits\napi 下的文件編出來(lái)的是injecteventhandler.so

\interfaces\native\innerkits\proxy 下的文件編出來(lái)的是libmultimodalinput_proxy.so

\service 下的文件編出來(lái)的是libmultimodalinput_service.so

\uinput 下的文件編出來(lái)的是mmi_uinject.so

接口

多模輸入目前提供的接口為事件注入接口,該接口目前僅對(duì)系統(tǒng)應(yīng)用開放。

JS接口

InJectEventHandler是處理注入事件類。

\applications\standard\systemui\navigationBar\src\main\js\default\pages\backKey\backKey.js

  1. export default { 
  2.     /** 
  3.      * User start touching the back button 
  4.      */ 
  5.     backTouchStart() { 
  6.         mLog.showInfo(TAG, `back touch start`); 
  7.         res = input.injectEventSync({ 
  8.             isPressed: true
  9.             keyCode: 2, 
  10.             keyDownDuration: 1 
  11.         }); 
  12.         mLog.showInfo(TAG, `injectEventHandler injectEventSync down res: ${res}`); 
  13.     }, 
  14.     /** 
  15.      * User stop touching the back button 
  16.      * Trigger "Back" event 
  17.      */ 
  18.     backTouchEnd() { 
  19.         mLog.showInfo(TAG, `back touch end and injectEventHandler injectEventSync`); 
  20.         res = input.injectEventSync({ 
  21.             isPressed: false
  22.             keyCode: 2, 
  23.             keyDownDuration: 1 
  24.         }); 
  25.         mLog.showInfo(TAG, `injectEventHandler injectEventSync up res: ${res}`); 
  26.     } 

可以從openharmony systemui的navigationbar的源碼中看到, 當(dāng)點(diǎn)擊navigationbar的back鍵的時(shí)候,就會(huì)調(diào)用js的接口函數(shù)injectEventSync,并傳入三個(gè)參數(shù),其中

isPress: 按鍵的狀態(tài),true表示down, false表示up

keyCode:鍵值碼,2表示back事件

keyDownDuration:按鍵按下到抬起之間的時(shí)長(zhǎng),單位ms,1表示1ms

C++接口

系統(tǒng)內(nèi)部接口

在\interfaces\native\innerkits\events\include下的頭文件都定義了各自對(duì)內(nèi)部系統(tǒng)調(diào)用的口。

KeyEvent的主要接口

KeyBoardEvent的主要接口

ManipulationEvent的主要接口

MmiPoint的主要接口

MouseEvent的主要接口

MultimodalEvent的主要接口

StylusEvent的主要接口

TouchEvent的主要接口

InjectEvent的實(shí)現(xiàn)邏輯

\foundation\multimodalinput\input\interfaces\native\innerkits\napi\src\key_event_handler.cpp

  1. static napi_value InjectEventSync(napi_env env, napi_callback_info info) 
  2.     size_t argc = 2; 
  3.     napi_value args[2] = { 0 }; 
  4.     napi_value thisArg = nullptr; 
  5.     void* data = nullptr; 
  6.     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisArg, &data)); 
  7.     napi_value eventObject = args[0]; 
  8.     int32_t ret = IsMatchType(eventObject, napi_object, env); 
  9.     if (ret) { 
  10.         return GetNapiInt32_t(ret, env); 
  11.     } 
  12.     napi_value isPressed, keyCode, keyDownDuration; 
  13.     napi_get_named_property(env, eventObject, "isPressed", &isPressed); 
  14.     napi_get_named_property(env, eventObject, "keyDownDuration", &keyDownDuration); 
  15.     napi_get_named_property(env, eventObject, "keyCode", &keyCode); 
  16.     if (IsMatchType(isPressed, napi_boolean, env) || IsMatchType(keyCode, napi_number, env) 
  17.         || IsMatchType(keyDownDuration, napi_number, env)) { 
  18.         return GetNapiInt32_t(-1, env); 
  19.     } 
  20.     OHOS::KeyProperty keyProperty = { 
  21.         .isPressed = GetCppBool(isPressed, env), 
  22.         .keyCode = GetCppInt32_t(keyCode, env), 
  23.         .keyDownDuration = GetCppInt32_t(keyDownDuration, env), 
  24.     }; 
  25.     OHOS::MultimodalProperty multimodalProperty { 
  26.         .highLevelEvent = 1, 
  27.         .uuid = "11111"
  28.         .sourceType = 1, 
  29.         .occurredTime = 1, 
  30.         .deviceId = "11111"
  31.         .inputDeviceId = 1, 
  32.         .isHighLevelEvent = true
  33.     }; 
  34.     OHOS::sptr<OHOS::KeyEvent> event = new OHOS::KeyEvent(); 
  35.     if (!event) { 
  36.         return GetNapiInt32_t(-1, env); 
  37.     } 
  38.     event->Initialize(multimodalProperty, keyProperty); 
  39.     std::shared_ptr<OHOS::InjectManager> injectManager = OHOS::InjectManager::GetInstance(); 
  40.     bool isSucceed = injectManager->InjectEvent(event); 
  41.     if (!isSucceed) { 
  42.         return GetNapiInt32_t(-1, env); 
  43.     } 
  44.     return GetNapiInt32_t(0, env); 

在key_event_handler.cpp中實(shí)現(xiàn)了InjectEventSync這個(gè)接口,通過(guò)NAPI獲得應(yīng)用端的isPressed,KeyDownDuration,KeyCode這三個(gè)數(shù)值,并將這三個(gè)參數(shù)放入到KeyProperty這個(gè)結(jié)構(gòu)體中。然后調(diào)用KeyEvent的Initialize,將KeyProperty封裝到KeyEvent中,最后再調(diào)用InjectManager的InjectEvent。

\foundation\multimodalinput\input\interfaces\native\innerkits\proxy\src\inject_manager.cpp

  1. bool InjectManager::InjectEvent(const sptr<MultimodalEvent> event) 
  2.     std::lock_guard<std::mutex> guard(lock_); 
  3.     if (!multimodalInputService_) { 
  4.         return false
  5.     } 
  6.  
  7.     int32_t result = multimodalInputService_->InjectEvent(event); 
  8.     if (result == 0) { 
  9.         return true
  10.     } 
  11.  
  12.     MMI_LOGI("inject failed"); 
  13.     return false

foundation\multimodalinput\input\interfaces\native\innerkits\proxy\include\inject_manager.h

  1. sptr<IMultimodalInputService> multimodalInputService_{nullptr}; 

multimodalInputService_->InjectEvent其實(shí)是一個(gè)IPC進(jìn)程間調(diào)用,這會(huì)調(diào)用到客戶端的MultimodalInputServiceProxy的InjectEvent。

foundation\multimodalinput\input\interfaces\native\innerkits\proxy\src\multimodal_input_service_proxy.cpp

  1. int32_t MultimodalInputServiceProxy::InjectEvent(const sptr<MultimodalEvent> &event) 
  2.     MessageParcel data; 
  3.     MessageParcel reply; 
  4.     MessageOption option(MessageOption::TF_ASYNC); 
  5.     if (!data.WriteInterfaceToken(MultimodalInputServiceProxy::GetDescriptor())) { 
  6.         HiLog::Error(LABEL, "write descriptor fail"); 
  7.         return ERR_INVALID_VALUE; 
  8.     } 
  9.  
  10.     if (!data.WriteInt32(MultimodalEvent::KEYBOARD)) { 
  11.         HiLog::Error(LABEL, "write descriptor fail"); 
  12.         return ERR_INVALID_VALUE; 
  13.     } 
  14.  
  15.     if (!data.WriteParcelable(event)) { 
  16.         HiLog::Error(LABEL, "inject event fail, write event error"); 
  17.         return ERR_INVALID_VALUE; 
  18.     } 
  19.     int error = Remote()->SendRequest(INJECT_EVENT, data, reply, option); 
  20.     if (error != ERR_NONE) { 
  21.         HiLog::Error(LABEL, "inject event fail, error: %{public}d", error); 
  22.     } 
  23.     return error; 

在MultimodalInputServiceProxy::InjectEvent會(huì)通過(guò)SendRequest向服務(wù)端MultimodalInputServiceStub發(fā)送數(shù)據(jù)。

foundation\multimodalinput\input\service\src\multimodal_input_service_stub.cpp

  1. int MultimodalInputServiceStub::OnRemoteRequest( 
  2.     uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option
  3.     MMI_LOGD("OnReceived, cmd = %{public}u", code); 
  4.     if (!IsPermissionValid()) { 
  5.         MMI_LOGE("calling app not acquired multimodal permission"); 
  6.         return MMI_PERMISSION_ERR; 
  7.     } 
  8.  
  9.     std::u16string myDescripter = MultimodalInputServiceStub::GetDescriptor(); 
  10.     std::u16string remoteDescripter = data.ReadInterfaceToken(); 
  11.     if (myDescripter != remoteDescripter) { 
  12.         MMI_LOGE("descriptor checked fail"); 
  13.         return MMI_BAD_TYPE; 
  14.     } 
  15.  
  16.     switch (code) { 
  17.         case INJECT_EVENT: { 
  18.             int32_t type = data.ReadInt32(); 
  19.             if (type == MultimodalEvent::KEYBOARD) { 
  20.                 sptr<MultimodalEvent> event = data.ReadParcelable<KeyEvent>(); 
  21.                 return InjectEvent(event); 
  22.             } 
  23.             MMI_LOGE("recv bad type %{public}d", type); 
  24.             return MMI_BAD_TYPE; 
  25.         } 
  26.         default: { 
  27.             MMI_LOGE("default case, need check"); 
  28.             return IPCObjectStub::OnRemoteRequest(code, data, reply, option); 
  29.         } 
  30.     } 

通過(guò)sendRequest將數(shù)據(jù)發(fā)送之后,服務(wù)端的MultimodalInputServiceStub的OnRemoteRequest就會(huì)被調(diào)用,最終會(huì)調(diào)用MultimodaInputService的InjectEvent。

\foundation\multimodalinput\input\service\src\multimodal_input_service.cpp

  1. int32_t MultimodalInputService::InjectEvent(const sptr<MultimodalEvent> &event) 
  2.     KeyEvent *eventPtr = reinterpret_cast<KeyEvent*>(event.GetRefPtr()); 
  3.     int keycode = eventPtr->GetKeyCode(); 
  4.     int state = 0; 
  5.     if (eventPtr->IsKeyDown()) { 
  6.         state = 1; 
  7.     } else { 
  8.         state = 0; 
  9.     } 
  10.     MMIS::KeyboardInject &inject = OHOS::MMIS::KeyboardInject::GetInstance(); 
  11.     MMI_LOGD("InjectEvent keycode %{public}d, state %{public}d", keycode, state); 
  12.     inject.InjectKeyEvent(keycode, state); 
  13.     return 0; 

MultimodaInputService的InjectEvent實(shí)際上會(huì)調(diào)用KeyboardInject的InjectKeyEvent,從函數(shù)的實(shí)現(xiàn)來(lái)看,目前只使用了KeyboardInject,也就是說(shuō)目前只支持鍵盤事件的注入。

\foundation\multimodalinput\input\uinput\keyboard_inject.cpp

  1. void KeyboardInject::InjectKeyEvent(uint16_t code, uint32_t value) const 
  2.     std::lock_guard<std::mutex> keyboardLock(mutex_); 
  3.     auto it = keyCodeMap_.find(code); 
  4.     if (it == keyCodeMap_.end()) { 
  5.         return
  6.     } 
  7.     InjectInputEvent injectInputEvent = {injectThread_->KEYBOARD_DEVICE_ID, EV_KEY, it->second, value}; 
  8.     injectThread_->WaitFunc(injectInputEvent); 
  9.     InjectInputEvent injectInputSync = {injectThread_->KEYBOARD_DEVICE_ID, EV_SYN, SYN_REPORT, 0}; 
  10.     injectThread_->WaitFunc(injectInputSync); 

在InjectKeyEvent中會(huì)通過(guò)InjectInputEvent的WaitFunc將注入事件繼續(xù)向下注入。

\foundation\multimodalinput\input\uinput\inject_thread.cpp

  1. void InjectThread::InjectFunc() const 
  2.     std::unique_lock<std::mutex> uniqueLock(mutex_); 
  3.     while (true) { 
  4.         conditionVariable_.wait(uniqueLock); 
  5.         while (injectQueue_.size() > 0) { 
  6.             if (injectQueue_[0].deviceId == TOUCH_SCREEN_DEVICE_ID) { 
  7.                 g_pTouchScreen->EmitEvent(injectQueue_[0].type, injectQueue_[0].code, injectQueue_[0].value); 
  8.             } else if (injectQueue_[0].deviceId == KEYBOARD_DEVICE_ID) { 
  9.                 g_pKeyboard->EmitEvent(injectQueue_[0].type, injectQueue_[0].code, injectQueue_[0].value); 
  10.             } 
  11.             injectQueue_.erase(injectQueue_.begin()); 
  12.         } 
  13.     } 
  14.  
  15. void InjectThread::WaitFunc(InjectInputEvent injectInputEvent) const 
  16.     std::lock_guard<std::mutex> lockGuard(mutex_); 
  17.     injectQueue_.push_back(injectInputEvent); 
  18.     conditionVariable_.notify_one(); 

在WaitFunc中會(huì)將injectInputEvent放入到injectQueue這個(gè)隊(duì)列中,這個(gè)隊(duì)列是用來(lái)存放injectInputEvent的,并且通過(guò)notify_one來(lái)喚醒InjectThread,由于目前只支持鍵盤類型事件的注入,所有只會(huì)調(diào)用g_pKeyboard->EmitEven(),g_pKeyboard是VirtualKeyboard的對(duì)象,VirtualKeyboard又繼承自VirtualDevice,因此最終會(huì)調(diào)用VirtualKeyboard的EmitEvent。

foundation\multimodalinput\input\uinput\virtual_device.cpp

  1. bool VirtualDevice::EmitEvent(uint16_t type, uint16_t code, uint32_t value) const 
  2.     struct input_event event {}; 
  3.     event.type = type; 
  4.     event.code = code; 
  5.     event.value = value; 
  6. #ifndef __MUSL__ 
  7.     gettimeofday(&event.timeNULL); 
  8. #endif 
  9.     if (write(fd_, &event, sizeof(event)) < static_cast<ssize_t>(sizeof(event))) { 
  10.         HiLog::Error(LABEL, "Event write failed %{public}s aborting", __func__); 
  11.         return false
  12.     } 
  13.     return true
  14.  
  15. bool VirtualDevice::SetUp() 
  16.     fd_ = open("/dev/uinput", O_WRONLY | O_NONBLOCK); 

在該函數(shù)中會(huì)將這個(gè)注入事件寫入到文件描述符為fd_的設(shè)備文件中,從SetUp的函數(shù)中可以看出實(shí)際是寫入到/dev/uinput這個(gè)設(shè)備文件中。

到此多模輸入系統(tǒng)接口的介紹以及InjectEvent整個(gè)注入事件的流程就結(jié)束了。

總結(jié)

通過(guò)本文的學(xué)習(xí)可以了解多模輸入系統(tǒng)事件派發(fā)的流程,以及多模輸入系統(tǒng)的接口和注入事件的流程,結(jié)合以上的源碼分析會(huì)對(duì)多模輸入子系統(tǒng)會(huì)有更深入的理解。

想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):

51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)

https://harmonyos.51cto.com

 

責(zé)任編輯:jianghua 來(lái)源: 鴻蒙社區(qū)
相關(guān)推薦

2023-04-06 09:14:11

多模輸入子系統(tǒng)鴻蒙

2021-09-13 15:15:18

鴻蒙HarmonyOS應(yīng)用

2023-06-28 15:00:02

開源鴻蒙輸入系統(tǒng)架構(gòu)

2021-11-08 15:04:47

鴻蒙HarmonyOS應(yīng)用

2022-01-06 16:17:58

鴻蒙HarmonyOS應(yīng)用

2021-09-18 14:40:37

鴻蒙HarmonyOS應(yīng)用

2022-02-17 20:57:07

OpenHarmon操作系統(tǒng)鴻蒙

2021-12-17 16:42:09

鴻蒙HarmonyOS應(yīng)用

2023-04-12 15:31:11

系統(tǒng)服務(wù)管理鴻蒙

2022-01-10 15:30:11

鴻蒙HarmonyOS應(yīng)用

2022-05-10 11:17:27

電話子系統(tǒng)數(shù)據(jù)服務(wù)模塊

2021-11-18 10:28:03

鴻蒙HarmonyOS應(yīng)用

2022-05-24 15:46:51

Wi-FiSTA模式

2022-01-20 14:33:29

openharmonwayland協(xié)議鴻蒙

2022-01-13 10:11:59

鴻蒙HarmonyOS應(yīng)用

2022-05-20 10:32:49

事件循環(huán)器事件隊(duì)列鴻蒙

2022-06-07 10:33:29

Camera組件鴻蒙

2022-05-30 15:08:33

包管理子系統(tǒng)包安裝模塊

2022-01-20 11:04:31

Linux DRMOpenHarmon鴻蒙

2022-03-18 16:07:04

Graphic子系統(tǒng)鴻蒙
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

国产主播精品| 男女啪啪999亚洲精品| 91最新地址在线播放| 57pao国产精品一区| 国产一二三四五区| av一级久久| 亚洲v中文字幕| 亚洲国产欧美不卡在线观看 | 欧美日韩黄色大片| 日韩精品福利视频| 国产av一区二区三区精品| 国产精品日韩精品欧美精品| 在线看欧美日韩| 韩国三级hd中文字幕有哪些| 在线天堂资源| 亚洲伦理在线精品| 国产视频一区二区不卡| 在线不卡免费视频| 亚洲欧美成人综合| 欧美精品在线免费| 超碰人人人人人人人| 精品网站aaa| 制服丝袜激情欧洲亚洲| 国产肥臀一区二区福利视频| 动漫一区在线| 国产亚洲欧美一级| 国产视频不卡| 性生活视频软件| 久久激情五月激情| 日韩av不卡在线| 日韩免费一级片| 综合天天久久| 精品国内亚洲在观看18黄 | av天堂永久资源网| 亚洲www色| 国产精品对白交换视频 | 999久久久91| 亚洲欧洲在线免费| www.88av| 国产精品网在线观看| 日韩一区和二区| 在线不卡一区二区三区| 色猫猫成人app| 色88888久久久久久影院野外| 免费不卡av在线| 羞羞视频在线观看不卡| 综合自拍亚洲综合图不卡区| 亚洲欧美精品| 在线免费观看黄色网址| 国产欧美精品国产国产专区| 任我爽在线视频精品一| 男男激情在线| 久久精品一区二区三区不卡 | 国产精品av网站| 九九精品免费视频| 久久www成人_看片免费不卡| 97av在线影院| 97久久久久久久| 日韩视频中文| 欧美重口另类videos人妖| 久久露脸国语精品国产91| 亚洲茄子视频| 欧美亚洲在线视频| 欧美超碰在线观看| 免费在线看成人av| 91精品国产综合久久香蕉最新版 | 国产精品白丝av| 亚洲一区二区三区毛片| a级片免费观看| 成人综合在线观看| 精品免费国产| 国产在线网站| 亚洲欧洲成人精品av97| 国产成人精品免费看在线播放| 国产日产一区二区三区| 亚洲一区二区三区中文字幕在线| 黄色大片中文字幕| 亚洲黄色免费看| 欧美视频一区二区三区在线观看 | 亚洲国产一区二区久久| 欧美一区二区三区在线| 极品白嫩少妇无套内谢| 欧洲在线一区| 深夜精品寂寞黄网站在线观看| 久久一级免费视频| 亚洲视频一二| 国产精品 欧美在线| 91尤物国产福利在线观看| 国产麻豆欧美日韩一区| 国产一区二区黄色| av在线中文| 夜色激情一区二区| 激情五月开心婷婷| 国产精区一区二区| 亚洲精品国产精品久久清纯直播| 日本乱子伦xxxx| 女同性一区二区三区人了人一| 91国内免费在线视频| 中文av免费观看| 成人国产电影网| 日韩中文一区| 97超碰在线免费| 欧美日韩黄色影视| 亚洲婷婷在线观看| 色综合色综合| 欧美一区二区色| 国产视频手机在线| 久久精品一区二区| av无码久久久久久不卡网站| 国模私拍国内精品国内av| 精品国产99国产精品| 免费网站在线高清观看| 亚洲手机在线| 91日本在线视频| 欧美精品久久久久久久久久丰满| 亚洲免费在线观看视频| 丰满少妇在线观看| 国产成人高清精品免费5388| 日韩中文字幕在线免费观看| 日本中文在线播放| 国产成人一级电影| 亚洲欧美日韩综合一区| 亚洲天堂电影| 亚洲国产精品久久91精品| 激情无码人妻又粗又大| 久久xxxx精品视频| 国产欧美在线一区二区| 中文字幕免费高清电视剧网站在线观看| 韩曰欧美视频免费观看| 日本精品一二三区| 中文精品电影| 成人两性免费视频| 99精品老司机免费视频| 欧美天堂在线观看| 催眠调教后宫乱淫校园| 亚洲最新av| 成人精品视频99在线观看免费| 国产永久免费高清在线观看 | 国产日韩久久久| 26uuu精品一区二区三区四区在线| 欧美少妇一区二区三区| 午夜不卡一区| 日韩视频精品在线| 在线观看免费中文字幕| 国产精品三级久久久久三级| 91淫黄看大片| 欧美亚洲精品在线| 国产精品v片在线观看不卡| 青青青草原在线| 欧美日韩国产页| 一本色道久久综合亚洲精品图片| 亚洲影视在线| 日本欧美精品久久久| 成人动漫一区| 亚洲欧美中文日韩在线| 最近免费中文字幕大全免费版视频| av男人天堂一区| 国产精品va无码一区二区| 日韩精品福利一区二区三区| 欧美在线xxx| 精华区一区二区三区| 色噜噜狠狠成人中文综合| 日本一区二区视频在线播放| 免费在线观看视频一区| 麻豆中文字幕在线观看| 精品国产乱码一区二区三区| 久久91精品国产91久久久| 午夜精品久久久久久久96蜜桃| 亚洲综合色网站| 亚洲久久久久久| 日韩av二区在线播放| 亚洲一区二区在| 玖玖玖电影综合影院| 国产69精品99久久久久久宅男| 天堂在线视频免费| 色婷婷综合久久久中文字幕| 免费看91的网站| 国内精品久久久久影院色| 777久久精品一区二区三区无码 | 日韩精品中文字| 久久影视中文字幕| 亚洲欧美日本韩国| 国产精品久久久久久亚洲av| 可以看av的网站久久看| 中文字幕精品一区日韩| 国产精品乱战久久久| 热99精品里视频精品| 日本免费在线观看| 亚洲大胆人体视频| 中文字幕免费高清网站| 一区二区三区在线高清| 欧美熟妇一区二区| 国产中文一区二区三区| 日本a在线免费观看| 成人免费看片39| 国产在线一区二| 欧洲亚洲精品久久久久| 午夜精品福利在线观看| 在线国产91| 亚洲精品福利视频| 国产精品九九九九| 欧美日韩中文字幕在线| 男人与禽猛交狂配| 久久精品日韩一区二区三区| 中文字幕久久久久久久| 丝袜美腿高跟呻吟高潮一区| 男人c女人视频| 精品久久综合| 国产三区二区一区久久| 国产午夜精品一区在线观看| 国产mv久久久| 24小时免费看片在线观看| 日韩亚洲综合在线| 欧美伦理影视网| 精品国产百合女同互慰| 国产乱码精品一区二区三区精东| 色悠悠亚洲一区二区| 国产精彩视频在线观看| 亚洲男帅同性gay1069| 亚洲ⅴ国产v天堂a无码二区| 99久久99久久精品免费看蜜桃| 国产男女无遮挡猛进猛出| 日韩电影在线一区二区| 日本网站免费在线观看| 欧美久久99| av磁力番号网| 欧美顶级大胆免费视频| 亚洲电影免费| 精品国产一级毛片| 蜜桃臀一区二区三区| 久久中文字幕导航| 国产成人免费电影| 欧洲一区在线| 91国产在线播放| 精品国产麻豆| 91免费人成网站在线观看18| 成人不卡视频| 国产精品日韩专区| 欧美国产日韩电影| 日韩美女激情视频| 写真福利精品福利在线观看| 欧美亚洲成人免费| 蜜桃视频在线网站| 欧美一级高清免费播放| 日本aa在线| 久久久爽爽爽美女图片| 女人黄色免费在线观看| 色综合视频网站| 免费毛片在线看片免费丝瓜视频| 免费不卡在线观看av| a视频在线观看| 欧美黄网免费在线观看| 久草在线资源站资源站| 欧美激情亚洲激情| 55av亚洲| 国产成+人+综合+亚洲欧洲| 激情开心成人网| 国产精品第100页| 亚洲人成网站在线在线观看| 91亚洲人电影| 91亚洲精品视频在线观看| 国产伦精品一区二区三区照片| 国产伦精品一区二区三区免费优势| 电影午夜精品一区二区三区| 国产精品毛片av| 欧美日韩高清在线一区| 欧美日韩国产一区二区三区不卡 | 日本www在线| 欧美精品少妇videofree| 污视频在线免费观看网站| 久久久久久久久国产| 午夜久久中文| 国产欧美精品一区二区| 无码国模国产在线观看| 久久久一本精品99久久精品| 精品高清在线| 国产卡一卡二在线| 在线国产精品一区| 能在线观看的av网站| 精品一区二区三区影院在线午夜| 天天操夜夜操很很操| 91在线观看高清| 国产传媒在线看| 亚洲午夜免费视频| 天堂网一区二区| 日韩一级片在线播放| 奇米影视888狠狠狠777不卡| 日韩一区二区精品视频| 波多一区二区| 国产精品永久在线| 精品自拍偷拍| 一区二区三区四区不卡| 亚洲黄网站黄| 久久这里只精品| eeuss国产一区二区三区| 国产一区二区三区精品在线| 一片黄亚洲嫩模| 中文字幕+乱码+中文| 欧美成人一区二区三区在线观看| 男人天堂亚洲二区| 欧美黑人视频一区| 粉嫩av一区二区三区四区五区| 99精彩视频在线观看免费| 自拍亚洲一区| www.av毛片| 国产美女一区二区三区| 久久只有这里有精品| 亚洲最大的成人av| 在线观看免费高清视频| 精品小视频在线| 色www永久免费视频首页在线| 国产精品电影网站| 欧美大奶一区二区| 久久久久久av无码免费网站下载| 日韩在线一二三区| 国产又粗又长又爽| 一区二区三区精品视频| 中文av免费观看| 亚洲日本欧美日韩高观看| 欧美人与性动交α欧美精品济南到 | 亚洲高清在线播放| 国产亚洲亚洲| 男人的天堂影院| 亚洲精品一卡二卡| 91中文字幕在线视频| 亚洲欧洲一区二区三区在线观看| 丁香影院在线| 97免费资源站| 午夜国产一区二区| 国产喷水theporn| 国产情人综合久久777777| 99久久精品国产亚洲| 亚洲成人在线网| free性欧美| 国产伦精品一区二区三区高清版 | 99国产精品欲| 日韩一区在线视频| 国产原创一区| 正在播放亚洲| 狠狠狠色丁香婷婷综合激情| 亚洲欧美综合7777色婷婷| 欧美三级资源在线| 91在线观看| 成人黄色激情网| 99久久九九| 69久久精品无码一区二区| 亚洲欧美另类小说| 国产夫绿帽单男3p精品视频| 久久国产加勒比精品无码| 国产成人免费视频网站视频社区| 中文字幕一区二区三区有限公司 | 欧美双性人妖o0| 午夜电影网亚洲视频| 特级丰满少妇一级aaaa爱毛片| 97婷婷涩涩精品一区| 少妇一区二区三区| 992kp快乐看片永久免费网址| 中文av字幕一区| 国产一区二区在线视频聊天| 欧美精品做受xxx性少妇| 风间由美一区二区av101| 欧美久久久久久久久久久久久| 97se亚洲国产综合自在线| 国产精品免费精品一区| 揄拍成人国产精品视频| 亚洲成人高清| 欧美大黑帍在线播放| 北岛玲一区二区三区四区| 可以免费在线观看的av| 这里只有精品视频在线| 国产精品久久免费视频| 男的插女的下面视频| 久久久噜噜噜久噜久久综合| 一级黄色片在线观看| 欧美丰满老妇厨房牲生活| 久久久久影视| 无码少妇一区二区三区芒果| 亚洲男人的天堂在线观看| 香蕉视频免费看| 国产精品啪视频| 亚洲性人人天天夜夜摸| 精品成人av一区二区三区| 欧美日本一道本| 2021中文字幕在线| 五月天丁香综合久久国产| 国产精品99精品久久免费| av资源免费观看| 久久精品视频中文字幕| 欧美交a欧美精品喷水| 日本 片 成人 在线| 亚洲国产成人av| 最新av网站在线观看| 国产成人亚洲欧美| 日韩精品高清不卡| 欧美高清视频一区二区三区| 亚洲人成网站在线播| 韩国一区二区三区视频| www日韩视频| 亚洲国产视频一区| 日韩免费网站|