当前位置: 首页 > news >正文

OpenHarmony按键分发流程(60%)

环境

系统版本: OpenHarmony 4.0.10.13
平台设备:rk3588

涉及代码

foundation/multimodalinput/input/service/module_loader/src/mmi_service.cpp
foundation/multimodalinput/input/service/libinput_adapter/src/libinput_adapter.cpp
foundation/multimodalinput/input/service/event_handler/src/input_event_handler.cpp
foundation/multimodalinput/input/service/event_handler/src/event_normalize_handler.cpp
foundation/multimodalinput/input/service/key_event_normalize/src/key_event_normalize.cpp
foundation/multimodalinput/input/service/event_handler/src/key_map_manager.cpp
foundation/multimodalinput/input/service/event_handler/src/key_event_value_transformation.cpp
foundation/multimodalinput/input/service/filter/src/event_filter_handler.cpp
foundation/multimodalinput/input/service/interceptor/src/event_interceptor_handler.cpp
foundation/multimodalinput/input/service/key_command/src/key_command_handler.cpp
foundation/multimodalinput/input/service/subscriber/src/key_subscriber_handler.cpp
foundation/multimodalinput/input/service/monitor/src/event_monitor_handler.cpp
foundation/multimodalinput/input/service/event_dispatch/src/event_dispatch_handler.cpp
foundation/multimodalinput/input/service/event_handler/src/key_auto_repeat.cpp
foundation/multimodalinput/input/frameworks/proxy/event_handler/src/client_msg_handler.cpp
foundation/multimodalinput/input/frameworks/proxy/event_handler/src/input_handler_manager.cpp
foundation/multimodalinput/input/frameworks/proxy/event_handler/src/input_manager_impl.cpp

多模输入子系统

OpenHamrony旨在为开发者提供NUI(Natural User Interface)的交互方式,有别于传统操作系统的输入,在OpenHarmony上,我们将多种维度的输入(触屏、鼠标、键盘、触摸板、遥控器等)整合在一起,通过归一/标准化处理后,分发给消费者(系统服务、应用)。开发者可以借助应用程序框架、系统自带的UI组件或API接口轻松地实现具有多维、自然交互特点的应用程序。
多模输入子系统在OpenHarmony系统架构中的位置:OpenHarmony技术架构

输入时间和设备状态数据流如下:
输入时间和设备状态数据流
如图所示,包含两类关键数据流:

  • 输入设备状态数据流
    输入设备状态数据描述输入设备的状态变化及其设备属性信息,包括:设备插入、移除状态、设备唯一标识、设备名称、设备支持的输入方式等。
    输入设备状态数据,经过内核设备驱动上报给多模输入服务端的输入设备状态管理模块。在输入设备管理模块对全局输入设备状态进行管理和维护,同时设备状态会封装为可监听接口提供给上层业务模块用来监听系统输入外设的状态。
  • 交互输入事件数据流
    交互输入事件数据用来描述键盘、鼠标、触摸屏输入事件;键盘事件包括:按键码、按键时间戳、按键所属设备等信息;鼠标事件包括:鼠标 X/Y 坐标、鼠标按钮(如:鼠标左|中|右)事件等;触摸事件包括:时间戳、触摸位置 X/Y 坐标等。
    输入事件数据由设备驱动上报给输入事件接收模块完成输入事件从内核空间到用户空间的转发,然后再给输入事件预处理模块完成输入事件标准化处理(按键 KeyCode 映射标准化等),最后由输入事件分发模块以系统预设分发机制和原则完成事件的分发。

根据上面数据流图,可以很清晰地了解到在用户通过输入设备发起一次交互请求后,输入事件上报和分发全流程。

按键分发代码流程梳理

多模输入分发流程,按键事件在kernel驱动层检测并识别后,向多模输入服务端分发,会经历以下处理流程:

  • 输入事件接收
  • 输入事件预处理
  • 输入事件分发:拦截、分发、监听
  • 应用框架传递输入事件
  • 应用监听处理

