触控设备

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

Android 支持各种触摸屏和触摸板,包括基于手写笔的数字化板。

触摸屏是与显示器相关联的触摸设备,使得用户具有直接操纵屏幕上的项目的印象。

触摸板是与显示器无关的触摸设备,例如数字化板。触摸板通常用于指向或用于绝对间接定位或用户界面的基于手势的控制。

触摸设备可能具有功能类似于鼠标按钮的按钮。

触摸设备有时可以使用各种不同的工具(例如手指或手写笔)进行操作,具体取决于底层触摸传感器技术。

触摸设备有时用于实现虚拟键。例如,在某些 Android 设备上,触摸屏传感器区域延伸到显示屏边缘之外,并作为触摸感应键盘的一部分起到双重作用。

由于触摸设备种类繁多,Android 依赖大量的配置属性来描述每个设备的特性和期望的行为。

触控设备分类

如果满足以下两个条件,则输入设备被归类为多点触控设备:

  • 输入设备报告存在ABS_MT_POSITION_XABS_MT_POSITION_Y绝对轴。

  • 输入设备没有任何游戏手柄按钮。此条件解决了某些游戏手柄的歧义,这些游戏手柄报告轴的代码与 MT 轴的代码重叠。

如果满足以下两个条件,则输入设备被归类为单点触摸设备:

  • 输入设备不属于多点触控设备。输入设备要么被归类为单点触控设备,要么被归类为多点触控设备,而不能同时归为两者。

  • 输入设备报告ABS_XABS_Y绝对轴的存在,以及BTN_TOUCH键码的存在。

一旦输入设备被归类为触摸设备,就可以通过尝试加载设备的虚拟键映射文件来确定虚拟键的存在。如果虚拟键映射可用,则还会加载设备的键布局文件。

请参阅以下有关虚拟键映射文件的位置和格式的部分。

接下来,系统加载触摸设备的输入设备配置文件。

所有内置触摸设备都应该有输入设备配置文件。如果不存在输入设备配置文件,系统将选择适用于典型通用触摸外围设备(例如外部 USB 或蓝牙 HID 触摸屏或触摸板)的默认配置。这些默认值不是为内置触摸屏设计的,很可能会导致不正确的行为。

加载输入设备配置后,系统会将输入设备分类为触摸屏触摸板指针设备。

  • 触摸屏设备用于直接操作屏幕上的对象。由于用户直接触摸屏幕,系统不需要任何额外的提示来指示正在操作的对象。

  • 触摸板设备用于向应用程序提供关于给定传感器区域上的触摸的绝对定位信息。它可能对数字化板有用。

  • 指针设备用于使用光标间接操作屏幕上的对象。手指被解释为多点触控指针手势。其他工具(例如手写笔)使用绝对位置进行解释。

    有关详细信息,请参阅间接多点触控指针手势

以下规则用于将输入设备分类为触摸屏触摸板指针设备。

  • 如果设置了touch.deviceType属性,则设备类型将按指示设置。

  • 如果输入设备报告存在INPUT_PROP_DIRECT输入属性(通过EVIOCGPROP ioctl),则设备类型将设置为touch screen 。此条件假定直接输入触摸设备连接到也已连接的显示器。

  • 如果输入设备报告存在INPUT_PROP_POINTER输入属性(通过EVIOCGPROP ioctl),则设备类型将设置为pointer

  • 如果输入设备报告存在REL_XREL_Y相对轴,则设备类型将设置为touch pad 。此条件解决了由鼠标和触摸板组成的输入设备的歧义。在这种情况下,触摸板将不会用于控制指针,因为鼠标已经控制了它。

  • 否则,设备类型将被设置为pointer 。此默认设置确保未指定任何其他特殊用途的触摸板将用于控制指针。

纽扣

按钮是可选的控件,应用程序可以使用它们来执行附加功能。触摸设备上的按钮与鼠标按钮的行为类似,主要用于指针式触摸设备或手写笔。

支持以下按钮:

  • BTN_LEFT :映射到MotionEvent.BUTTON_PRIMARY

  • BTN_RIGHT :映射到MotionEvent.BUTTON_SECONDARY

  • BTN_MIDDLE :映射到MotionEvent.BUTTON_MIDDLE

  • BTN_BACKBTN_SIDE :映射到MotionEvent.BUTTON_BACK 。按下此按钮还会合成按键代码为KeyEvent.KEYCODE_BACK的按键。

  • BTN_FORWARDBTN_EXTRA :映射到MotionEvent.BUTTON_FORWARD 。按下此按钮还会合成按键代码为KeyEvent.KEYCODE_FORWARD的按键。

  • BTN_STYLUS :映射到MotionEvent.BUTTON_SECONDARY

  • BTN_STYLUS2 :映射到MotionEvent.BUTTON_TERTIARY

工具和工具类型

工具是手指、手写笔或其他用于与触摸设备交互的装置。一些触摸设备可以区分不同类型的工具。

在 Android 的其他地方,如在MotionEvent API 中,工具通常称为指针

