引用:http://blog.163.com/fenglang_2006/blog/static/13366231820108205274325/

第一章摘要

在Linux内核支持的基础上,Android在其2.0源码中加入多点触摸功能。由此触摸屏在Android的frameworks被完全分为2种实现途径:单点触摸屏的单点方式,多点触摸屏的单点和多点方式。

第二章软件位

在Linux的input.h中,多点触摸功能依赖于以下几个主要的软件位:

………………………..

#define SYN_REPORT0

#define SYN_CONFIG1

#define SYN_MT_REPORT2

………………………...

#define ABS_MT_TOUCH_MAJOR0x30/* Major axis of touching ellipse */

#define ABS_MT_TOUCH_MINOR0x31/* Minor axis (omit if circular) */

#define ABS_MT_WIDTH_MAJOR0x32/* Major axis of approaching ellipse */

#define ABS_MT_WIDTH_MINOR0x33/* Minor axis (omit if circular) */

#define ABS_MT_ORIENTATION0x34/* Ellipse orientation */

#define ABS_MT_POSITION_X0x35/* Center X ellipse position */

#define ABS_MT_POSITION_Y0x36/* Center Y ellipse position */

#define ABS_MT_TOOL_TYPE0x37/* Type of touching device */

#define ABS_MT_BLOB_ID0x38/* Group a set of packets as a blob */

…………………………

在Android中对应的软件位定义在RawInputEvent.java中:

…………………..

public class RawInputEvent {

……………….

public static final int CLASS_TOUCHSCREEN_MT = 0x00000010;

………………..

public static final int ABS_MT_TOUCH_MAJOR = 0x30;

public static final int ABS_MT_TOUCH_MINOR = 0x31;

public static final int ABS_MT_WIDTH_MAJOR = 0x32;

public static final int ABS_MT_WIDTH_MINOR = 0x33;

public static final int ABS_MT_ORIENTATION = 0x34;

public static final int ABS_MT_POSITION_X = 0x35;

public static final int ABS_MT_POSITION_Y = 0x36;

public static final int ABS_MT_TOOL_TYPE = 0x37;

public static final int ABS_MT_BLOB_ID = 0x38;

………………….

public static final int SYN_REPORT = 0;

public static final int SYN_CONFIG = 1;

public static final int SYN_MT_REPORT = 2;

………………..

在Android中,多点触摸的实现方法在具体的代码实现中和单点是完全区分开的。在Android代码的EventHub.cpp中,单点屏和多点屏由如下代码段来判定:

int EventHub::open_device(const char *deviceName)

{

………………………

if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)

&& test_bit(ABS_MT_POSITION_X, abs_bitmask)

&& test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {

device->classes |= CLASS_TOUCHSCREEN | CLASS_TOUCHSCREEN_MT;

//LOGI("It is a multi-touch screen!");

}

//single-touch?

else if (test_bit(BTN_TOUCH, key_bitmask)

&& test_bit(ABS_X, abs_bitmask)

&& test_bit(ABS_Y, abs_bitmask)) {

device->classes |= CLASS_TOUCHSCREEN;

//LOGI("It is a single-touch screen!");

}

………………..

}

我们知道,在触摸屏驱动中,通常在probe函数中会调用input_set_abs_params给设备的input_dev结构体初始化,这些input_dev的参数会在Android的EventHub.cpp中被读取。如上可知,如果我们的触摸屏想被当成多点屏被处理,只需要在驱动中给input_dev额外增加以下几个参数即可:

input_set_abs_params(mcs_data.input, ABS_MT_POSITION_X, pdata->abs_x_min,  pdata->abs_x_max, 0, 0);

input_set_abs_params(mcs_data.input, ABS_MT_POSITION_Y, pdata->abs_y_min,  pdata->abs_y_max, 0, 0);

input_set_abs_params(mcs_data.input, ABS_MT_TOUCH_MAJOR, 0, 15, 0, 0);

//相当于单点屏的ABX_PRESSURE

input_set_abs_params(mcs_data.input, ABS_MT_WIDTH_MAJOR, 0, 15, 0, 0);

//相当于单点屏的ABS_TOOL_WIDTH

注:

为了让我们的驱动代码支持所有的Android版本,无论是多点屏还是单点屏,一般都会保留单点屏的事件,如ABS_TOUCH, ABS_PRESSURE, ABS_X, ABS_Y等。另外,由于在Android2.0前支持多点的frameworks大多是用HAT0X,HAT0Y来实现的,所以一般也会上报这2个事件。

第三章同步方式

