锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Android层面上对sensor及event事件的处理

时间:2023-11-21 21:37:01 磁性传感器ls

也许这个总结会有点凌乱,以后再讲sensor,一会又讲event是的。但把两者放在一起也是有原因的,sensor的处理是event正是因为在事件的基础上为sensor对event依赖,所以把两者放在一起。仔细想想,还是有原因的。

开始前先说明两点。

1、这里说的android层面上是linux内核之上的

2、sensor指的是gsensor,lightsensor等

下面正式开始,先简单说一下驱动中的处理。一般来说,驱动通常是通过的i2c来获取sensor当然,设备数据中有中断机制。然后通过input_event,input_sync等函数报告事件。报告的数据无疑写在设备节点(/dev/input/event*)。接下来是看android层次处理。

在android从层面上看,先看BoardConfig.mk

62 #BOARD_HAS_SENSOR := true
很明显,这是一个可配置的选项,意思也很清楚,配置,意味着sensor的相关的代码会被编译。接下来我们看看解析这个配置的地方:hardware其中一个Android.mk

ifeq ($(BOARD_HAS_SENSOR),true) 28 LOCAL_SRC_FILES :=                      \ 29                 sensors.cpp             \ 30                 SensorBase.cpp          \ 31                 LightSensor.cpp         \ 32                 AccelSensor.cpp         \ 33                 MagSensor.cpp           \ 34                 PressSensor.cpp         \ 35                 InputEventReader.cpp

我们可以看到31-34是:光感、加速度、磁性和压力。它也是可选的,可以根据您的实际使用情况使用sensor添加或删除。在这里,我们主要关注SensorBase.cpp,看下面的代码

145 int SensorBase::openInput(const char* inputName) { 146     int fd = -1; 147     int input_id = -1; 148     const char *dirname = "/dev/input"; 149     const char *inputsysfs = "/sys/class/input"; 150     char devname[PATH_MAX]; 151     char *filename; 152     DIR *dir; 153     struct dirent *de; 154  155     dir = opendir(dirname); 156     if(dir == NULL) 157         return -1; 158     strcpy(devname, dirname); 159     filename = devname   strlen(devname); 160     *filename   = '/'; 161     while((de = readdir(dir))) { 162         if(de->d_name[0] == '.' && 163                 (de->d_name[1] == '\0' || 164                         (de->d_name[1] == '.' && de->d_name[2] == '\0'))) 165             continue; 166         strcpy(filename, de->d_name); 167         fd = open(devname, O_RDONLY); 168  169         if (fd>=0) { 170             char name[80]; 171             if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) { 172                 name[0] = '\0'; 173             } 174  175             if (!strcmp(name, inputName)) { 176                 strcpy(input_name, filename); 177                 break; 178             } else { 179                 close(fd); 180                 fd = -1; 181             } 182         } 183     } 184     closedir(dir); 185     ALOGE_IF(fd<0, "couldn't find '%s' input device", inputName); 186     return fd; 187 }

首先是定义event节点目录:

148     const char *dirname = "/dev/input";

然后打开这个目录,得到它event*,真正的报告数据是从event*在此之前,为了给程序足够的访问权限event*节点,在ueventd.$VENDOR.rc 设置节点分析权限:

25 /dev/input/event2         0666   root        input 26 /dev/input/event0         0666   root        input

这跟android下getevent这个命令的用法是一样的,我们通常在android串口命令行输入getevent 命令将在串口终端打印event如果用户触发报告数据,则在终端命令行中输出相应的报告数据。

root@rom_3420:/# getevent

couldnot get driver version for /dev/input/mice, Not a typewriter

adddevice 1: /dev/input/event1

name:"matrix-keypad"

adddevice 2: /dev/input/event0

name:"gpio-keys"

有兴趣的客户自己研究getevent代码,位于android源码目录下的:system/core/toolbox/getevent.c读取上报数据的位置在里面main在函数中,使用轮询机制读取数据的,如下:

