【Android源码 栏目提醒】:以下是网学会员为您推荐的Android源码 -转]Android触摸屏校准程序的实现 - 培训教程,希望本篇文章对您学习有所帮助。
最近学习了电容触摸屏的驱动及其上层工作原理拿出来和大家分享 转
Android触摸屏校准程序的实现 一校准的触摸算法如下 触摸屏校准通用方法。
XL YL是显示屏坐标XT YT是触摸屏坐标 XL XTAYTBC YL XTDYTEF 由于具体计算是希望是整数运算所以实际中保存的ABCDEF为整数而增加一个参数Div XL XTAYTBC / Div YL YTDYTEF / Div TSLIB把以上的7个参数 ABCDEF Div 保存在 pointercal 文件中。
不校准的数据 A1 B0 C0 D0 E1 F0 Div1 A B C D E F Div -411 37818 -3636780 -51325 39 47065584 65536 二
Android 事件处理机制
android 事件的传入是从EventHub开始的EventHub是 事件的抽象结构维护着系统设备的运行情况设备文件放在/dev/input里设备类型包括Keyboard、TouchScreen、 TraceBall。
它在系统启动的时候会通过 open_device方法将系统提供的输入设备都增加到这个抽象结构中并维护一个所有输入设备的文件描述符如果输入设备是键盘的话还会读取 /system/usr/keylayout/目录下对应键盘设备的映射文件修改./development/emulator/keymaps /qwerty.kl来改变键值的映射关系另外getEvent方法是对EventHub中的设备文件描述符使用poll操作等侍驱动层事件的发生如果发生的事件是键盘事件则调用Map函数按照映射文件转换成相应的键值并将扫描码和键码返回给KeyInputQueue. frameworks/base/services/jni/com_
android_server_KeyInputQueue.cpp 根据事件的类型以及事件值进行判断处理从而确定这个事件对应的设备状态是否发生了改变并相应的改变对这个设备的描述结构InputDevice。
Windowmanager会创建一个线程InputDispatcherThread在这个线程里从事件队列中读取发生的事件 QueuedEvent ev mQueue.getEvent并根据读取到事件类型的不同分成三类KEYBOARD、TOUCHSCREEN、TRACKBALL分别进 行处理例如键盘事件会调用dispatchKeyKeyEventev.event 0 0以将事件通过Binder发送给具有焦点的窗口应用程序然后调用 mQueue.recycleEventev继续等侍键盘事件的发生如果是触摸屏事件则调用dispatchPointerev MotionEventev.event 0 0这里会根据事件的种类UP、DOWN、MOVE、OUT_SIDE等进行判断并处理比如Cancel或将事件发送到具有权限的指定的窗口中 去 移植方案
Android本身并不带触摸屏校准。
Android获取到的数据就是驱动上报的原始数据。
方案一 : 移植TSLIB通过TSLIB产生 pointercal 校准参数文件。
方案二 : 从
Android框架层获取OnTouch事件产生 pointercal 校准参数文件 方案一: 数据的校准在驱动中完成。
即把 pointercal 的参数数据通过某种方式sysfs传递给驱动程序进行校准。
方案二: 驱动上报原始点原始点在框架层拦截后进行校验处理。
TSLIB移植过程 修改
源码以适应
android的文件结构。
设定
Android.mk 编译选项生成库即应用。
etc/ts.conf module_raw input src/ts_config.c define TS_CONF /system/etc/ts.conf src/ts_load_module.c char plugin_directory/system/lib/ts/plugins/ tests/fbutils.c char defaultfbdevice /dev/graphics/fb0 COPY ts.conf 到 /system/etc/ts.conf init.rc. mkdir /data/etc/pointercal 通过 ts_calibrate 产生pointercal 数据文件。
框架内获取参数文件制作APK 应用仿效ts_calibrate采点并计算出各参数产生 pointercal框架内实现触摸屏校准在 InputDevive.java 中 拦截触摸屏原始数据进行pointercal参数校验后再分发驱动内实现触摸屏校准 在init.rc 中添加event在触摸屏加载后把 pointercal参数输送给驱动。
结果-效果 实现细节: 扩展init - proper_serivce 系统支持的属性权限对自定义的特殊系统属性进行权限开放。
使用自定义系统属性在 init.rc 中 on property 事件中处理pointercal的读写权限。
使用自定义系统属性 触摸屏校准程序.apk 和 InputDevice.java 中的输入事件的同步。
在触摸屏校准期间 inputDevice 在输入事件中不能采用算法。
校准程序完成有inputDevice重新启用校准算法 模拟器中至今无法进入 device.absX/Y null 的代码 需要了解以下 inputDevice 被调用的步骤。
三触摸屏的时间流程: 驱动层: / Touchscreen absolute values These parameters are used to help the input layer discard out of range readings and reduce jitter etc. o min max:- indicate the min and max values your touch screen returns o fuzz:- use a higher number to reduce jitter The default values correspond to Mainstone II in QVGA mode Please read Documentation/input/input-programming.txt for more details. / static int abs_x3 350 3900 5 module_param_arrayabs_x int NULL 0 MODULE_PARM_DESCabs_x Touchscreen absolute X min max fuzz static int abs_y3 320 3750 40 module_param_arrayabs_y int NULL 0 MODULE_PARM_DESCabs_y Touchscreen absolute Y min max fuzz static int abs_p3 0 150 4 module_param_arrayabs_p int NULL 0 MODULE_PARM_DESCabs_p Touchscreen absolute Pressure min max fuzz / 对设备进行初始化设置 / set_bitEV_ABS wm-input_dev-evbit set_bitABS_X wm-input_dev-absbit set_bitABS_Y wm-input_dev-absbit set_bitABS_PRESSURE wm-input_dev-absbit input_set_abs_paramswm-input_dev ABS_X abs_x0 abs_x1 abs_x2 0 input_set_abs_paramswm-input_dev ABS_Y abs_y0 abs_y1 abs_y2 0 input_set_abs_paramswm-input_dev ABS_PRESSURE abs_p0 abs_p1 abs_p2 0 / 事件发生时提供原始点 / input_report_abswm-input_dev ABS_X data.x 0xfff input_report_abswm-input_dev ABS_Y data.y 0xfff input_report_abswm-input_dev ABS_PRESSURE data.p 0xfff / 提供给驱动外查询input_dev 的接口 struct input_absinfo info ioctlfd EVIOCGABSaxis info src file: evDev.c / if _IOC_NRcmd ABS_MAX _IOC_NREVIOCGABS0 t _IOC_NRcmd ABS_MAX abs.value dev-abst abs.minimum dev-absmint abs.maximum dev-absmaxt abs.fuzz dev-absfuzzt abs.flat dev-absflatt
Android 底层驱动 EventHub.cpp static const char device_path /dev/input openPlatformInputvoid scan_dirdevice_path open_devicedevname fd opendeviceName O_RDWR / 对外接口getEvent inotify 监控device_path目录 使用poll机制轮询 inotify 和各个输入设备的可用状态。
解析事件或输入信息放入各个传出参数中。
/ bool EventHub::getEventint32_t outDeviceId int32_t outType int32_t outScancode int32_t outKeycode uint32_t outFlags int32_t outValue nsecs_t outWhen JNI 部分 com_
android_server_KeyInputQueue.cpp. 提供接口 static JNINativeMethod gInputMethods / name signature funcPtr / readEvent Landroid/view/RawInputEventZ void
android_server_KeyInputQueue_readEvent getDeviceClasses II void
android_server_KeyInputQueue_getDeviceClasses getDeviceName ILjava/lang/String void
android_server_KeyInputQueue_getDeviceName getAbsoluteInfo IILcom/
android/server/InputDeviceAbsoluteInfoZ void
android_server_KeyInputQueue_getAbsoluteInfo getSwitchState II void
android_server_KeyInputQueue_getSwitchState getSwitchState III void
android_server_KeyInputQueue_getSwitchStateDevice getScancodeState II void
android_server_KeyInputQueue_getScancodeState getScancodeState III void
android_server_KeyInputQueue_getScancodeStateDevice getKeycodeState II void
android_server_KeyInputQueue_getKeycodeState getKeycodeState III void
android_server_KeyInputQueue_getKeycodeStateDevice hasKeys IZZ void
android_server_KeyInputQueue_hasKeys java service 部分 KeyInputQueue.java. 循环查询输入设备信息或目录状态并处理 Thread mThread new ThreadInputDeviceReader public void run
android.os.Process.setThreadPriority
android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY try RawInputEvent ev new RawInputEvent while true InputDevice di // block doesnt release the monitor readEventev boolean send false boolean configChanged false ...... //检测到新设备后 if ev.type RawInputEvent.EV_DEVICE_ADDED synchronized mFirst di newInputDeviceev.deviceId mDevices.putev.deviceId di configChanged true //对触摸屏设备 InputDevice.AbsoluteInfo absX InputDevice.AbsoluteInfo absY InputDevice.AbsoluteInfo absPressure InputDevice.AbsoluteInfo absSize if classesRawInputEvent.CLASS_TOUCHSCREEN 0 absX loadAbsoluteInfodeviceId RawInputEvent.ABS_X X absY loadAbsoluteInfodeviceId RawInputEvent.ABS_Y Y absPressure loadAbsoluteInfodeviceId RawInputEvent.ABS_PRESSURE Pressure absSize loadAbsoluteInfodeviceId RawInputEvent.ABS_TOOL_WIDTH Size else absX null absY null absPressure null absSize null return new InputDevicedeviceId classes name absX absY absPressure absSize 我们对触摸屏的数据修订是在 InputDevice.java 中基于 absX absY absPressure null 的状态下的当绝对原始点数据从驱动报上来之后传递到InputDevice.java 经过我们的校准后再dispatch出去到windowManager - activity 。
这样就是起到了校准效果。
四需要注意的补助说明 EventHub 中有使用IOCTL 对触摸屏的EVIOCGABSaxis进行了采样取出内容struct input_absinfo info struct input_absinfo __s32 value __s32 minimum __s32 maximum __s32 fuzz __s32 flat __s32 resolution define EVIOCGABSabs _IORE 0x40 abs struct input_absinfo / get abs value/limits / 取出的是触摸屏的最大值最小值等这些值在com_
android_server_KeyInputQueue.cpp 中会把这些值传递给InputDevice.cpp中使用即把报上来的位置通过算法进行计算成绝对坐标值 scaledX scaledX-device.absX.minValue / device.absX.range w 当然如果出现了XY轴相反或者坐标反向等问题都可通过改写这条语句来进行实际操作。