支持以下工具类型:

  • BTN_TOOL_FINGERMT_TOOL_FINGER :映射到MotionEvent.TOOL_TYPE_FINGER

  • BTN_TOOL_PENMT_TOOL_PEN :映射到MotionEvent.TOOL_TYPE_STYLUS

  • BTN_TOOL_RUBBER :映射到MotionEvent.TOOL_TYPE_ERASER

  • BTN_TOOL_BRUSH :映射到MotionEvent.TOOL_TYPE_STYLUS

  • BTN_TOOL_PENCIL :映射到MotionEvent.TOOL_TYPE_STYLUS

  • BTN_TOOL_AIRBRUSH :映射到MotionEvent.TOOL_TYPE_STYLUS

  • BTN_TOOL_MOUSE :映射到MotionEvent.TOOL_TYPE_MOUSE

  • BTN_TOOL_LENS :映射到MotionEvent.TOOL_TYPE_MOUSE

  • BTN_TOOL_DOUBLETAPBTN_TOOL_TRIPLETAPBTN_TOOL_QUADTAP :映射到MotionEvent.TOOL_TYPE_FINGER

悬停与触摸工具

工具可以与触摸设备接触,也可以在其范围内并悬停在其上方。并非所有触摸设备都能够感测到悬停在触摸设备上方的工具的存在。那些这样做的,例如基于 RF 的手写笔数字化仪,通常可以检测工具何时在数字化仪的有限范围内。

InputReader组件负责区分触摸工具和悬停工具。同样,触摸工具和悬停工具以不同的方式报告给应用程序。

使用MotionEvent.ACTION_DOWNMotionEvent.ACTION_MOVEMotionEvent.ACTION_DOWNMotionEvent.ACTION_POINTER_DOWNMotionEvent.ACTION_POINTER_UP将触摸工具作为触摸事件报告给应用程序。

使用MotionEvent.ACTION_HOVER_ENTERMotionEvent.ACTION_HOVER_MOVEMotionEvent.ACTION_HOVER_EXIT将悬停工具作为通用运动事件报告给应用程序。

