OpenHarmony TouchScreen 无法正常工作问题分析
问题背景:
将openharmony 2.2 3.0 3.1beta 移植到imx8q 和 芯驰X9H 平台, 多出现过屏幕点亮以后TouchScreen 无法正常工作. 也就是说在其他富设备平台上移植OH的时候也会大概率出现类似的问题,有必要对该问题的深层次原因进行分析.
网上有一种解决方案: 修改 /system/etc/udev/rules.d/touchscreen.rules , 将其中的"DRIVERS"属性改成 该平台touch driver name. 严格来讲 这个是 使能 OH touch必须的一步, 但很遗憾只有这一步并不能解决上面两个平台遇到的问题.
问题原因分析:
在指出具体原因之前,先简要梳理一下OH 事件分发路径.OH 在3.1Beta之前显示架构是基于weston, 在3.1Beta以后 应该更换成RenderService(RS). 两套显示架构采用的事件分发机制是不一样的,简要梳理如下:
A. Weston 版本的事件分发架构如下:
B. RS 版本的事件分发架构如下:
由上两个图可以看到, 两种分发机制的 一个明显不同点在于: 一个是由weston 进程 分发 ; 而另外一个 不经RS,而是由一个独立的进程mmi_service 进行分发. 或者类似于android里面的InputManagerService,事件的分发不经由显示架构SF.
明显的相同点有两个: 一个是 多是通过socket 进行事件的传递; 另一个是 事件的获取都是通过libinput 接口.
回到分析"不能touch"这个问题, 由上可知,两种分发机制多是基于udev 的, 所以 配置touchscreen.rules 是必须的一步, 为什么这个是必须的一步,原因在于: udev 会根据这个配置文件 和 系统中的设备信息做match, 如没有找到匹配的配置文件,不会调用udev_device_update_db 在 /data/udev/data 和 /data/udev/tags 里面生成相关设备的配置信息. 而这些配置信息是libinput 正常工作所必须的, 具体逻辑如下所显:
其中在udev_device_get_is_initialized 将通过udev_device_read_db 读取这些设备信息文件,如没有这些文件,udev_device_get_is_initialized 将返回0. 这将导致 device_added 无法执行到, 也就生成不了 seat 和对应的 evdev 对象. 而这些信息 是libinput 能否正常工作所需要的, libinput_get_event 就不能从事件数组里面获得事件.
解决办法:
需要让touch 可以正常工作,前提条件是在/data/udev里面需要存在相关设备信息文件, 也就是说 udev_device_update_db 必须被调用, 而该接口要被调用,依赖底层上报 NETLINK_KOBJECT_UEVENT,存在如下逻辑:
imx8q 不能工作是因为设备正常冷启动时候,udev 服务没有接收到NETLINK_KOBJECT_UEVENT 事件, 需要插拔下 屏幕数据线.
X9H 不能工作是因为底层不会上报 NETLINK_KOBJECT_UEVENT,即使插拔 数据线,同样不会上报. 解决的办法是在 /data/udev 里面构建相关设备信息文件. 需要构建的文件如下:
A. /data/udev/data/+input:input0 ---- 这里的数字0 与 /dev/input/event0(有事件生成的节点)相同
B./data/udev/data/c13:64 ---- 这里文件名是由字符c+"cat /sys/class/input/event0/dev" 组成
C. /data/udev/tags/seat/+input:input0
A ,B 中两个文件里面的内容构建方法可以 拷贝 一个其他平台的, 具体内容可以修改成 平台具体的信息.
芯驰X9H OH 3.1Beta 版本: