精品欧美一区二区三区在线观看 _久久久久国色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)

亚洲av无码一区二区三区dv| 蜜臀av午夜精品久久| 小h片在线观看| 欧美国产日产图区| 91视频在线免费观看| 欧美激情黑白配| 香蕉国产精品| 亚洲免费福利视频| 三区视频在线观看| 特黄毛片在线观看| 亚洲精品视频在线| 日韩欧美精品一区二区三区经典| 国产99999| 视频一区中文字幕国产| 欧美激情免费看| 日本乱子伦xxxx| 国产精品极品国产中出| 欧美人xxxx| 人妻少妇被粗大爽9797pw| 国产精品剧情一区二区在线观看| 97se狠狠狠综合亚洲狠狠| 91精品久久久久久久久久入口| 国产成人在线免费视频| 一区二区影视| 日日骚久久av| 日韩精品卡通动漫网站| aaa国产精品| 91精品久久久久久久久99蜜臂| 国产精品97在线| av老司机免费在线| 亚洲精品国产无天堂网2021 | 亚洲精品日产精品乱码不卡| 欧美一区二区综合| 十九岁完整版在线观看好看云免费| 国产一区二区免费看| 国产精品美乳一区二区免费| 久久99国产综合精品免费| 一区精品久久| 欧美激情精品久久久久久免费印度 | 羞羞色院91蜜桃| 久久国产精品久久w女人spa| 欧美激情欧美激情| 久久久久久激情| 欧美精品99| 欧美成人黄色小视频| 免费看一级大片| 亚洲国产精品日韩专区av有中文| 宅男66日本亚洲欧美视频| 精品无码国产污污污免费网站| 欧美电影免费网站| 日韩av在线一区| 麻豆国产精品一区| 亚洲婷婷影院| 伊人久久久久久久久久久久久| 蜜桃精品一区二区| 中文字幕伦av一区二区邻居| 国产亚洲精品日韩| 国产成人免费观看网站| 日韩激情在线| 久久久精品日本| 99久久婷婷国产综合| 欧美不卡视频| 欧美多人乱p欧美4p久久| 国产亚洲欧美精品久久久www| 欧美日本不卡| 高清一区二区三区四区五区| 成人精品在线看| 肉肉av福利一精品导航| 国产精品久久久久久久久久久久| 超碰在线观看91| 精品午夜一区二区三区在线观看| 91久久久久久久| 亚洲成人第一区| 99精品热视频| 日韩av不卡播放| 二区在线播放| 亚洲午夜视频在线观看| 欧美一区二区中文字幕| 日韩毛片免费观看| 欧美日韩精品一区二区三区| 欧美性猛交xx| 日韩精品免费一区二区三区竹菊| 亚洲网站在线播放| 成年人午夜剧场| 亚洲一区日本| 国产女精品视频网站免费| www.我爱av| 久久综合久久久久88| 亚洲三级一区| av资源中文在线天堂| 欧美亚洲综合网| 亚洲欧美日韩中文字幕在线观看| 天海翼亚洲一区二区三区| 在线性视频日韩欧美| 久久国产精品波多野结衣av| 亚洲女优在线| 亚洲精品日韩激情在线电影| 视频一区二区三区在线看免费看| 国产精品毛片无遮挡高清| 久青草视频在线播放| 国产另类xxxxhd高清| 日韩欧美电影一二三| 日韩女同一区二区三区 | 久久免费视频3| 日韩精品第二页| 亚洲精品成人久久| 久久av红桃一区二区禁漫| 亚洲精品1区| 成人xvideos免费视频| 深夜福利免费在线观看| 亚洲欧美精品午睡沙发| 一级黄色香蕉视频| 久久夜色精品国产噜噜av小说| 中文字幕欧美精品在线| 国产精品久久久久久久妇| 国产在线精品一区二区| 日韩尤物视频| 国产白浆在线免费观看| 日韩欧美成人一区二区| 林心如三级全黄裸体| 先锋影音久久久| 福利视频久久| 2024最新电影免费在线观看| 欧美三区在线观看| 新91视频在线观看| 99精品视频免费观看视频| 懂色一区二区三区av片| av色图一区| 日本电影亚洲天堂一区| 亚洲中文字幕一区| 亚洲黄色精品| 成人av中文| 日本在线视频网址| 欧美一区二区三区系列电影| 91禁男男在线观看| 奇米色777欧美一区二区| 欧美1o一11sex性hdhd| 精品丝袜在线| 日韩成人网免费视频| 精品深夜av无码一区二区老年| 国产一区二区三区久久悠悠色av| 亚洲精品一区国产精品| 岛国精品在线| 中文字幕精品一区久久久久| 91视频在线视频| 国产女主播视频一区二区| 国产精品亚洲二区在线观看 | 亚洲精品永久www嫩草| 成人在线观看免费视频| 色婷婷**av毛片一区| 中文字幕 欧美激情| 欧美国产精品中文字幕| 手机在线成人免费视频| 色综合天天爱| 91九色视频导航| 污污的视频在线观看| 日韩精品自拍偷拍| 日本中文字幕在线免费观看| 99久久久久久| 国产精品免费观看久久| 欧美日韩黑人| 成人激情视频免费在线| 超碰超碰在线| 亚洲第一国产精品| 国产高潮久久久| 国产色婷婷亚洲99精品小说| 日韩av在线中文| 自拍视频亚洲| 国产嫩草一区二区三区在线观看| 51av在线| 国产一级揄自揄精品视频| 亚洲网站免费观看| 一区二区三区av电影 | 日韩精品福利一区二区三区| 日韩美女视频免费在线观看| 3p在线观看| 日韩免费电影网站| 丁香六月婷婷综合| 日本一二三四高清不卡| xxxxwww一片| 亚洲一区二区毛片| 在线一区高清| 欧美理论电影在线精品| 国产欧美日韩91| 99热99re6国产在线播放| 亚洲欧美色婷婷| 国产视频www| 色综合久久久网| 内射一区二区三区| 91麻豆.com| 三级黄色片播放| 久久久久免费| 国产制服91一区二区三区制服| 秋霞在线一区| 亚洲精品日韩av| 91精品影视| 欧美激情亚洲自拍| av在线中文| 亚洲精品99久久久久| 在线观看av大片| 亚洲图片欧美一区| sm捆绑调教视频| 99视频有精品| 中文字幕一区二区在线观看视频| 亚洲一区二区成人| 欧美a级免费视频| 日韩av二区| 久久国产精品-国产精品| 国产精品一区三区在线观看| 国产成人精品优优av| 欧美人与牲禽动交com| 日韩中文字幕在线看| 欧美另类自拍| 亚洲精品一区二区三区蜜桃下载| 国产又粗又黄视频| 色成年激情久久综合| 日本一二三区不卡| 一区二区三区在线观看国产 | 91亚洲国产| 欧美国产二区| 久久香蕉精品香蕉| 超碰97网站| 亚洲国产视频二区| 成人一区二区电影| 欧美成人aaa| 国产精品九九九| 黄色综合网址| 欧美与欧洲交xxxx免费观看| av影院在线| 欧美激情亚洲另类| 国产精品69xx| 色与欲影视天天看综合网| а天堂中文在线官网| 久久夜色精品亚洲噜噜国产mv| av中文字幕在线| 中文字幕日韩av| 婷婷在线视频观看| 日韩天堂在线视频| 亚洲成a人v欧美综合天堂麻豆| 亚洲人高潮女人毛茸茸| 男人天堂网在线观看| 亚洲欧美日韩一区二区在线 | 久久久久久99精品| 蜜桃传媒一区二区亚洲av| 99热在这里有精品免费| 精品少妇人妻av一区二区三区| 国产成人亚洲综合a∨婷婷| 在线免费黄色小视频| 国产成人免费视频网站| 扒开伸进免费视频| 99视频精品全部免费在线| 国产精品久久无码| 久久久电影一区二区三区| 非洲一级黄色片| 国产精品进线69影院| 三级在线观看免费大全| 亚洲美女免费在线| 国产精品1000| 色妞www精品视频| 中文字幕+乱码+中文| 欧美日韩精品免费观看视频| 国产精品乱码一区二区| 日韩视频一区二区| 熟妇人妻中文av无码| 日韩电影免费在线观看中文字幕| 日韩精品系列| 色综合影院在线| 成人在线免费看黄| 国内成人精品一区| 超碰国产一区| 成人妇女免费播放久久久| 涩爱av色老久久精品偷偷鲁| 国产一区二区黄色| 精品国产乱码久久久久久果冻传媒| 亚洲黄色成人久久久| 欧美国产91| 狠狠干 狠狠操| 毛片av中文字幕一区二区| 午夜影院免费观看视频| 99精品欧美一区二区蜜桃免费| av永久免费观看| 一区二区三区在线视频观看| 成人免费毛片男人用品| 91精品国产综合久久精品麻豆| 蜜臀av免费在线观看| 伊人亚洲福利一区二区三区| 暖暖在线中文免费日本| 国产成人精品久久二区二区91| 精品三级国产| 日本精品一区二区三区不卡无字幕| 88国产精品视频一区二区三区| 欧美大片在线播放| 国产一区二区三区四区五区入口 | 麻豆精品国产传媒| 91麻豆国产在线观看| 亚洲视频重口味| 日韩欧美在线视频免费观看| av在线免费在线观看| 亚洲天堂av在线免费| 久久www人成免费看片中文| 国产精品久久久久久久久久久久久| 亚洲精品a区| 一区二区三区四区视频在线观看 | 性亚洲最疯狂xxxx高清| 日韩成人综合网站| 欧美日韩大片一区二区三区| 欧美视频久久| 毛片毛片毛片毛| 久久久精品tv| 四虎成人精品永久免费av| 在线成人av网站| 国产在线观看网站| 91精品国产成人www| 日韩三级网址| 亚洲啪啪av| 老司机午夜精品视频| 久久久久国产免费| 中文字幕综合网| 国产成人精品一区二区色戒| 亚洲精品一区二区在线| av漫画网站在线观看| 999视频在线免费观看| 国产高清一区二区| 亚洲老女人av| 国产视频911| 波多野结衣一本一道| 亚洲欧美日韩精品久久| 男人久久天堂| 精品一区日韩成人| 亚洲伦伦在线| 免费的av网站| 欧美日韩亚洲网| 亚洲欧洲精品视频| 51精品国产黑色丝袜高跟鞋| 岛国成人av| 成人毛片视频网站| av在线这里只有精品| 日本五十熟hd丰满| 亚洲精品ady| 高清不卡亚洲| 日本一区二区三区四区在线观看 | 欧美午夜在线视频| 亚洲综合20p| 亚洲综合免费观看高清完整版 | 国产午夜精品麻豆| 成人小电影网站| 欧美一区二区影视| 男女男精品网站| fc2ppv在线播放| 欧美一级精品在线| 秋霞在线午夜| 韩国成人动漫在线观看| 亚洲专区一区| 特级西西www444人体聚色| 欧美性大战久久久久久久蜜臀| jizz在线观看中文| 亚洲自拍偷拍福利| 亚洲国产三级| a天堂中文字幕| 欧美精品vⅰdeose4hd| 色屁屁www国产馆在线观看| 国产精品国模大尺度私拍| 亚洲欧美日韩国产一区| 国产91丝袜美女在线播放| 欧美伦理视频网站| 成人免费高清| 国产欧美在线一区二区| 久久精品中文| 波兰性xxxxx极品hd| 日韩欧美一级精品久久| 国产拍在线视频| 亚洲乱码一区二区三区| 国产乱子伦一区二区三区国色天香| 精品在线免费观看视频| 亚洲天堂av女优| 美女国产精品久久久| 99热在线这里只有精品| 国产精品理论片在线观看| 欧洲成人一区二区三区| 国产精品久久久久久久av电影 | 日本女优爱爱视频| 亚洲欧美日韩一区二区三区在线观看| 亚洲精品字幕在线观看| 国产成人免费av电影| 欧美黄在线观看| 无码熟妇人妻av| 欧美一区二区黄| 欧美影视资讯| 青青青青在线视频| 中文子幕无线码一区tr| 亚洲毛片在线播放| 国产精品免费福利| 99国产成+人+综合+亚洲欧美| 欧美激情视频二区| 亚洲成人久久一区| 欧美亚洲黄色| 丰满爆乳一区二区三区| 亚洲色大成网站www久久九九| 欧美美乳在线| 国产欧美日韩在线播放|