多模输入服务(MutilModalInputService)MMIService启动

MMIService服务有init进程启动,代码流程如下:
base/startup/init/services/init/main.c

//init进程启动
int main(int argc, char * const argv[])
{...EnableInitLog(INIT_INFO);if (isSecondStage == 0) {SystemPrepare(); //系统做准备工作:打开log服务、使能kmsg、挂载基本目录、进入init第二阶段} else {LogInit();}SystemInit(); //系统初始化SystemExecuteRcs();SystemConfig();//加载系统配置文件、启动开机服务和基本服务SystemRun();//启动属性服务ParamServicereturn 0;
}

init进程做好系统准备工作后,由SystemConfig()启动各系统服务
base/startup/init/services/init/standard/init.c

void SystemConfig(void)
{...TriggerServices(START_MODE_BOOT); //启动开机阶段服务,如:hdf_devmgr、hiview、param_watcher、device_manager、storage_manager、appspawn等TriggerServices(START_MODE_NORMAL);//启动基本服务:wifi_hal_service、multimodalinput、bluetooth_service、netmanager等
}

至此通过TriggerServices(START_MODE_NORMAL)启动了多模输入服务multimodalinput,即MMIS
foundation/multimodalinput/input/service/module_loader/src/mmi_service.cpp

void MMIService::OnStart()
{...//初始化MMIS和相关的windowManager、ANRManager 、PointerDrawingManager 、InputHandler等。int32_t ret = Init();//启动OnThread线程,监听kernel上报的eventt_ = std::thread(std::bind(&MMIService::OnThread, this));pthread_setname_np(t_.native_handle(), name.c_str());...
}

MMIService服务启动后,紧接着进行init,并创建OnThread线程;我们首先看看init()

int32_t MMIService::Init()
{...WinMgr->Init(*this);    //初始化WindowsManagerANRMgr->Init(*this);    //初始化ANRManagerFINGERSENSE_WRAPPER->InitFingerSenseWrapper();DISPLAY_MONITOR->InitCommonEventSubscriber();if (!IPointerDrawingManager::GetInstance()->Init()) {...}...InputHandler->Init(*this);    //初始化InputHandler,调用BuildInputHandlerChain()构建inputHandler的传递链if (!InitLibinputService()) {    //初始化InitLibinputAdapter..}if (!InitDelegateTasks()) {..}...
}
...
bool MMIService::InitLibinputService()
{//初始化libinputAdapter并绑定InputEventHandler::OnEvent()if (!(libinputAdapter_.Init(std::bind(&InputEventHandler::OnEvent, InputHandler, std::placeholders::_1)))) {MMI_HILOGE("Libinput init, bind failed");return false;}...
}

在init中初始化相关manager和其他服务,其中包括初始化libinputAdapter并绑定InputEventHandler::OnEvent(),监听Event事件,并进一步处理。
了解inputHander.Init()便于理解后续各inputHandler中keyevent传递过程
foundation/multimodalinput/input/service/event_handler/src/input_event_handler.cpp

void InputEventHandler::Init(UDSServer& udsServer)
{udsServer_ = &udsServer;BuildInputHandlerChain();
}
nt32_t InputEventHandler::BuildInputHandlerChain()
{eventNormalizeHandler_ = std::make_shared<EventNormalizeHandler>();
#if !defined(OHOS_BUILD_ENABLE_KEYBOARD) && !defined(OHOS_BUILD_ENABLE_POINTER) && !defined(OHOS_BUILD_ENABLE_TOUCH)return RET_OK;
#endif // !OHOS_BUILD_ENABLE_KEYBOARD && !OHOS_BUILD_ENABLE_POINTER && !OHOS_BUILD_ENABLE_TOUCHstd::shared_ptr<IInputEventHandler> handler = eventNormalizeHandler_;
#if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)eventFilterHandler_ = std::make_shared<EventFilterHandler>();handler->SetNext(eventFilterHandler_);handler = eventFilterHandler_;
#endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH...
}

通过SetNext()将各种inputEventHandler链起来,形成
EventNormalizeHandler-->EventFilterHandler-->EventInterceptorHandler-->KeyCommandHandler->KeySubscriberHandler->EventMonitorHandler->EventDispatchHandler

回到主线OnStart(),看看OnThread()内容

//OnThread线程,分发kernel上报的event
void MMIService::OnThread()
{...libinputAdapter_.ProcessPendingEvents();while (state_ == ServiceRunningState::STATE_RUNNING) {...for (int32_t i = 0; i < count && state_ == ServiceRunningState::STATE_RUNNING; i++) {auto mmiEd = reinterpret_cast<mmi_epoll_event *>(ev[i].data.ptr);CHKPC(mmiEd);//根据I/O类型的不同,处理流程不同,按键事件为EPOLL_EVENT_INPUT类型,进入libinputAdapter_.EventDispatch()if (mmiEd->event_type == EPOLL_EVENT_INPUT) {libinputAdapter_.EventDispatch(mmiEd->fd);} else if (mmiEd->event_type == EPOLL_EVENT_SOCKET) {OnEpollEvent(ev[i]);} else if (mmiEd->event_type == EPOLL_EVENT_SIGNAL) {OnSignalEvent(mmiEd->fd);} else if (mmiEd->event_type == EPOLL_EVENT_ETASK) {OnDelegateTask(ev[i]);} else {MMI_HILOGW("Unknown epoll event type:%{public}d", mmiEd->event_type);}}...}
}

OnThread处理kernel上报上来的按键事件,向后续流程进行libinputAdapter_.EventDispatch()按键事件分发
foundation/multimodalinput/input/service/libinput_adapter/src/libinput_adapter.cpp

void LibinputAdapter::EventDispatch(int32_t fd)
{...//准备处理kernel上报上来的eventOnEventHandler();...
}void LibinputAdapter::OnEventHandler()
{CALL_DEBUG_ENTER;CHKPV(funInputEvent_);libinput_event *event = nullptr;while ((event = libinput_get_event(input_))) {funInputEvent_(event);libinput_event_destroy(event);}
}

前面InitLibinputService()绑定了input_event_handler.cpp的OnEvent()

void InputEventHandler::OnEvent(void *event)
{...eventNormalizeHandler_->HandleEvent(lpEvent);...
}

foundation/multimodalinput/input/service/event_handler/src/event_normalize_handler.cpp

void EventNormalizeHandler::HandleEvent(libinput_event* event)
{//获取event事件类型auto type = libinput_event_get_type(event);...switch (type) {...//处理按键类型eventcase LIBINPUT_EVENT_KEYBOARD_KEY: {HandleKeyboardEvent(event);DfxHisysevent::CalcKeyDispTimes();    //统计按键分发次数break;}...
}
//进入处理按键事件流程
int32_t EventNormalizeHandler::HandleKeyboardEvent(libinput_event* event)
{...auto keyEvent = KeyEventHdr->GetKeyEvent();    //获取keyEvent对象auto packageResult = KeyEventHdr->Normalize(event, keyEvent);    //标准化keyevent...nextHandler_->HandleKeyEvent(keyEvent);    //传递至下个handler处理按键事件KeyRepeat->SelectAutoRepeat(keyEvent);    //是否出发某些自动重复功能,如键盘长按连续输入字符MMI_HILOGD("keyCode:%{public}d, action:%{public}d", keyEvent->GetKeyCode(), keyEvent->GetKeyAction());...
}//将底层异构的硬件输入事件统一封装为应用层可理解的标准化事件,包含设备信息、按键状态、时间戳及语义意图,实现输入事件的抽象与跨平台兼容
int32_t KeyEventNormalize::Normalize(struct libinput_event *event, std::shared_ptr<KeyEvent> keyEvent)
{....//根据device转换keycodekeyCode = KeyMapMgr->TransferDeviceKeyValue(device, keyCode);....//标准化keyEvent对象参数值,包括按键事件、意图、设备id、按键码等keyEvent->SetActionTime(time);keyEvent->SetAction(keyAction);keyEvent->SetDeviceId(deviceId);keyEvent->SetKeyCode(keyCode);keyEvent->SetKeyAction(keyAction);if (keyEvent->GetPressedKeys().empty()) {keyEvent->SetActionStartTime(time);}KeyEvent::KeyItem item;bool isKeyPressed = (libinput_event_keyboard_get_key_state(data) != KEYSTATUS);item.SetDownTime(time);item.SetKeyCode(keyCode);item.SetDeviceId(deviceId);item.SetPressed(isKeyPressed);item.SetUnicode(KeyCodeToUnicode(keyCode, keyEvent));//管理特殊keyEvent状态,如NumLock、CapsLock、ScrollLockHandleKeyAction(device, item, keyEvent);int32_t keyIntention = keyItemsTransKeyIntention(keyEvent->GetKeyItems());keyEvent->SetKeyIntention(keyIntention);return RET_OK;
}

根据代码执行先后顺序,这里主要动作:

  • 根据设备,将linux keycode转换成device keycode
  • 标准化keyevent对象各参数
  • 管理特殊按键状态
  • 更新按键intention

了解下TransferDeviceKeyValue()转换过程
foundation/multimodalinput/input/service/event_handler/src/key_map_manager.cpp

int32_t KeyMapManager::TransferDeviceKeyValue(struct libinput_device *device,int32_t inputKey)
{//device为空时使用默认按键映射表转换inputKeyif (device == nullptr) {return TransferDefaultKeyValue(inputKey);}//使用定制按键映射表转换inputKeyint32_t deviceId = InputDevMgr->FindInputDeviceId(device);if (auto itr = configKeyValue_.find(deviceId); itr != configKeyValue_.end()) {if (auto devKey = itr->second.find(inputKey); devKey != itr->second.end()) {return devKey->second;}}//上面调节不成立,仍使用默认按键映射表return TransferDefaultKeyValue(inputKey);
}int32_t KeyMapManager::TransferDefaultKeyValue(int32_t inputKey)
{...return TransferKeyValue(inputKey).sysKeyValue;
}

foundation/multimodalinput/input/service/event_handler/src/key_event_value_transformation.cpp

KeyEventValueTransformation TransferKeyValue(int32_t keyValueOfInput)
{auto it = MAP_KEY_EVENT_VALUE_TRANSFORMATION.find(keyValueOfInput);...return it->second;
}//默认的键值映射表:当前按下的键为KEY_1 
//2:linux keycode      KEY_1: key event标签		2:native keycode 	 2001: 系统keycode  HOS_KEY_1:系统key event码
const std::multimap<int32_t, KeyEventValueTransformation> MAP_KEY_EVENT_VALUE_TRANSFORMATION = {{11, {"KEY_0", 11, 2000, HOS_KEY_0}},{2, {"KEY_1", 2, 2001, HOS_KEY_1}},{3, {"KEY_2", 3, 2002, HOS_KEY_2}},...
};

当前按键为数字1,由于没有没有定制按键转化配置文件,使用默认的配置表,将linux keycode 2转为2001系统keycode,即后续APP使用的keycode。
得到转换后的keycode并进行标准化keyevent,继续HandleKeyEvent()
foundation/multimodalinput/input/service/event_handler/src/event_normalize_handler.cpp

void EventNormalizeHandler::HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)
{...//继续向EventFilterHandler传递keyeventnextHandler_->HandleKeyEvent(keyEvent);...
}

通过前文BuildInputHandlerChain()可知EventNormalizeHandler的nextHandler为EventFilterHandler
foundation/multimodalinput/input/service/filter/src/event_filter_handler.cpp

void EventFilterHandler::HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)
{//处理需要过滤的keyeventif (HandleKeyEventFilter(keyEvent)) {MMI_HILOGD("Key event is filtered");return;}//继续向EventInterceptorHandler传递keyeventnextHandler_->HandleKeyEvent(keyEvent);
}bool EventFilterHandler::HandleKeyEventFilter(std::shared_ptr<KeyEvent> event)
{//默认filters为空,直接returnif (filters_.empty()) {return false;}//遍历过滤器,检查keyevent是否需要过滤处理for (auto &i: filters_) {if (!inputDevice->HasCapability(i.deviceTags)) {continue;}if (i.filter->HandleKeyEvent(event)) {MMI_HILOGD("Call HandleKeyEventFilter return true");return true;}}return false;
}

foundation/multimodalinput/input/service/interceptor/src/event_interceptor_handler.cpp

void EventInterceptorHandler::HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)
{//检查按键是否需要拦截if (OnHandleEvent(keyEvent)) {MMI_HILOGD("KeyEvent filter find a keyEvent from Original event keyCode:%{public}d",keyEvent->GetKeyCode());BytraceAdapter::StartBytrace(keyEvent, BytraceAdapter::KEY_INTERCEPT_EVENT);return;}//继续向KeyCommandHandler传递keyEventnextHandler_->HandleKeyEvent(keyEvent);
}bool EventInterceptorHandler::OnHandleEvent(std::shared_ptr<KeyEvent> keyEvent)
{MMI_HILOGD("Handle KeyEvent");...//检查是否keyevent需要被拦截return interceptors_.HandleEvent(keyEvent);
}bool EventInterceptorHandler::InterceptorCollection::HandleEvent(std::shared_ptr<KeyEvent> keyEvent)
{CHKPF(keyEvent);//默认未设置拦截器,在此returnif (interceptors_.empty()) {MMI_HILOGD("Key interceptors is empty");return false;}...return isInterceptor;
}

