作为网站门牌号的域名,域名是如何创造的?现在企业网站需要配合域名使用,企业邮箱等等系统也要陪配合域名使用,域名与企业办公息息相关,域名不仅仅指一个网址...
2024-11-18 8
一,Android sensor 系统架构
HAl 就是对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节。也就是说,把对硬件的支持分成了两层,一层放在用户空间(User Space),一层放在内核空间(Kernel Space),其中,硬件抽象层运行在用户空间,而Linux内核驱动程序运行在内核空间。
二,HAL 层Sensor 框架实现
Sensor HAL层相对来说比较简单,它的意图就是为fraMework层提供接口API的实现,如open_sensors,poll等,一旦实现完毕,framewoerk 里面的SensorManager,SensorService 里面的native(本地)方法可以直接被调用。
2.1 HAL 客制化
在alps\device\mediatek$(proj)\ProjectConfig.mk中 配置对应的传感器为y
等效路径(kernel3.18\arch\arm64\configs$(proj).deconfig)
CONFIG_MTK_SENSOR_SUPPORT=y CONFIG_CUSTOM_KERNEL_ACCELEROMETER=y CONFIG_MTK_ICM20645G=y CONFIG_CUSTOM_KERNEL_ALSPS=y CONFIG_MTK_CM36558=y CONFIG_CUSTOM_KERNEL_GYROSCOPE=y CONFIG_MTK_ICM20645gY=y
2.2 获取module函数
Hal层的库文件是怎么被上层调用的?上层调用时的入口(相当于mAIn)又是什么呢?它就是HAL_MODULE_INFO_SYM。
路径:vendor/mediatek/proprietary/hardware/sensor/sensors.c
static int open_sensors(const strUCt hw_module_t* module, const char* name, struct hw_device_t** device) { ALOGD("%s: name: %s! fwq debug\r\n", __func__, name); return init_nusensors(module, device); } static struct hw_module_methods_t sensors_module_methods = { .open = open_sensors }; struct sensors_module_t HAL_MODULE_INFO_SYM = { .common = { .tag = HARDWARE_MODULE_TAG, .version_major = 1, .version_minor = 0, .id = SENSORS_HARDWARE_MODULE_ID, .name = "MTK SENSORS Module", .author = "Mediatek", .methods = &sensors_module_methods, }, .get_sensors_list = sensors__get_sensors_list, };
路径:vendor/mediatek/proprietary/hardware/sensor/nusensors.cpp
int init_nusensors(hw_module_t const* module, hw_device_t** device) { int status = -EINVAL; dev = new sensors_poll_context_t(); memset(&dev->device, 0, sizeof(sensors_poll_device_1)); dev->device.common.tag = HARDWARE_DEVICE_TAG; #if defined(SENSOR_BATCH_SUPPORT) || defined(CUSTOM_KERNEL_SENSORHUB) dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_1; #else dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_0; #endif dev->device.common.module = const_cast<hw_module_t*>(module); dev->device.common.close = poll__close; dev->device.activate = poll__activate; dev->device.setDelay = poll__setDelay; dev->device.poll = poll__poll; dev->device.batch = poll__batch; dev->device.flush = poll__flush; *device = &dev->device.common; status = 0; return status; }
2.3 创建 sensors_poll_context_t 对象
sensors_poll_context_t::sensors_poll_context_t() { memset(&device, 0, sizeof(device)); mSensors[accel] = new AccelerationSensor(); mPollFds[accel].fd = ((AccelerationSensor*)mSensors[accel])->mdata_fd; mPollFds[accel].events = POLLIN; mPollFds[accel].revents = 0; mSensors[proximity] = new ProximitySensor(); mPollFds[proximity].fd = ((ProximitySensor*)mSensors[proximity])->mdata_fd; mPollFds[proximity].events = POLLIN; mPollFds[proximity].revents = 0; int wakeFds[2]; int result = pIPe(wakeFds); if (result < 0) { ALOGE_IF(result < 0, "error creating wake pipe (%s)", strerror(errno)); mWritePipeFd = -1; } else { result = fcntl(wakeFds[0], F_SETFL, O_NONBLOCK); ALOGE_IF(result < 0, "fcntl(wakeFds[0] fail (%s)", strerror(errno)); result = fcntl(wakeFds[1], F_SETFL, O_NONBLOCK); ALOGE_IF(result < 0, "fcntl(wakeFds[1] fail (%s)", strerror(errno)); mWritePipeFd = wakeFds[1]; } mPollFds[wake].fd = wakeFds[0]; mPollFds[wake].events = POLLIN; mPollFds[wake].revents = 0; }
2.4 创建Sensor对象
路径:vendor/mediatek/proprietary/hardware/sensor/Proximity.cpp
ProximitySensor::ProximitySensor() : SensorBase(NULL, "m_alsps_input"),//PRO_INPUTDEV_NAME mEnabled(0), mInputReader(32) { char datapath[64]={"/sys/class/misc/m_alsps_misc/psactive"}; int fd = -1; char buf[64]={0}; int len; mdata_fd = FindDataFd(); if (mdata_fd >= 0) { strcpy(input_sysfs_path, "/sys/class/misc/m_alsps_misc/"); input_sysfs_path_len = strlen(input_sysfs_path); } else { ALOGE("couldn't find input device "); return; } ALOGD("prox misc path =%s", input_sysfs_path); fd = open(datapath, O_RDWR); if (fd >= 0) { len = read(fd,buf,sizeof(buf)-1); if (len <= 0) { ALOGD("read p err, len = %d", len); } else { buf[len] = '\0'; sscanf(buf, "%d", &mDataDiv); ALOGD("read p buf(%s), mp %d", datapath,mDataDiv); } close(fd); } else { ALOGE("open acc misc path %s fail ", datapath); } }
2.5 通用sensor 的使能函数
static int poll__activate(struct sensors_poll_device_t *dev, int handle, int enabled) { sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; return ctx->activate(handle-ID_OFFSET, enabled); }
int sensors_poll_context_t::activate(int handle, int enabled) { .... int index = handleToDriver(handle); ..... if(NULL != mSensors[index]) { ALOGD( "use new sensor index=%d, mSensors[index](%x)", index, mSensors[index]); if(this->device.common.version >= SENSORS_DEVICE_API_VERSION_1_1) { ALOGD("support batch active \n" ); mSensors[batchsensor]->enable(handle, enabled); } err = mSensors[index]->enable(handle, enabled); } return err; }
2.6 封装poll 函数
poll 函数对应framework中poll操作,这里只需了解它的功能实现,调用逻辑需要查看framework层代码
poll 是一个非常重要的接口,它的实现基于linux 内核中IO多路复用策略(一种效率非常高的机制)
static int poll__poll(struct sensors_poll_device_t *dev, sensors_event_t* data, int count) { sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; return ctx->pollEvents(data, count); }
轮询事件方法,这是一个构造方法,该对象创建,会启动轮询机制,**sensorlist[]中文件描述符,等待事件上报 (使用IO多路复用策略)
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count) { ..... do { for (int i=0 ; count && i<numSensorDrivers ; i++) { SensorBase* const sensor(mSensors[i]); if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) { int nb = sensor->readEvents(data, count); ..... } if (count) { // we still have some room, so try to see if we can get // some events immediately or just wait if we don't have // anything to return n = poll(mPollFds, numFds, nbEvents ? 0 : -1); if (n<0) { int err; err = errno; ALOGE("poll() failed (%s)", strerror(errno)); return -err; } if (mPollFds[wake].revents & POLLIN) { char msg; int result = read(mPollFds[wake].fd, &msg, 1); ALOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno)); ALOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg)); mPollFds[wake].revents = 0; } } // if we have events and space, go read them } while (n && count); return nbEvents; }
2.7 读取事件函数
int ProximitySensor::readEvents(sensors_event_t* data, int count) { .... ssize_t n = mInputReader.fill(mdata_fd); if (n < 0) return n; int numEventReceived = 0; input_event const* event; while (count && mInputReader.readEvent(&event)) { int type = event->type; //ALOGE("fwq1....\r\n"); if (type == EV_REL) { processEvent(event->code, event->value); //ALOGE("fwq2....\r\n"); } ..... mInputReader.next(); } //ALOGE("fwq read Event 2\r\n"); return numEventReceived; }
void ProximitySensor::processEvent(int code, int value) { ALOGD("processEvent code=%d,value=%d\r\n",code, value); switch (code) { case EVENT_TYPE_PS_VALUE: mPendingEvent.distance= value-1; break; } }
2.8 获得sensor 列表函数
路径:vendor/mediatek/proprietary/hardware/sensor/sensors.c
这一步非常重要,HAL_MODULE_INFO_SYM 映射了hal 层XXX.so 库的入口,上层hw_get_module 将获得该入口,使得上层可以和底层.so库进行交互
static int sensors__get_sensors_list(struct sensors_module_t* module, struct sensor_t const** list) { ALOGD(" sSensorList addr =%p, module addr =%p\r\n",sSensorList,module); ALOGD(" ARRAY_SIZE(sSensorList) =%d SENSORS_NUM=%d MAX_NUM_SENSOR=%d \r\n",ARRAY_SIZE(sSensorList), SENSORS_NUM, MAX_NUM_SENSOR); *list = sSensorList; return ARRAY_SIZE(sSensorList); }
struct sensor_t sSensorList[] = { #ifdef CUSTOM_KERNEL_ACCELEROMETER { .name = ACCELEROMETER, .vendor = ACCELEROMETER_VENDER, .version = 3, .handle = ID_ACCELEROMETER+ID_OFFSET, .type = SENSOR_TYPE_ACCELEROMETER, .maxRange = ACCELEROMETER_RANGE,//32.0f, .resolution = ACCELEROMETER_RESOLUTION,//4.0f/1024.0f, .power = ACCELEROMETER_POWER,//130.0f/1000.0f, .minDelay = 10000, .maxDelay = 1000000, .reserved = {} }, #endif #if defined(CUSTOM_KERNEL_ALSPS) || defined(CUSTOM_KERNEL_ALS) { .name = LIGHT, .vendor = LIGHT_VENDER, .version = 1, .handle = ID_LIGHT+ID_OFFSET, .type = SENSOR_TYPE_LIGHT, .maxRange = LIGHT_RANGE,//10240.0f, .resolution = LIGHT_RESOLUTION,//1.0f, .power = LIGHT_POWER,//0.13f, .reserved = {} }, #endif };
三,Selinux权限问题
四,HAL 层log分析
psensor 手机中常见的使用就是拨号时贴脸灭屏,拨号后遮挡psensor,使用Adb抓取android log ,过滤的的psensor log部分如下:
驱动部分后续再介绍
TAG:android光线传感器
标签: 当前位置: 首页 > 问答
相关文章
作为网站门牌号的域名,域名是如何创造的?现在企业网站需要配合域名使用,企业邮箱等等系统也要陪配合域名使用,域名与企业办公息息相关,域名不仅仅指一个网址...
2024-11-18 8
说起建设网站,不得不提的就是网站绑定的域名,域名作为网站的门牌号,不仅仅要代表网站和企业的形象,更加要让访问者用起来方便快捷。小编就教大家如何为网站注...
2024-11-18 6
做一名企业家是多么匆忙啊! 从零开始创业是一件伤脑筋又有挑战性的事情,但同时也是一件非常有益且令人兴奋的事情。当您创立起您自己的事业,您将充满营销、...
2024-11-18 8
其实很多朋友们认为,注册域名的时候就需要选择自己喜欢的域名在进行注册,但是小编表示这样其实是不对的,域名注册则是被分为域名和域名交易平台两个部分,今天...
2024-11-18 7
我们在建造一个网站前,都会首先先思考挑选一个实用、好记的域名。可是实事是当咱们在查询域名时都会发现,有意义的域名,简直都被抢注一空。这时咱们就要改变一...
2024-11-17 7
作为中国最早的域名投资者之一,58同城的创始人姚劲波很早就把赶集网的同音域名ganjinwang.com收归旗下,现在打开该网址,仍然链接到58同城。...
2024-11-17 8
想必每一个做网站的朋友在注册域名的时候都是费尽脑汁的,好不容易想好了一个域名却发现已经被注册了,这个时候有一个批量域名查询工具是不是很方便,今天小编就...
2024-11-17 8