由于多点触摸技术需要采集到多个点,然后再一起处理这些点,所以在软件实现中需要保证每一波点的准确性和完整性。因此,Linux内核提供了input_mt_sync(struct input_dev * input)函数。在每波的每个点上报后需要紧跟一句input_mt_sync(), 当这波所有点上报后再使用input_sync()进行同步。例如一波要上报3个点:

/* 上报点1*/

……………..

input_mt_sync(input);

/* 上报点2*/

……………..

input_mt_sync(input);

/* 上报点3*/

……………..

input_mt_sync(input);

input_sync(input);

注:即使是仅上报一个点的单点事件,也需要一次input_my_sync。

第四章触摸事件数组的处理

上面我们曾说到generateAbsMotion这个方法,它们在InputDevice类的内部类MotionState中实现,该类被定义为InputDevice类的静态成员类(static class),调用它们可以直接使用:

InputDeviceClass.MotionStateClass.generateAbsMotion()。

public class InputDevice {

……………………………

static class MotionState {//下面是这个内部类的几个函数

……………………………….

/* mLastNumPointers 为上一个动作在触屏上按键的个数 */

int mLastNumPointers = 0;

final int[] mLastData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];

/* mNextNumPointers 为下一个动作在触屏上按键的个数 */

/* 通过对这2个值大小的判断,可以确认新的动作方式 */

int mNextNumPointers = 0;

final int[] mNextData = new int[(MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS)

+ MotionEvent.NUM_SAMPLE_DATA];

………………………………….

int[] generateAveragedData(int upOrDownPointer, int lastNumPointers,

int nextNumPointers) { //平滑处理

…………………………………….

}

private boolean assignPointer(int nextIndex, boolean allowOverlap) {//指派按键

……………………………………

}

private int updatePointerIdentifiers() {//更新按键ID

………………………………….

}

void removeOldPointer(int index) {

……………………………………

}

MotionEvent generateAbsMotion(InputDevice device, long curTime,

long curTimeNano, Display display, int orientation,

int metaState) {

……………………………………

int upOrDownPointer = updatePointerIdentifiers();

final int numPointers = mLastNumPointers;

………………………………………

/* 对行为的判断 */

if (nextNumPointers != lastNumPointers) { //前后在触屏上点个数不同,说明有手指up或down

if (nextNumPointers > lastNumPointers) {

if (lastNumPointers == 0) { //上次触屏上没有按键,新值又大,说明有按键按下

action = MotionEvent.ACTION_DOWN;

mDownTime = curTime;

} else {//有新点按下,分配给新点ID号

action = MotionEvent.ACTION_POINTER_DOWN

| (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);

}

} else {//新动作比原来pointer数量少

if (numPointers == 1) { //原来只有1个点按下,所以现在的动作是全部按键up

action = MotionEvent.ACTION_UP;

} else { //原来有多点按下,现在是ACTION_POINTER_UP动作,

action = MotionEvent.ACTION_POINTER_UP

| (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);

}

}

currentMove = null;

} else { //前后触屏pointer个数相同,所以是移动动作ACTION_MOVE

action = MotionEvent.ACTION_MOVE;

}

/* 后面则是根据屏幕的height和width以及屏幕方向orientation对这些点进行二次处理 */

……………………………………

}

MotionEvent generateRelMotion(InputDevice device, long curTime,

long curTimeNano, int orientation, int metaState) {

/* 轨迹球等的处理方式 */

…………………………………………..

}

void finish() {      //结束这轮动作

mNextNumPointers = mAddingPointerOffset = 0;

mNextData[MotionEvent.SAMPLE_PRESSURE] = 0;

}

…………………………………….

}

……………………………….

……………………………………

}

第五章接口

我们平时所看到的用2个手指对图片放大缩小、旋转等手势都是由应用程序编写浏览器实现的。这些应用程序大多会使用Android2.0以上的在MotionEvent.java中实现的新的接口。所以,我们还需要给MotionEvent类补充尽量全的接口。这里可以完全参照google新的android代码。

第六章总结

综上,在硬件支持基础上,Android1.6如果要实现多点触摸功能,主要工作可简述为以下几个方面:

1、 驱动中,除了增加多点的事件上报方式,还要完全更改单点的事件上报方式。

2、 Android的Frameworks层需要修改的文件有:EventHub.cpp,RawInputEvent.java,KeyInputQueue.java,InputDevice.java,MotionEvent.java。

3、 编写新的支持多点触摸功能的多媒体浏览器。

4、 为了代码简练,android2.0在轨迹球和单点屏事件方式中也全使用了新的变量名,以方便多点屏事件同样能使用这些变量,所以修改时还需要注意许多细节方面。