触摸设备驱动程序要求

  1. 触摸设备驱动程序应该只为它们实际支持的轴和按钮注册轴和键代码。注册过多的轴或键代码可能会混淆设备分类算法或导致系统错误地检测设备的功能。

    例如,如果设备报告BTN_TOUCH键码,系统将假定BTN_TOUCH将始终用于指示工具是否实际触摸屏幕。因此,不应使用BTN_TOUCH来指示工具仅在范围内和悬停。

  2. 单点触控设备使用以下 Linux 输入事件:

    • ABS_X :(必需)报告工具的 X 坐标。

    • ABS_Y :(必需)报告工具的 Y 坐标。

    • ABS_PRESSURE :(可选)报告施加到工具尖端的物理压力或触摸触点的信号强度。

    • ABS_TOOL_WIDTH :(可选)报告触摸触点或工具本身的横截面积或宽度。

    • ABS_DISTANCE :(可选)报告工具与触摸设备表面的距离。

    • ABS_TILT_X :(可选)报告工具从触摸设备表面沿 X 轴的倾斜度。

    • ABS_TILT_Y :(可选)报告工具从触摸设备表面沿 Y 轴的倾斜度。

    • BTN_TOUCH :(必需)指示工具是否正在接触设备。

    • BTN_LEFTBTN_RIGHTBTN_MIDDLEBTN_BACKBTN_SIDEBTN_FORWARDBTN_EXTRABTN_STYLUSBTN_STYLUS2 :(可选)报告按钮状态。

    • BTN_TOOL_FINGER , BTN_TOOL_PEN , BTN_TOOL_RUBBER , BTN_TOOL_BRUSH , BTN_TOOL_PENCIL , BTN_TOOL_AIRBRUSH , BTN_TOOL_MOUSE , BTN_TOOL_LENS , BTN_TOOL_DOUBLETAP , BTN_TOOL_TRIPLETAP , BTN_TOOL_QUADTAP报告工具类型:(可选)

  3. 多点触控设备使用以下 Linux 输入事件:

    • ABS_MT_POSITION_X :(必需)报告工具的 X 坐标。

    • ABS_MT_POSITION_Y :(必需)报告工具的 Y 坐标。

    • ABS_MT_PRESSURE :(可选)报告施加到工具尖端的物理压力或触摸接触的信号强度。

    • ABS_MT_TOUCH_MAJOR :(可选)报告触摸接触的横截面积,或触摸接触的较长尺寸的长度。

    • ABS_MT_TOUCH_MINOR :(可选)报告触摸接触的较短尺寸的长度。如果ABS_MT_TOUCH_MAJOR正在报告面积测量,则不应使用该轴。

    • ABS_MT_WIDTH_MAJOR :(可选)报告工具本身的横截面积,或工具本身较长尺寸的长度。如果工具本身的尺寸未知,则不应使用此轴。

    • ABS_MT_WIDTH_MINOR :(可选)报告工具本身较短尺寸的长度。如果ABS_MT_WIDTH_MAJOR正在报告面积测量值或工具本身的尺寸未知,则不应使用该轴。

    • ABS_MT_ORIENTATION :(可选)报告工具的方向。

    • ABS_MT_DISTANCE :(可选)报告工具与触摸设备表面的距离。

    • ABS_MT_TOOL_TYPE :(可选)工具类型报告为MT_TOOL_FINGERMT_TOOL_PEN

    • ABS_MT_TRACKING_ID :(可选)报告工具的跟踪 ID。跟踪 ID 是一个任意的非负整数,用于在多个工具处于活动状态时独立地识别和跟踪每个工具。例如,当多个手指触摸设备时,每个手指都应分配一个不同的跟踪 ID,只要手指保持接触,就会使用该 ID。当相关工具移出范围时,跟踪 ID 可能会被重复使用。

    • ABS_MT_SLOT :(可选)在使用 Linux 多点触控协议“B”时报告工具的插槽 ID。有关详细信息,请参阅 Linux 多点触控协议文档。

    • BTN_TOUCH :(必需)指示工具是否正在接触设备。

    • BTN_LEFTBTN_RIGHTBTN_MIDDLEBTN_BACKBTN_SIDEBTN_FORWARDBTN_EXTRABTN_STYLUSBTN_STYLUS2 :(可选)报告按钮状态。

    • BTN_TOOL_FINGER , BTN_TOOL_PEN , BTN_TOOL_RUBBER , BTN_TOOL_BRUSH , BTN_TOOL_PENCIL , BTN_TOOL_AIRBRUSH , BTN_TOOL_MOUSE , BTN_TOOL_LENS , BTN_TOOL_DOUBLETAP , BTN_TOOL_TRIPLETAP , BTN_TOOL_QUADTAP报告工具类型:(可选)

  4. 如果同时定义了单点触摸和多点触摸协议的轴,则将仅使用多点触摸轴,而忽略单点触摸轴。

  5. ABS_XABS_YABS_MT_POSITION_XABS_MT_POSITION_Y轴的最小值和最大值以设备特定的表面单位定义设备活动区域的边界。在触摸屏的情况下,活动区域描述了触摸设备实际覆盖显示屏的部分。

    对于触摸屏,系统会根据以下计算自动对上报的以表面为单位的触摸位置进行插值,得到以显示像素为单位的触摸位置:

    displayX = (x - minX) * displayWidth / (maxX - minX + 1)
    displayY = (y - minY) * displayHeight / (maxY - minY + 1)
    

    触摸屏可能会报告报告的活动区域之外的触摸。

    在活动区域​​外启动的触摸不会传送到应用程序,但可用于虚拟键。

    在活动区域​​内启动的触摸,或进入和离开显示区域的触摸被传送到应用程序。因此,如果触摸在应用程序的边界内开始,然后移出活动区域,则应用程序可能会收到显示坐标为负或超出显示边界的触摸事件。这是预期的行为。

    触摸设备永远不应将触摸坐标限制在活动区域​​的边界内。如果触摸离开活动区域,则应将其报告为活动区域外,或者根本不报告。

    例如,如果用户的手指在触摸屏的左上角附近触摸,它可能会报告坐标 (minX, minY)。如果手指继续移动到活动区域之外,触摸屏应该开始报告坐标小于 minX 和 minY 的坐标,例如 (minX - 2, minY - 3),或者它应该完全停止报告触摸。换句话说,当用户的手指真正触摸到活动区域之外时,触摸屏不应报告 (minX, minY)。

    将触摸坐标夹紧到显示边缘会在屏幕边缘周围创建一个人为的硬边界,这会阻止系统平滑地跟踪进入或离开显示区域边界的运动。

  6. ABS_PRESSUREABS_MT_PRESSURE报告的值(如果有的话)在工具接触设备时必须为非零,否则为零以指示工具悬停。

    报告压力信息是可选的,但强烈建议。应用程序可以使用压力信息来实现压敏绘图等效果。

  7. 当工具接触设备时, ABS_TOOL_WIDTHABS_MT_TOUCH_MAJORABS_MT_TOUCH_MINORABS_MT_WIDTH_MAJORABS_MT_WIDTH_MINOR报告的值应为非零,否则为零,但这不是必需的。例如,触摸设备可能能够测量手指触摸接触的尺寸,但不能测量手写笔触摸接触的尺寸。

    报告大小信息是可选的,但强烈建议。应用程序可以使用压力信息来实现大小敏感绘图和其他效果。

  8. 当工具接触设备时, ABS_DISTANCEABS_MT_DISTANCE报告的值应接近零。即使工具直接接触,该距离也可能保持非零。报告的确切值取决于硬件测量距离的方式。

    报告距离信息是可选的,但建议用于手写笔设备。

  9. 当工具垂直于设备时, ABS_TILT_XABS_TILT_Y报告的值应为零。非零倾斜表示工具保持在倾斜状态。

    假定沿 X 轴和 Y 轴的倾斜角以与垂直线的度数为单位指定。每个轴的中心点(完全垂直)由(max + min) / 2给出。小于中心点的值表示向上或向左倾斜,大于中心点的值表示向下或向右倾斜。

    InputReader将 X 和 Y 倾斜分量转换为范围从 0 到PI / 2弧度的垂直倾斜角和范围从-PIPI弧度的平面方向角。这种表示导致方向描述与用于描述手指触摸的内容兼容。

    报告倾斜信息是可选的,但建议用于手写笔设备。

  10. 如果工具类型由ABS_MT_TOOL_TYPE报告,它将取代BTN_TOOL_*报告的任何工具类型信息。如果根本没有可用的工具类型信息,则工具类型默认为MotionEvent.TOOL_TYPE_FINGER

  11. 根据以下条件确定工具处于活动状态:

    • 使用单点触控协议时,如果BTN_TOUCHBTN_TOOL_*为 1,则该工具处于活动状态。

      此条件意味着InputReader至少需要了解一些有关工具性质的信息,无论是接触还是工具类型。如果没有可用信息,则假定该工具处于非活动状态(超出范围)。

    • 使用多点触控协议“A”时,只要该工具出现在最近的同步报告中,它就会处于活动状态。当该工具停止出现在同步报告中时,它就不复存在了。

    • 使用多点触控协议“B”时,只要有活动插槽,该工具就会处于活动状态。当插槽被清除时,该工具将不复存在。

  12. 根据以下条件确定工具悬停:

    • 如果工具是BTN_TOOL_MOUSEBTN_TOOL_LENS ,则工具不会悬停,即使以下任一条件为真。

    • 如果工具处于活动状态并且驱动程序报告压力信息,并且报告的压力为零,则工具悬停。

    • 如果该工具处于活动状态且驱动程序支持BTN_TOUCH键码且BTN_TOUCH的值为零,则该工具处于悬停状态。

  13. InputReader支持多点触控协议“A”和“B”。新的驱动程序应该使用“B”协议,但两者都可以。

  14. 从 Android Ice Cream Sandwich 4.0 开始,可能需要更改触摸屏驱动程序以符合 Linux 输入协议规范。

    可能需要进行以下更改:

    • 当工具变为非活动状态(手指“向上”)时,它应该停止出现在后续的多点触控同步报告中。当所有工具都变为非活动状态(所有手指都“向上”)时,驱动程序应发送一个空的同步报告数据包,例如SYN_MT_REPORT后跟SYN_REPORT

      以前版本的 Android 期望通过发送压力值 0 来报告“向上”事件。旧行为与 Linux 输入协议规范不兼容,不再受支持。

    • 应使用ABS_MT_PRESSURE报告物理压力或信号强度信息。

      以前版本的 Android 从ABS_MT_TOUCH_MAJOR检索压力信息。旧行为与 Linux 输入协议规范不兼容,不再受支持。

    • 应使用ABS_MT_TOUCH_MAJOR报告触摸大小信息。

      以前版本的 Android 从ABS_MT_TOOL_MAJOR检索尺寸信息。旧行为与 Linux 输入协议规范不兼容,不再受支持。

    触摸设备驱动程序不再需要特定于 Android 的自定义设置。依靠标准的 Linux 输入协议,Android 可以使用未修改的驱动程序支持更广泛的触摸外围设备,例如外部 HID 多点触控触摸屏。