foundation/multimodalinput/input/service/key_command/src/key_command_handler.cpp

void KeyCommandHandler::HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)
{//处理短按按键、组合按键、特殊按键(默认均未配置)if (OnHandleEvent(keyEvent)) {MMI_HILOGD("The keyEvent start launch an ability, keyCode:%{public}d", keyEvent->GetKeyCode());BytraceAdapter::StartBytrace(keyEvent, BytraceAdapter::KEY_LAUNCH_EVENT);return;}//继续向KeySubscriberHandler传递keyeventnextHandler_->HandleKeyEvent(keyEvent);
}bool KeyCommandHandler::OnHandleEvent(const std::shared_ptr<KeyEvent> key)
{//处理(快捷键)按键短按事件bool isHandled = HandleShortKeys(key);//处理组合按键(如Ctrl + C)isHandled = HandleSequences(key) || isHandled;if (isHandled) {return true;}//检查是否为特殊按键, Power、Vol+、Vol-if (!specialKeys_.empty() && specialKeys_.find(key->GetKeyCode()) != specialKeys_.end()) {HandleSpecialKeys(key->GetKeyCode(), key->GetAction());return true;}//处理订阅按键事件if (IsSpecialType(key->GetKeyCode(), SpecialType::SUBSCRIBER_BEFORE_DELAY)) {...InputHandler->GetSubscriberHandler()->HandleKeyEvent(tmpKey);...}...
}

KeyCommandHandler::OnHandleEvent()按键事件处理分类按键

  • 快捷键:
  • 全局特殊按键:Power、Vol+、Vol-

快捷键处理:

bool KeyCommandHandler::HandleShortKeys(const std::shared_ptr<KeyEvent> keyEvent)
{...//遍历快捷键配置表的快捷键(etc/multimodalinput/ability_launch_config.json 默认未配置),并处理相应的快捷键事件for (auto &item : shortcutKeys_) {...//从配置文件/data/service/el1/public/multimodalinput/Settings.xml(默认无此文件)中获取识别为按键短按的配置int32_t delay = GetKeyDownDurationFromXml(shortcutKey.businessId);//按键按下持续0~4s则认为是短按事件if (delay >= MIN_SHORT_KEY_DOWN_DURATION && delay <= MAX_SHORT_KEY_DOWN_DURATION) {MMI_HILOGD("User defined new short key down duration: %{public}d", delay);shortcutKey.keyDownDuration = delay;}//根据快捷键配置的出发类型决定Down或up触发时机if (shortcutKey.triggerType == KeyEvent::KEY_ACTION_DOWN) {return HandleKeyDown(shortcutKey);} else if (shortcutKey.triggerType == KeyEvent::KEY_ACTION_UP) {return HandleKeyUp(keyEvent, shortcutKey);} else {return HandleKeyCancel(shortcutKey);}}//取消按键事件return HandleConsumedKeyEvent(keyEvent);
}

