Part 01
什么是云电脑和键鼠适配?
云电脑是目前非常热门的一项新技术,它基于云计算,将大量的存储、计算资源都整合成一个大的资源池并存放在云端,按需分配给用户。云端会通过高速网络,将电脑的画面投送到用户的设备上。
云电脑的终端设备类型非常丰富,有能随身携带的普通手机、Pad,能连接电视的机顶盒,以及一些老旧电脑终端等等。
对于普通电脑而言,最常用的操作输入设备就是鼠标和键盘。云电脑想要替代传统笔记本,就需要在各种终端都要适配键盘和鼠标。但是由于很多移动设备在交互上更会注重触摸交互,其对键盘和鼠标的支持往往不尽如人意。再加上终端厂商会对其终端设备系统进行高度的定制化,加剧了在云电脑在键鼠适配支持的碎片化程度,每个厂商的终端都有其特定的问题。因此键鼠的适配在云电脑终端设备整体适配工作中占据了很大的比重。
Part 02
Android键盘使用原理
在Android应用中,我们可以通过实时检测页面的onKeyDown、onKeyUp、dispatchKeyEvent等方法来实时检测绝大部分键盘按键的使用,但是由于Android系统的支持问题和厂商固件碎片化的问题,这些方法在实际使用时,会发现在不同的终端上同一个按键会有不同的键值甚至是没有键值。而为了能统一所有终端设备的按键的键值,我们对整个系统物理按键键值的映射原理进行了分析,如下:
在Android内核中,按键按下时,IR硬件扫描码会在驱动里面被映射为input.h中定义的某个键值。比如像键盘这种HID设备,按键按下时内核中的键值转换会在drivers/hid/hid-input.c 中进行映射,转化后的值即为scanCode。
在hid-input.c中的映射表如下:
图1 系统hid-input.c源码截图
同时在Android系统层的头文件input-event-codes.h中也定义了这些键值所代表的键名称。如下图(截取):
图2 系统input-event-codes.h源码部分截图
在内核中映射完之后,就需要将linux键值映射到Android系统要使用的键值映射,这部分通常定义在系统的device/xxx/xxx.kl(keylayout) 文件中。
keylayout文件的内容如下图(部分):
图3 系统keylayout文件部分截图
在kl文件中,将内核映射的结果scancode,最终映射为Android系统需要使用的键值,并最终转化为应用需要使用的keycode。
整体的流程如下:
图片
Part 03
云电脑适配键盘
了解整体键值映射的流程,那不同终端是因为什么导致的最终键值不同的,而云电脑又是怎样去对多种的终端进行键值适配的呢?
在对比多个终端设备的配置文件之后,我们发现,不同厂商的终端键值不统一主要是因为内置在系统中kl文件内容不一样导致的,因此云电脑的键值适配主要就是适配kl文件来实现。
那kl文件又需要怎么适配呢?主要的方案有4种:
(1)云电脑在应用层,根据不同终端的回调的键值,将错误的键值转化为正确的键值,完成按键的正确映射后,再使用正常的键值进行云电脑的输入交互;
(2)系统中新增不同键盘的适配文件,云电脑根据需要兼容的键盘来定制不同的适配文件并统一集成到系统中;
(3)修改系统默认的适配文件,以键盘的按钮功能为优先映射;
(4)在使用云电脑时使用单独的适配文件,云电脑的适配文件跟其他应用的区别避免相互干扰。
每种方案都有其对应的优缺点,比如方案一,部分终端设备存在键值的缺失和重复,如果只是在应用端进行适配,这部分按键依旧无法很好的支持;方案二中通过新增需要适配键盘的keylayout文件,那这可能会导致云电脑支持的键盘数量变得非常有限,同时也会导致适配测试工作量膨胀;方案三修改系统默认的适配文件,可能会导致原本的部分遥控器按键会出现错误;而如果使用方案四,则需要对Android系统底层键盘适配文件匹配流程进行完全重构,适配工作量巨大。
综合以上各个方案的优缺点,考虑到遥控器和键盘的按键重合较少,同时遥控器的按键键值一般也都是标准键值,因此最终选择了方案3作为云电脑键盘的适配方案,同时要确保适配的所有按键键值全部都是标准键值。
在确定了适配方案之后,就需要对所有终端中的Generic.kl文件进行修改,逐项对比其注册的键值跟云电脑使用要求的标准键值,完成所有适配终端的键盘适配。
Part 04
鼠标适配
在Android系统中,通过实时检测系统的onGenericMotionEvent方法,来识别鼠标的滑动和点击。在onGenericMotionEvent方法中通过MotionEvent中的action值来区别鼠标左键点击、右键点击、鼠标滑动等不同的操作方法。终端设备在鼠标操作上,其返回值基本保持统一,因此基本无需额外适配。
Part 05
虚拟键鼠方案
由于每款终端设备在适配云电脑时基本都需要额外对键盘的键值进行适配,因此使用手机、pad作为外部远程的操作设备来模拟实际的键鼠,对云电脑进行操作就很有意义。
虚拟键鼠的方法主要有2个:
(1)在局域网内构建通信服务,在移动端应用直接通过扫描二维码等方式连接通道后,通过发送自定义键鼠指令,云电脑将这些指令转化为实际需要的操作指令,完成云电脑的操作;
(2)通过蓝牙HID,两台设备连接蓝牙后,在移动端发送蓝牙HID命令进行云电脑的操作。
由于蓝牙HID需要两边的设备都支持蓝牙,且要求的系统版本较高,蓝牙连接对于很多用户成本也更高,因此选择方案一作为虚拟键鼠方案。
方案一中需要在终端上建立一个稳定的数据通道,这个数据通道可以使用WebSocket。在鼠标点击和滑动时,通道中需要传输大量的数据,因此可以使用protobuf作为数据通道中传输的数据格式。Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。
移动端在向大屏端发送鼠标数据时,需要将用户的操作手势,拆解为最基础的按键按下、抬起、移动等操作,然后将这些操作转化为操作数据,再对数据进行发送。举个例子,比如一次普通的鼠标左键点击操作,需要将点击操作,细分为左键按下,左键抬起2个事件;再比如一次左键点击拖动操作,需要这个操作,细分为左键按下、鼠标移动、左键抬起事件3个事件。
除了鼠标和键盘这两个最常用的两个设备外,其他不同类型的输入设备,比如遥控器、游戏手柄都可以通过这种方式,实现对云电脑的操作,从而避免了大量适配工作。