触摸设备操作

下面简单总结一下Android上的触摸设备操作。

  1. EventHubevdev驱动程序读取原始事件。

  2. InputReader使用原始事件并更新有关每个工具的位置和其他特征的内部状态。它还跟踪按钮状态。

  3. 如果 BACK 或 FORWARD 按钮被按下或释放, InputReader会通知InputDispatcher有关按键事件。

  4. InputReader确定是否发生了虚拟按键按下。如果是,它会通知InputDispatcher有关按键事件。

  5. InputReader确定触摸是否在显示范围内启动。如果是,它会通知InputDispatcher关于触摸事件。

  6. 如果没有触摸工具但至少有一个悬停工具,则InputReader将悬停事件通知给InputDispatcher

  7. 如果触摸设备类型是pointerInputReader执行指针手势检测,相应地移动指针和点,并通知InputDispatcher有关指针事件。

  8. InputDispatcher使用WindowManagerPolicy来确定是否应分派事件以及是否应唤醒设备。然后, InputDispatcher将事件传递给适当的应用程序。

触摸设备配置

触摸设备行为由设备的轴、按钮、输入属性、输入设备配置、虚拟键映射和键布局决定。

有关参与键盘配置的文件的更多详细信息,请参阅以下部分:

特性

系统依赖于许多输入设备配置属性来配置和校准触摸设备行为。

原因之一是触摸设备的设备驱动程序经常使用特定于设备的单元来报告触摸的特征。

例如,许多触摸设备使用内部设备特定的尺度来测量触摸接触面积,例如触摸触发的传感器节点总数。这个原始尺寸值对应用程序没有意义,因为它们需要了解触摸设备传感器节点的物理尺寸和其他特性。

该系统使用输入设备配置文件中编码的校准参数来解码、转换和规范化触摸设备报告的值,使其成为应用程序可以理解的更简单的标准表示形式。

文档约定

出于文档目的,我们将使用以下约定来描述系统在校准过程中使用的值。

原始轴值

以下表达式表示触摸设备驱动程序报告为EV_ABS事件的原始值。

raw.x
ABS_XABS_MT_POSITION_X轴的值。
raw.y
ABS_YABS_MT_POSITION_Y轴的值。
raw.pressure
ABS_PRESSUREABS_MT_PRESSURE轴的值,如果不可用则为 0。
raw.touchMajor
ABS_MT_TOUCH_MAJOR轴的值,如果不可用则为 0。
raw.touchMinor
ABS_MT_TOUCH_MINOR轴的值,如果不可用, raw.touchMajor
raw.toolMajor
ABS_TOOL_WIDTHABS_MT_WIDTH_MAJOR轴的值,如果不可用则为 0。
raw.toolMinor
ABS_MT_WIDTH_MINOR轴的值,如果不可用, raw.toolMajor
raw.orientation
ABS_MT_ORIENTATION轴的值,如果不可用则为 0。
raw.distance
ABS_DISTANCEABS_MT_DISTANCE轴的值,如果不可用则为 0。
raw.tiltX
ABS_TILT_X轴的值,如果不可用则为 0。
raw.tiltY
ABS_TILT_Y轴的值,如果不可用则为 0。

原始轴范围

以下表达式表示原始值的范围。它们是通过为每个轴调用EVIOCGABS ioctl 获得的。

raw.*.min
原始轴的包含最小值。
raw.*.max
原始轴的包含最大值。
raw.*.range
相当于raw.*.max - raw.*.min
raw.*.fuzz
原始轴的精度。例如。 fuzz = 1 表示值精确到 +/- 1 个单位。
raw.width
触摸区域包含的宽度,相当于raw.x.range + 1
raw.height
触摸区域包含的高度,相当于raw.y.range + 1

输出范围

以下表达式表示输出坐标系的特征。该系统使用线性插值将触摸位置信息从触摸设备使用的表面单位转换为将报告给显示像素等应用程序的输出单位。

output.width
输出宽度。对于触摸屏(与显示器相关联),这是以像素为单位的显示宽度。对于触摸板(不与显示器关联),输出宽度等于raw.width ,表示不会执行插值。
output.height
输出高度。对于触摸屏(与显示器相关联),这是以像素为单位的显示高度。对于触摸板(与显示器无关),输出高度等于raw.height ,表示不会执行插值。
output.diag
输出坐标系的对角线长度,相当于sqrt(output.width ^2 + output.height ^2)

基本配置

触摸输入映射器使用输入设备配置文件中的许多配置属性来指定校准值。下表描述了一些通用配置属性。所有其他属性以及它们用于校准的字段将在以下部分中进行描述。

touch.deviceType

定义: touch.deviceType = touchScreen | touchPad | pointer | default

指定触摸设备类型。

  • 如果值为touchScreen ,则触摸设备是与显示器关联的触摸屏。

  • 如果值为touchPad ,则触摸设备是与显示器无关的触摸板。

  • 如果值为pointer ,则触摸设备是与显示器无关的触摸板,其动作用于间接多点触摸指针手势

  • 如果取值为default ,系统会根据分类算法自动检测设备类型。

有关设备类型如何影响触摸设备行为的更多详细信息,请参阅分类部分。

在 Honeycomb 之前,所有触摸设备都被认为是触摸屏。

touch.orientationAware

定义: touch.orientationAware = 0 | 1

指定触摸设备是否应对显示方向变化作出反应。

  • 如果该值为1 ,则只要显示方向发生变化,触摸设备报告的触摸位置就会旋转。

  • 如果该值为0 ,则触摸设备报告的触摸位置不受显示方向更改的影响。

如果设备是触摸屏,则默认值为1 ,否则为0

系统区分内部和外部触摸屏和显示器。方向感知内部触摸屏根据内部显示器的方向旋转。方向感知外部触摸屏基于外部显示器的方向旋转。

方向感知用于支持 Nexus One 等设备上触摸屏的旋转。例如,当设备从其自然方向顺时针旋转 90 度时,触摸的绝对位置将被重新映射,使得触摸屏绝对坐标系左上角的触摸被报告为左上角的触摸显示器旋转坐标系的角点。这样做是为了使用与应用程序用来绘制其视觉元素的坐标系相同的坐标系来报告触摸。

在 Honeycomb 之前,所有触摸设备都被认为是方向感知的。

touch.gestureMode

定义: touch.gestureMode = pointer | spots | default

指定指针手势的呈现模式。此配置属性仅在触摸设备的类型为pointer时才相关。

  • 如果值为pointer ,则触摸板手势将通过类似于鼠标指针的光标呈现。

  • 如果值为spots ,则触摸板手势由表示手势质心的锚点和表示各个手指位置的一组圆形点表示。

当设置了INPUT_PROP_SEMI_MT输入属性时,默认值为pointer ,否则为spots

XY字段

X 和 Y 字段提供接触区域中心的位置信息。

计算

计算很简单:来自触摸驱动器的位置信息被线性插值到输出坐标系。

xScale = output.width / raw.width
yScale = output.height / raw.height

If not orientation aware or screen rotation is 0 degrees:
output.x = (raw.x - raw.x.min) * xScale
output.y = (raw.y - raw.y.min) * yScale
Else If rotation is 90 degrees:
    output.x = (raw.y - raw.y.min) * yScale
    output.y = (raw.x.max - raw.x) * xScale
Else If rotation is 180 degrees:
    output.x = (raw.x.max - raw.x) * xScale
    output.y = (raw.y.max - raw.y) * yScale
Else If rotation is 270 degrees:
    output.x = (raw.y.max - raw.y) * yScale
    output.y = (raw.x - raw.x.min) * xScale
End If

TouchMajorTouchMinorToolMajorToolMinorSize字段

TouchMajorTouchMinor字段以输出单位(像素)描述接触区域的近似尺寸。

ToolMajorToolMinor字段以输出单位(像素)描述工具本身的近似尺寸。

Size字段描述了相对于触摸设备可以感应到的最大可能触摸的标准化触摸大小。最小可能的归一化尺寸为 0.0(无接触,或者无法测量),最大可能的归一化尺寸为 1.0(传感器区域饱和)。

当可以测量近似长度和宽度时, TouchMajor字段指定接触区域的较长维度, TouchMinor字段指定接触区域的较短维度。当只能测量接触区域的近似直径时, TouchMajorTouchMinor字段将相等。

同样, ToolMajor字段指定较长的尺寸,而ToolMinor字段指定工具横截面积的较短尺寸。

如果触摸尺寸不可用但工具尺寸可用,则工具尺寸将设置为等于触摸尺寸。相反,如果工具尺寸不可用但触摸尺寸可用,则触摸尺寸将设置为等于工具尺寸。

触摸设备以各种方式测量或报告触摸尺寸和工具尺寸。当前的实现支持三种不同类型的测量:直径、面积和表面单位的几何边界框。

touch.size.calibration

定义: touch.size.calibration = none | geometric | diameter | area | default