Power按键处理:

//特殊按键类型
enum SpecialType {SPECIAL_ALL = 0,SUBSCRIBER_BEFORE_DELAY = 1,KEY_DOWN_ACTION = 2
};
//默认特殊按键表,包含Power按键、音量键
const std::map<int32_t, SpecialType> SPECIAL_KEYS = {{ KeyEvent::KEYCODE_POWER, SpecialType::KEY_DOWN_ACTION },{ KeyEvent::KEYCODE_VOLUME_DOWN, SpecialType::SPECIAL_ALL },{ KeyEvent::KEYCODE_VOLUME_UP, SpecialType::SPECIAL_ALL }
};//拦截电源键和音量键继续下发
void KeyCommandHandler::HandleSpecialKeys(int32_t keyCode, int32_t keyAction)
{auto iter = specialKeys_.find(keyCode);if (keyAction == KeyEvent::KEY_ACTION_UP) {if (iter != specialKeys_.end()) {specialKeys_.erase(iter);return;}}if (keyAction == KeyEvent::KEY_ACTION_DOWN) {if (iter == specialKeys_.end()) {auto it = specialKeys_.emplace(keyCode, keyAction);if (!it.second) {MMI_HILOGD("KeyCode duplicated");return;}}}
}

若按键不是快捷键和系统按键,则继续向KeySubscriberHandler传递
foundation/multimodalinput/input/service/subscriber/src/key_subscriber_handler.cpp