631     while(1) { 632         pollres = poll(ufds, nfds, -1);

处理过程与上述处理过程相同。hardware读取过程相同,EventHub里面读取到event之后对这些数据进行分类,然后分发到各种线程的控制器中进行最终处理。key,有key处理控制器跟线程;touch,有touch控制器跟线程。

但说到这里,可能会有这样一个问题:问什么?android不把sensor还放置了数据eventHub内部处理,而不是sensor分开处理数据?其实如果有人知道原因,我也有这样的疑惑。但有一点可以确认,在framework里面会对sensor过滤数据是错误的sensor处理数据。如:

frameworks/base/services/input/EventHub.h 200     // Sets devices that are excluded from opening. 201     // This can be used to ignore input devices for sensors. 202     virtual void setExcludedDevices(const Vector& devices) = 0;

和:

frameworks/base/services/input/InputReader.cpp  496 void InputReader::refreshConfigurationLocked(uint32_t changes) {  497     mPolicy->getReaderConfiguratin(&mConfig);
 498     mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);

其实android的代码里面也表明了,但这样做的原因,如上所说的,不知道为什么这样做。

如果想了解更多的 frameworks/base/services/input里面怎样对数据进行读取和分类的,或者是想了解android对event数据的处理的过程,可以参考下面几个博客:

Android输入事件流程中的EventHub分析及源码演示

http://blog.csdn.net/a345017062/article/details/6417929

Android应用程序键盘(Keyboard)消息处理机制分析

http://www.blogjava.net/mixer-a/archive/2012/04/17/374987.html

http://blog.csdn.net/yangwen123/article/details/14160289

好,说到这里,既然我们知道了android处理event数据的过程,那么,当我们需要的时候,就可以自己定制自己的hardware,来获取,甚至是截取android event数据。说白了,也就是对 /dev/input/ 里面节点信息的截取。说到这里,还想提一提,因为android所有处理event数据都是以轮询的机制来处理的。它不像fifo(管道)的形式,数据一旦被读取了就不见了。如果多个地方等待读取某一event的数据,那么一旦数据过来了,所有在轮询的地方都能获取到数据。而如果我们在截取数据的时候,只想让截取数据的地方获取到数据呢?个人觉得是可以实现的。这方面客户研究一下getevent和setevent的用法。

对event数据的获取就讲到这里,接下来回到sensor的处理中。

在“.mk”我们会看到会拷贝sensor的xml文件:
 

frameworks/native/data/etc/android.hardware.sensor.light.xml:system/etc/permissions/android.hardware.sensor.light.xml \
frameworks/native/data/etc/android.hardware.sensor.accelerometer.xml:system/etc/permissions/android.hardware.sensor.accelerometer.xml \

其实在manager里面就是通过是否存在这样一个xml文件来判断是否有sensor的存在:

frameworks/base/core/java/android/content/pm/PackageManager.java

 988     @SdkConstant(SdkConstantType.FEATURE)
 989     public static final String FEATURE_SENSOR_ACCELEROMETER = "android.hardware.sensor.accelerometer";
 
1013     /**
1014      * Feature for {@link #getSystemAvailableFeatures} and
1015      * {@link #hasSystemFeature}: The device includes a light sensor.
1016      */
1017     @SdkConstant(SdkConstantType.FEATURE)
1018     public static final String FEATURE_SENSOR_LIGHT = "android.hardware.sensor.light";

在device/$VENDOR/$BOARD/required_hardware.xml里面对字符串的定义:


overlay/frameworks/base/core/res/res/values/config.xml里面对光感强度等级的描述:


 87         20   
 88         30   
 89         40   
 90         50   
 91         60   
 92         70   
 93         80   
 94         130  
 95         180  
 96         255  
 97         255  
 98         255  
 99     

Framework里面会对xml的参数进行解析,具体就不去分析了。这方面还挺有意思,有兴趣可以自行分析。

init.rc里面对相关属性的定义:节点路径和默认光照强度

88     # Set light sensor sysfs path and light sensor threshold lux value
89     setprop ro.hardware.lightsensor "/sys/class/i2c-dev/i2c-2/device/2-0044/"
90     setprop ro.lightsensor.threshold  20

在后在LightSensor.cpp里面会对这两个属性解析解析:

55         property_get("ro.hardware.lightsensor", buffer, "0");
56         strcpy(ls_sysfs_path, buffer);
57         ls_sysfs_path_len = strlen(ls_sysfs_path);
58         enable(0, 1);
59     }
60 

光照强度

 61     /* Default threshold lux is 10 if ro.lightsensor.threshold
 62        isn't set */
 63     property_get("ro.lightsensor.threshold", buffer, "10");
 64     mThresholdLux = atoi(buffer);

Hardware里面定义好后,接下来是JNI里面导出接口函数:

frameworks\base\core\jni\android_hardware_SensorManager.cpp

在源码里,我们可以看到JNI接口的函数列表:

static JNINativeMethod gMethods[] = {
    {"nativeClassInit", "()V",              (void*)nativeClassInit },
    {"sensors_module_init","()I",           (void*)sensors_module_init },
    {"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",
                                            (void*)sensors_module_get_next_sensor },
 
    {"sensors_create_queue",  "()I",        (void*)sensors_create_queue },
    {"sensors_destroy_queue", "(I)V",       (void*)sensors_destroy_queue },
    {"sensors_enable_sensor", "(ILjava/lang/String;II)Z",
                                            (void*)sensors_enable_sensor },
 
    {"sensors_data_poll",  "(I[F[I[J)I",     (void*)sensors_data_poll },
};

然后,接下来是在framework层面对sensor数据的处理,报错以下几点。这里不着重分析,一般到这里,所有数据都交由系统源码进行处理,这部分我们基本上不会进行修改。

SensorManager.java

实现传感器系统核心的管理类SensorManager

Sensor.java

单一传感器的描述性文件Sensor

SensorEvent.java

表示传感器系统的事件类SensorEvent

SensorEventListener.java

传感器事件的监听者SensorEventListener接口

SensorListener.java

传感器的监听者SensorListener接口


--------------------- 
版权声明:本文为CSDN博主「little_paul」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hbk320/article/details/47188519

 

 

 

 

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章