指定触摸驱动程序用于报告触摸大小和工具大小的测量类型。

  • 如果值为none ,则大小设置为零。

  • 如果值为geometric ,则假定大小以与位置相同的表面单位指定,因此它以相同的方式缩放。

  • 如果值为diameter ,则假定大小与触摸或工具的直径(宽度)成正比。

  • 如果值为area ,则假定大小与触摸或工具的面积成比例。

  • 如果值为default ,如果raw.touchMajorraw.toolMajor轴可用,系统将使用geometric校准,否则使用none校准。

touch.size.scale

定义: touch.size.scale = <一个非负浮点数>

指定校准中使用的常数比例因子。

默认值为1.0

touch.size.bias

定义: touch.size.bias = <一个非负浮点数>

指定校准中使用的恒定偏差值。

默认值为0.0

touch.size.isSummed

定义: touch.size.isSummed = 0 | 1

指定是将大小报告为所有活动接触的大小总和,还是针对每个接触单独报告。

  • 如果该值为1 ,则报告的大小将除以使用前的联系人数量。

  • 如果值为0 ,则报告的大小将按原样使用。

默认值为0

某些触摸设备,尤其是“Semi-MT”设备无法区分多个触点的各个尺寸,因此它们会报告代表其总面积或宽度的尺寸测量值。对于此类设备,此属性仅应设置为1 。如有疑问,请将此值设置为0

计算

TouchMajorTouchMinorToolMajorToolMinorSize字段的计算取决于指定的校准参数。

If raw.touchMajor and raw.toolMajor are available:
    touchMajor = raw.touchMajor
    touchMinor = raw.touchMinor
    toolMajor = raw.toolMajor
    toolMinor = raw.toolMinor
Else If raw.touchMajor is available:
    toolMajor = touchMajor = raw.touchMajor
    toolMinor = touchMinor = raw.touchMinor
Else If raw.toolMajor is available:
    touchMajor = toolMajor = raw.toolMajor
    touchMinor = toolMinor = raw.toolMinor
Else
    touchMajor = toolMajor = 0
    touchMinor = toolMinor = 0
    size = 0
End If

size = avg(touchMajor, touchMinor)

If touch.size.isSummed == 1:
    touchMajor = touchMajor / numberOfActiveContacts
    touchMinor = touchMinor / numberOfActiveContacts
    toolMajor = toolMajor / numberOfActiveContacts
    toolMinor = toolMinor / numberOfActiveContacts
    size = size / numberOfActiveContacts
End If

If touch.size.calibration == "none":
    touchMajor = toolMajor = 0
    touchMinor = toolMinor = 0
    size = 0
Else If touch.size.calibration == "geometric":
    outputScale = average(output.width / raw.width, output.height / raw.height)
    touchMajor = touchMajor * outputScale
    touchMinor = touchMinor * outputScale
    toolMajor = toolMajor * outputScale
    toolMinor = toolMinor * outputScale
Else If touch.size.calibration == "area":
    touchMajor = sqrt(touchMajor)
    touchMinor = touchMajor
    toolMajor = sqrt(toolMajor)
    toolMinor = toolMajor
Else If touch.size.calibration == "diameter":
    touchMinor = touchMajor
    toolMinor = toolMajor
End If

If touchMajor != 0:
    output.touchMajor = touchMajor * touch.size.scale + touch.size.bias
Else
    output.touchMajor = 0
End If

If touchMinor != 0:
    output.touchMinor = touchMinor * touch.size.scale + touch.size.bias
Else
    output.touchMinor = 0
End If

If toolMajor != 0:
    output.toolMajor = toolMajor * touch.size.scale + touch.size.bias
Else
    output.toolMajor = 0
End If

If toolMinor != 0:
    output.toolMinor = toolMinor * touch.size.scale + touch.size.bias
Else
    output.toolMinor = 0
End If

output.size = size

Pressure

Pressure字段将施加到触摸设备的近似物理压力描述为介于 0.0(无触摸)和 1.0(最大力)之间的归一化值。

零压力表示工具悬停。

touch.pressure.calibration

定义: touch.pressure.calibration = none | physical | amplitude | default

指定触摸驱动程序用来报告压力的测量类型。

  • 如果值为none ,则压力未知,因此触摸时设置为 1.0,悬停时设置为 0.0。

  • 如果该值为physical ,则假定压力轴测量施加到触摸板上的实际物理压力强度。

  • If the value is amplitude , the pressure axis is assumed to measure the signal amplitude, which is related to the size of the contact and the pressure applied.

  • If the value is default , the system uses the physical calibration if the pressure axis available, otherwise uses none .

touch.pressure.scale

Definition: touch.pressure.scale = <a non-negative floating point number>

Specifies a constant scale factor used in the calibration.

The default value is 1.0 / raw.pressure.max .

Calculation

The calculation of the Pressure field depends on the specified calibration parameters.

If touch.pressure.calibration == "physical" or "amplitude":
    output.pressure = raw.pressure * touch.pressure.scale
Else
    If hovering:
        output.pressure = 0
    Else
        output.pressure = 1
    End If
End If

Orientation and Tilt Fields

The Orientation field describes the orientation of the touch and tool as an angular measurement. An orientation of 0 indicates that the major axis is oriented vertically, -PI/2 indicates that the major axis is oriented to the left, PI/2 indicates that the major axis is oriented to the right. When a stylus tool is present, the orientation range may be described in a full circle range from -PI or PI .

The Tilt field describes the inclination of the tool as an angular measurement. A tilt of 0 indicates that the tool is perpendicular to the surface. A tilt of PI/2 indicates that the tool is flat on the surface.