android 多点的更多相关文章

  1. Linux与Android 多点触摸协议【转】

    本文转载自:http://blog.csdn.net/xubin341719/article/details/7833277 一.Linux与Android 多点触摸协议 为了使用功能强大的多点触控设 ...

  2. Linux & Android 多点触摸协议

    Linux & Android 多点触摸协议 Android4.0多点触摸入门 1 KERNEL 对于触摸屏的驱动我们简单的划分为两个主要的部分,一个是注册,另一个是上报. 1.1 注册 单点 ...

  3. Android多点触控技术

    1 简介 Android多点触控在本质上需要LCD驱动和程序本身设计上支持,目前市面上HTC.Motorola和Samsung等知名厂商只要使用电容屏触控原理的手机均可以支持多点触控Multitouc ...

  4. [yueqian_scut]Android多点触控技术和应用框架

    Android多点触控技术跟Linux输入子系统紧密相关.本文将从应用的角度说明Android多点触控技术的接口和应用. 一.多点触控场景分析 网络上有关Android多点触控技术的文章多见于两点拉伸 ...

  5. Android 多点触控与简单手势(一)

    现在一般的Android手机都会使用电容触摸屏最少可以支持两点触摸,多的可能是七八个,所以基本上都会支持多点触控, android系统中应用程序可以使用多点触控的事件来完成各种手势和场景需求. And ...

  6. Android多点触控技术实战,自由地对图片进行缩放和移动

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11100327 在上一篇文章中我带着大家一起实现了Android瀑布流照片墙的效果, ...

  7. Android 多点触控错误处理(java.lang.IllegalArgumentException: pointerIndex out of range)

    最近做View的多点触控时,每次第一次触控事件完美运行,第二次就直接崩了,错误信息如下: 01-03 00:05:44.220 4377-4410/system_process E/AndroidRu ...

  8. Android 多点手势识别详解

    google 提供的API中,有个类,大家都很熟悉,GestureDetector.使用它,我们可以识别用户通常会用的手势.但是,这个类不支持多点触摸(可能 google认为没有人会在几个手指都在屏幕 ...

  9. scaleform mobile sdk for android 多点触摸 修正

    修正 scaleform 的多点触控 (随手一记 给后来的人做个参考) scaleform 版本号 4.2.24 (估计这就是最后一个 移动版的版本了,万年没有更新了) 开始 一直以为 scalefo ...

随机推荐

  1. Hightcharts动态创建series

    第一种方法: 申明options时动态设置series,然后再创建chart对象 代码如下: <html> <head> <title>Highcharts Exa ...

  2. Eclipse安装nodeclipse插件

    1. Start Eclipse, then select Help > Install New Software... 2. Enter the update site URL into th ...

  3. 浅析-博客Ping服务

    简介:PING服务是博客站点向博客目标网站.搜索引擎等发出的博客内容更新通知服务,然后博客目标网站.搜索引擎就会及时的索引.收录以及传播您的博客内容. PING原理 PING 服务是博客站点向博客目标 ...

  4. python中的进程、线程(threading、multiprocessing、Queue、subprocess)

    Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CP ...

  5. Webform购物车(用Session存储,页面传值)

    购物车主要实现的功能: ①在主页面可以将所有商品显示出来,包括价格,库存. ②点击购买可以累加产品,如果是同一种产品,只会累加每种产品的数量. ③查看购物车,可以查看明细,包括所购物品的名称,价格,数 ...

  6. c#面向对象基础 静态成员、构造函数、命名空间与类库

    静态成员 属性.方法和字段等成员是对象实例所特有的,即改变一个对象实例的这些成员不影响其他的实例中的这些成员.除此之外,还有一种静态成员(也称为共享成员),例如静态方法.静态属性或静态字段.静态成员可 ...

  7. spring security动态管理资源结合自定义登录页面

    如果想将动态管理资源与自定义登录页面一起使用,最简单的办法就是在数据库中将登录页面对应的权限设置为IS_AUTHENTICATED_ANONYMOUSLY. 因此在数据库中添加一条资源信息. INSE ...

  8. bug1

    1从相册中获取图片,低版本可以,高版本不行.看见抛出 Bitmap too large to be uploaded into a texture 原来是高版本的android,机子好点,相机就好点, ...

  9. BizTalk开发系列(一) "Hello World"

    学习开发语言的时候很喜欢输出“Hello World”作为第一个程序.今天我们也在BizTalk 上创建一个简单的 "Hello World" 程序. BizTalk的时候有很多文 ...

  10. Android课程---寄存器与存储器的区别

    存储器在CPU外,一般指硬盘,U盘等可以在切断电源后保存资料的设备,容量一般比较大,缺点是读写速度都很慢,普通的机械硬盘读写速度一般是50MB/S左右.内存和寄存器就是为了解决存储器读写速度慢而产生的 ...