void KeySubscriberHandler::HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)
{//if (OnSubscribeKeyEvent(keyEvent)) {...}//继续向EventMonitorHandler传递keyeventnextHandler_->HandleKeyEvent(keyEvent);
}bool KeySubscriberHandler::OnSubscribeKeyEvent(std::shared_ptr<KeyEvent> keyEvent)
{...//根据按键动作调用不同处理方法,按下时首先进入HandleKeyDown()if (keyAction == KeyEvent::KEY_ACTION_DOWN) {handled = HandleKeyDown(keyEvent);} else if (keyAction == KeyEvent::KEY_ACTION_UP) {hasEventExecuting_ = false;handled = HandleKeyUp(keyEvent);} else if (keyAction == KeyEvent::KEY_ACTION_CANCEL) {hasEventExecuting_ = false;handled = HandleKeyCancel(keyEvent);} ...
}bool KeySubscriberHandler::HandleKeyDown(const std::shared_ptr<KeyEvent> &keyEvent)
{...for (const auto &subscriber : subscribers_) {auto &keyOption = subscriber->keyOption_;if (!keyOption->IsFinalKeyDown()) {MMI_HILOGD("!keyOption->IsFinalKeyDown()");continue;}if (keyCode != keyOption->GetFinalKey()) {ClearTimer(subscriber);MMI_HILOGD("keyCode != keyOption->GetFinalKey()");continue;}if (!IsPreKeysMatch(keyOption->GetPreKeys(), pressedKeys)) {ClearTimer(subscriber);MMI_HILOGD("preKeysMatch failed");continue;}if (keyOption->GetFinalKeyDownDuration() <= 0) {MMI_HILOGD("keyOption->GetFinalKeyDownDuration() <= 0");//向订阅者通知并发送按键事件信息NotifySubscriber(keyEvent, subscriber);handled = true;continue;}if (!AddTimer(subscriber, keyEvent)) {MMI_HILOGE("Leave, add timer failed");}}MMI_HILOGD("%{public}s", handled ? "true" : "false");return handled;
}

foundation/multimodalinput/input/service/monitor/src/event_monitor_handler.cpp

void EventMonitorHandler::HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)
{OnHandleEvent(keyEvent);//继续向EventDispatchHandler传递keyeventnextHandler_->HandleKeyEvent(keyEvent);
}bool EventMonitorHandler::OnHandleEvent(std::shared_ptr<KeyEvent> keyEvent)
{...if (monitors_.HandleEvent(keyEvent)) ...
}bool EventMonitorHandler::MonitorCollection::HandleEvent(std::shared_ptr<KeyEvent> keyEvent)
{...//for (const auto &mon : monitors_) {if ((mon.eventType_ & HANDLE_EVENT_TYPE_KEY) == HANDLE_EVENT_TYPE_KEY) {mon.SendToClient(keyEvent);}}...
}void EventMonitorHandler::SessionHandler::SendToClient(std::shared_ptr<KeyEvent> keyEvent) const
{NetPacket pkt(MmiMessageId::REPORT_KEY_EVENT);...if (!session_->SendMsg(pkt)) {...
}

foundation/multimodalinput/input/service/event_dispatch/src/event_dispatch_handler.cpp

void EventDispatchHandler::HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)
{...DispatchKeyEventPid(*udsServer, keyEvent);
}int32_t EventDispatchHandler::DispatchKeyEventPid(UDSServer& udsServer, std::shared_ptr<KeyEvent> key)
{...MMI_HILOGD("Event dispatcher of server:KeyEvent:KeyCode:%{public}d,Action:%{public}d,EventType:%{public}d,""Fd:%{public}d", key->GetKeyCode(), key->GetAction(), key->GetEventType(), fd);auto session = udsServer.GetSession(fd);auto currentTime = GetSysClockTime();if (ANRMgr->TriggerANR(ANR_DISPATCH, currentTime, session)) {MMI_HILOGW("The key event does not report normally, application not response");return RET_OK;}NetPacket pkt(MmiMessageId::ON_KEY_EVENT);InputEventDataTransformation::KeyEventToNetPacket(key, pkt);if (!udsServer.SendMsg(fd, pkt)) {MMI_HILOGE("Sending structure of EventKeyboard failed! errCode:%{public}d", MSG_SEND_FAIL);return MSG_SEND_FAIL;}ANRMgr->AddTimer(ANR_DISPATCH, key->GetId(), currentTime, session);return RET_OK;
}
http://www.xdnf.cn/news/957331.html

相关文章:

  • 4.redis集群
  • rk3568的data分区修改
  • 以太网PHY布局布线指南
  • Houdini POP入门学习07 - 分组
  • 热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
  • 论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
  • 游戏开发中常见的战斗数值英文缩写对照表
  • ubuntu中安装conda的后遗症
  • 3439. 重新安排会议得到最多空余时间 I
  • vue3 报错Missing semicolon
  • Yolov8 目标检测蒸馏学习记录
  • 【2025】pycharm 安装
  • 详解什么是One-Hot Encoding (独热编码)
  • PH热榜 | 2025-06-08
  • Ascend NPU上适配Step-Audio模型
  • C语言数据结构笔记4:子函数中使用的sizeof 指针无法获取数组的实际大小
  • 学习经验分享篇(3)——电机驱动电力电子方向投稿经历
  • 职场生存发展指南 | 边界 / 责任 / 社交 / 情绪
  • 个人自用debian启动
  • C语言 学习 宏命令(预处理) 2025年6月9日14:41:39
  • 【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
  • 机器人模仿学习调研
  • 处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
  • Android实践:查看远程文档
  • 数据驱动证券业务精细化决策,从洞察到行动的全链路赋能
  • IBMS集成系统 结合数字孪生技术,实现建筑的3D可视化监控与智能化运维
  • prxomox 8.3-8.4更新
  • 如何在Android Studio中导出apk文件
  • [25-cv-06277]Keith律所代理昆虫画作版权图
  • docker相关(AI回答)