touch.orientation.calibration

Definition: touch.orientation.calibration = none | interpolated | vector | default

Specifies the kind of measurement used by the touch driver to report the orientation.

  • If the value is none , the orientation is unknown so it is set to 0.

  • If the value is interpolated , the orientation is linearly interpolated such that a raw value of raw.orientation.min maps to -PI/2 and a raw value of raw.orientation.max maps to PI/2 . The center value of (raw.orientation.min + raw.orientation.max) / 2 maps to 0 .

  • If the value is vector , the orientation is interpreted as a packed vector consisiting of two signed 4-bit fields. This representation is used on Atmel Object Based Protocol parts. When decoded, the vector yields an orientation angle and confidence magnitude. The confidence magnitude is used to scale the size information, unless it is geometric.

  • If the value is default , the system uses the interpolated calibration if the orientation axis available, otherwise uses none .

Calculation

The calculation of the Orientation and Tilt fields depends on the specified calibration parameters and available input.

If touch.tiltX and touch.tiltY are available:
    tiltXCenter = average(raw.tiltX.min, raw.tiltX.max)
    tiltYCenter = average(raw.tiltY.min, raw.tiltY.max)
    tiltXAngle = (raw.tiltX - tiltXCenter) * PI / 180
    tiltYAngle = (raw.tiltY - tiltYCenter) * PI / 180
    output.orientation = atan2(-sin(tiltXAngle), sinf(tiltYAngle))
    output.tilt = acos(cos(tiltXAngle) * cos(tiltYAngle))
Else If touch.orientation.calibration == "interpolated":
    center = average(raw.orientation.min, raw.orientation.max)
    output.orientation = PI / (raw.orientation.max - raw.orientation.min)
    output.tilt = 0
Else If touch.orientation.calibration == "vector":
    c1 = (raw.orientation & 0xF0) >> 4
    c2 = raw.orientation & 0x0F

    If c1 != 0 or c2 != 0:
        If c1 >= 8 Then c1 = c1 - 16
        If c2 >= 8 Then c2 = c2 - 16
        angle = atan2(c1, c2) / 2
        confidence = sqrt(c1*c1 + c2*c2)

        output.orientation = angle

        If touch.size.calibration == "diameter" or "area":
            scale = 1.0 + confidence / 16
            output.touchMajor *= scale
            output.touchMinor /= scale
            output.toolMajor *= scale
            output.toolMinor /= scale
        End If
    Else
        output.orientation = 0
    End If
    output.tilt = 0
Else
    output.orientation = 0
    output.tilt = 0
End If

If orientation aware:
    If screen rotation is 90 degrees:
        output.orientation = output.orientation - PI / 2
    Else If screen rotation is 270 degrees:
        output.orientation = output.orientation + PI / 2
    End If
End If

Distance Field

The Distance field describes the distance between the tool and the touch device surface. A value of 0.0 indicates direct contact and larger values indicate increasing distance from the surface.

touch.distance.calibration

Definition: touch.distance.calibration = none | scaled | default

Specifies the kind of measurement used by the touch driver to report the distance.

  • If the value is none , the distance is unknown so it is set to 0.

  • If the value is scaled , the reported distance is multiplied by a constant scale factor.

  • If the value is default , the system uses the scaled calibration if the distance axis available, otherwise uses none .

touch.distance.scale

Definition: touch.distance.scale = <a non-negative floating point number>

Specifies a constant scale factor used in the calibration.

The default value is 1.0 .

Calculation

The calculation of the Distance field depends on the specified calibration parameters.

If touch.distance.calibration == "scaled":
    output.distance = raw.distance * touch.distance.scale
Else
    output.distance = 0
End If

Example

# Input device configuration file for a touch screen that supports pressure,
# size and orientation.  The pressure and size scale factors were obtained
# by measuring the characteristics of the device itself and deriving
# useful approximations based on the resolution of the touch sensor and the
# display.
#
# Note that these parameters are specific to a particular device model.
# Different parameters will need to be used for other devices.

# Basic Parameters
touch.deviceType = touchScreen
touch.orientationAware = 1

# Size
# Based on empirical measurements, we estimate the size of the contact
# using size = sqrt(area) * 28 + 0.
touch.size.calibration = area
touch.size.scale = 28
touch.size.bias = 0
touch.size.isSummed = 0

# Pressure
# Driver reports signal strength as pressure.
#
# A normal index finger touch typically registers about 80 signal strength
# units although we don't expect these values to be accurate.
touch.pressure.calibration = amplitude
touch.pressure.scale = 0.0125

# Orientation
touch.orientation.calibration = vector

Compatibility Notes

The configuration properties for touch devices changed significantly in Android Ice Cream Sandwich 4.0. All input device configuration files for touch devices must be updated to use the new configuration properties.

Older touch device drivers may also need to be updated.

Virtual Key Map Files

Touch devices are often used to implement virtual keys.

There are several ways of doing this, depending on the capabilities of the touch controller. Some touch controllers can be directly configured to implement soft keys by setting firmware registers. Other times it is desirable to perform the mapping from touch coordinates to key codes in software.

When virtual keys are implemented in software, the kernel must export a virtual key map file called virtualkeys.<devicename> as a board property. For example, if the touch screen device drivers reports its name as "touchyfeely" then the virtual key map file must have the path /sys/board_properties/virtualkeys.touchyfeely .

A virtual key map file describes the coordinates and Linux key codes of virtual keys on the touch screen.

