成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

系統
本文可以了解多模輸入系統事件派發的流程,以及多模輸入系統的接口和注入事件的流程,結合以上的源碼分析會對多模輸入子系統會有更深入的理解。

[[424563]]

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

簡介

多模輸入系統主要用于接收按鍵,觸摸等輸入事件,并且會對這些原始輸入事件進行處理,之后再對這些事件進行派發。同時多模輸入系統還提供了注入事件的接口,應用可以通過調用這個接口產生輸入事件,然后將該輸入事件注入到輸入系統中進行處理。

OpenHarmony 源碼解析之多模輸入子系統(事件派發流程)-鴻蒙HarmonyOS技術社區

輸入系統框架

OpenHarmony 源碼解析之多模輸入子系統(事件派發流程)-鴻蒙HarmonyOS技術社區

多模輸入系統主要是由InputManagerService, InputEventHub, InputEventDistributer來負責處理的。InputManagerService會啟動InputEventHub,并且會通過創建子線程的方式來創建InputEventDistributer。當底層傳來按鍵或觸摸事件的時候,InputEventHub就會進行讀取,并且會對這些原始的輸入事件進行處理,處理完后會交給InputEventDistributer進行派發。InputEventDistributer又會通過InputEventClientProxy進行IPC交互的方式發給應用端。

多模輸入系統事件派發流程

事件派發流程圖

OpenHarmony 源碼解析之多模輸入子系統(事件派發流程)-鴻蒙HarmonyOS技術社區

源碼分析

下面就對多模輸入系統事件派發流程的源碼進行分析。

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的啟動是在WMS的main函數中通過InputManagerService::GetInstance()->Run()執行的。

\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()中首先會創建InputEventHub的對象并通過RegisterReadCallback來注冊InputEventHub的回調,然后通過SetUp來啟動InputEventHub, InputEventHub主要是用于對底層原始輸入事件的讀取和處理,該函數的最后會創建distributerThread子線程,用于對輸入事件的派發。

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.     } 

在這個函數中InputEventHub主要的工作就是通過調用驅動層的OpenInputDevice來打開輸入設備,并且會將EventCallback的回調函數通過驅動層的RegisterReportCallback進行注冊。當底層有事件傳遞上來,EventCallback就會被調用。OpenInputDevice和RegisterReportCallback具體實現分別是在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); 

當底層有輸入事件上來的話,EventCallback就會被調用,在這個函數里會通過EventPackage->type來判斷輸入事件的類型,其中

EV_REL是相對坐標的輸入事件,比如軌跡球,鼠標事件

EV_ABS是絕對坐標的輸入事件,比如觸屏觸摸事件

EV_KEY是按鍵輸入事件,比如設備上的物理按鍵的點擊事件

EV_SYN是Motion的一系列動作結束標志位

如果是鼠標事件,會將相對坐標值放入到data.x和data.y中,如果是觸屏觸摸事件,會將在觸屏上觸摸的坐標位置放入到data.x和data.y中,如果是按鍵事件會將按鍵的點擊狀態放入到data.state中。

處理完輸入事件后,會將數據放入到data中,并通過readCallback傳給InputManagerService進行處理,之后就會調用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這個函數首先會判斷eventQueue這個事件隊列里事件數量是否達到最大數量,如果達到最大數量該線程就一直等待,否則就會把該事件放到eventQueue這個事件隊列里,并且同時也會發出nonEmpty的signal, 來讓Distribute中的線程停止等待。

Distribute函數中,當eventQueue隊列里沒有事件的時候,就會一直等待,當有事件來的時候就會停止線程等待,然后會遍歷整個eventQueue這個隊列,把每個事件獲取出來后放入到events這個數組中,并做為參數放入到InputEventDistributer::Distribute中進行事件的派發。

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.     } 

這個函數比較簡單,主要就是遍歷所有的InputEventClientProxy, 并且調用各自的onRawEvent進行實際的派發工作。

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_); 

這個函數主要就是通過ipc的交互方式把輸入事件傳給應用端。

到此整個多模輸入系統的事件派發流程就結束了。

多模輸入系統接口說明

模塊

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

通過每個目錄下的.gn文件可以看到每個目錄下的模塊都對應動態庫

\interfaces\native\innerkits\event下的文件編出來的是mmi_event.so

\interfaces\native\innerkits\napi 下的文件編出來的是injecteventhandler.so

\interfaces\native\innerkits\proxy 下的文件編出來的是libmultimodalinput_proxy.so

\service 下的文件編出來的是libmultimodalinput_service.so

\uinput 下的文件編出來的是mmi_uinject.so

接口

多模輸入目前提供的接口為事件注入接口,該接口目前僅對系統應用開放。

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的源碼中看到, 當點擊navigationbar的back鍵的時候,就會調用js的接口函數injectEventSync,并傳入三個參數,其中

isPress: 按鍵的狀態,true表示down, false表示up

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

keyDownDuration:按鍵按下到抬起之間的時長,單位ms,1表示1ms

C++接口

系統內部接口

在\interfaces\native\innerkits\events\include下的頭文件都定義了各自對內部系統調用的口。

KeyEvent的主要接口

KeyBoardEvent的主要接口

ManipulationEvent的主要接口

MmiPoint的主要接口

MouseEvent的主要接口

MultimodalEvent的主要接口

StylusEvent的主要接口

TouchEvent的主要接口

InjectEvent的實現邏輯

\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中實現了InjectEventSync這個接口,通過NAPI獲得應用端的isPressed,KeyDownDuration,KeyCode這三個數值,并將這三個參數放入到KeyProperty這個結構體中。然后調用KeyEvent的Initialize,將KeyProperty封裝到KeyEvent中,最后再調用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其實是一個IPC進程間調用,這會調用到客戶端的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會通過SendRequest向服務端MultimodalInputServiceStub發送數據。

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.     } 

通過sendRequest將數據發送之后,服務端的MultimodalInputServiceStub的OnRemoteRequest就會被調用,最終會調用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實際上會調用KeyboardInject的InjectKeyEvent,從函數的實現來看,目前只使用了KeyboardInject,也就是說目前只支持鍵盤事件的注入。

\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中會通過InjectInputEvent的WaitFunc將注入事件繼續向下注入。

\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中會將injectInputEvent放入到injectQueue這個隊列中,這個隊列是用來存放injectInputEvent的,并且通過notify_one來喚醒InjectThread,由于目前只支持鍵盤類型事件的注入,所有只會調用g_pKeyboard->EmitEven(),g_pKeyboard是VirtualKeyboard的對象,VirtualKeyboard又繼承自VirtualDevice,因此最終會調用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); 

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

到此多模輸入系統接口的介紹以及InjectEvent整個注入事件的流程就結束了。

總結

通過本文的學習可以了解多模輸入系統事件派發的流程,以及多模輸入系統的接口和注入事件的流程,結合以上的源碼分析會對多模輸入子系統會有更深入的理解。

想了解更多內容,請訪問:

51CTO和華為官方合作共建的鴻蒙技術社區

https://harmonyos.51cto.com

 

責任編輯:jianghua 來源: 鴻蒙社區
相關推薦

2023-04-06 09:14:11

多模輸入子系統鴻蒙

2021-09-13 15:15:18

鴻蒙HarmonyOS應用

2023-06-28 15:00:02

開源鴻蒙輸入系統架構

2022-02-17 20:57:07

OpenHarmon操作系統鴻蒙

2022-01-06 16:17:58

鴻蒙HarmonyOS應用

2021-11-08 15:04:47

鴻蒙HarmonyOS應用

2021-12-17 16:42:09

鴻蒙HarmonyOS應用

2021-09-18 14:40:37

鴻蒙HarmonyOS應用

2023-04-12 15:31:11

系統服務管理鴻蒙

2022-01-10 15:30:11

鴻蒙HarmonyOS應用

2022-05-10 11:17:27

電話子系統數據服務模塊

2021-11-18 10:28:03

鴻蒙HarmonyOS應用

2022-05-24 15:46:51

Wi-FiSTA模式

2022-01-20 14:33:29

openharmonwayland協議鴻蒙

2022-01-13 10:11:59

鴻蒙HarmonyOS應用

2022-05-20 10:32:49

事件循環器事件隊列鴻蒙

2022-06-07 10:33:29

Camera組件鴻蒙

2022-05-30 15:08:33

包管理子系統包安裝模塊

2022-03-18 16:07:04

Graphic子系統鴻蒙

2022-01-20 11:04:31

Linux DRMOpenHarmon鴻蒙
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91在线视频免费观看 | 精品一二 | 免费在线观看91 | 中文字幕一区二区三区四区五区 | 视频在线一区二区 | 欧美成人一区二区三区 | 欧美成人精品二区三区99精品 | 日韩精品av| 亚洲国产精品一区二区三区 | 亚洲一区二区三区四区在线观看 | 亚洲综合一区二区三区 | 毛片免费看 | www.久久| 成人午夜在线 | 在线天堂免费中文字幕视频 | 久久久久久国产精品 | 一级黄色片免费在线观看 | 国产高清一区二区三区 | 一区二区视频在线观看 | 成人av免费| 欧美午夜精品 | 精品国产91乱码一区二区三区 | 91精品在线播放 | 青青草av | 成人h动漫亚洲一区二区 | 特黄特黄a级毛片免费专区 av网站免费在线观看 | 久久伊| 久久国产亚洲 | 成人午夜网站 | 97av视频在线 | 日韩视频精品在线 | 精精国产xxxx视频在线播放7 | 亚洲精品一区二区三区中文字幕 | 日韩免费高清视频 | 成人影音 | 国产午夜精品视频 | 特黄av| 涩涩视频在线看 | 国产一区视频在线 | 国产精品欧美一区二区 | 国产在线一区观看 |