In addition to the virtual key map file, there must be a corresponding key layout file and key character map file to map the Linux key codes to Android key codes and to specify the type of the keyboard device (usually SPECIAL_FUNCTION ).

Syntax

A virtual key map file is a plain text file consisting of a sequence of virtual key layout descriptions either separated by newlines or by colons.

Comment lines begin with '#' and continue to the end of the line.

Each virtual key is described by 6 colon-delimited components:

  • 0x01 : A version code. Must always be 0x01 .
  • <Linux key code>: The Linux key code of the virtual key.
  • <centerX>: The X pixel coordinate of the center of the virtual key.
  • <centerY>: The Y pixel coordinate of the center of the virtual key.
  • <width>: The width of the virtual key in pixels.
  • <height>: The height of the virtual key in pixels.

All coordinates and sizes are specified in terms of the display coordinate system.

Here is a virtual key map file all written on one line.

# All on one line
0x01:158:55:835:90:55:0x01:139:172:835:125:55:0x01:102:298:835:115:55:0x01:217:412:835:95:55

The same virtual key map file can also be written on multiple lines.

# One key per line
0x01:158:55:835:90:55
0x01:139:172:835:125:55
0x01:102:298:835:115:55
0x01:217:412:835:95:55

In the above example, the touch screen has a resolution of 480x800. Accordingly, all of the virtual keys have a <centerY> coordinate of 835, which is a little bit below the visible area of the touch screen.

The first key has a Linux scan code of 158 ( KEY_BACK ), centerX of 55 , centerY of 835 , width of 90 and height of 55 .

Example

Virtual key map file: /sys/board_properties/virtualkeys.touchyfeely .

0x01:158:55:835:90:55
0x01:139:172:835:125:55
0x01:102:298:835:115:55
0x01:217:412:835:95:55

Key layout file: /system/usr/keylayout/touchyfeely.kl .

key 158 BACK
key 139 MENU
key 172 HOME
key 217 SEARCH

Key character map file: /system/usr/keychars/touchyfeely.kcm .

type SPECIAL_FUNCTION

Indirect Multi-touch Pointer Gestures

In pointer mode, the system interprets the following gestures:

  1. Single finger tap: click.

  2. Single finger motion: move the pointer.

  3. Single finger motion plus button presses: drag the pointer.

  4. Two finger motion both fingers moving in the same direction: drag the area under the pointer in that direction. The pointer itself does not move.

  5. Two finger motion both fingers moving towards each other or apart in different directions: pan/scale/rotate the area surrounding the pointer. The pointer itself does not move.

  6. Multiple finger motion: freeform gesture.

Palm rejection

As of Android 13, the system can automatically reject inputs from palms when the built-in framework is enabled. In-house, custom-built solutions are still supported, though they might need to be modified to return the TOOL_TYPE_PALM flag when a palm is detected. The built-in framework also works in conjunction with custom solutions.

The actual model looks at the first 90 ms of gesture data, at the current pointer, and at the surrounding pointers, then considers how far away from the edge of the display the touches are. It then determines, on a per-pointer basis, which of the pointers are palms. It also takes into account the size of each contact, as reported by TouchMajor and TouchMinor . The Android framework then removes the pointers that are marked as palms from the touch stream.

If a pointer was already sent to the apps, then the system either:

  • (If there are other active pointers) Cancels the pointer with ACTION_POINTER_UP and FLAG_CANCELED set.
  • (If this is the only pointer) Cancels the pointer with ACTION_CANCEL .

A public API, MotionEvent.FLAG_CANCELED , indicates that the current event shouldn't trigger user action. This flag is set for both ACTION_CANCEL and ACTION_POINTER_UP .

If the palm pointer wasn't sent to apps, then the system simply drops the pointer.

Enable palm rejection

  1. In your touch driver, use the input_abs_set_res macro to set the resolutions for the following fields (units are pixels per mm ):
    • ABS_MT_POSITION_X
    • ABS_MT_POSITION_Y
    • ABS_MT_TOUCH_MAJOR
    • ABS_MT_TOUCH_MINOR

    Support for ABS_MT_TOUCH_MINOR is optional. However, if your device does support it, make sure the resolution is set correctly.

  2. To confirm the fields are set correctly, run:
        $ adb shell getevent -li
    
  3. To enable the feature during runtime, run:
        $ adb shell device_config put input_native_boot palm_rejection_enabled 1
    
  4. Restart the system_server process.
         $ adb shell stop && adb shell start
        
  5. Confirm that adb shell dumpsys input shows that there are palm rejectors inside UnwantedInteractionBlocker . If it doesn't, check the input-related logs to find clues on what might be misconfigured.

    See the following example for reference:

    UnwantedInteractionBlocker:
      mEnablePalmRejection: true
      isPalmRejectionEnabled (flag value): true
      mPalmRejectors:
        deviceId = 3:
          mDeviceInfo:
            max_x = 
            max_y = 
            x_res = 11.00
            y_res = 11.00
            major_radius_res = 1.00
            minor_radius_res = 1.00
            minor_radius_supported = true
            touch_major_res = 1
            touch_minor_res = 1
          mSlotState:
            mSlotsByPointerId:
    
            mPointerIdsBySlot:
    
          mSuppressedPointerIds: {}
    
  6. To permanently enable the feature, add the corresponding sysprop command in your init**rc file:

    setprop persist.device_config.input_native_boot.palm_rejection_enabled 1
    

Further Reading

  1. Linux multi-touch protocol
  2. ENAC list of available multitouch devices on Linux