Android sensor 系统框架 (二)
连载上一篇http://www.cnblogs.com/hackfun/p/7327320.html
(D) 如何加载访问.so库
在前一篇博客http://www.cnblogs.com/hackfun/p/7327320.html中,知道如何生成了
一个HAL的.so库,在这里将分析如何加载这个HAL,如何再次封装以适合多客户端访问的情况。
实际上,系统是通过SENSORS_HARDWARE_MODULE_ID找到对应的.so库的。因为该库中的
struct sensors_module_t结构体包含了一个唯一的ID就是SENSORS_HARDWARE_MODULE_ID,
最终的目的也是要获得这个结构体。通过查找这个ID得知是在以下文件中加载设个so的。
文件路径是:
frameworks/native/services/sensorservice/SensorDevice.cpp
先看代码注释,最后再总结。
SensorDevice.cpp
SensorDevice::SensorDevice()
: mSensorDevice(),
mSensorModule()
{
/* 获取SENSORS_HARDWARE_MODULE_ID对应的模块(.so库) */
status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
(hw_module_t const**)&mSensorModule);
......
/* 打开模块 */
err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
......
/* 这个模块列表中有多少个sensor */
ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
......
/* 设置容器大小 */
mActivationCount.setCapacity(count);
......
/* 激活/使能模块中所有sensors */
for (size_t i= ; i<size_t(count) ; i++) {
/* 添加sensor到容器 */
mActivationCount.add(list[i].handle, model);
/* 激活/使能sensors */
mSensorDevice->activate(
reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
list[i].handle, );
}
} ...... ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
......
do {
/* 轮询接收所有sensors上报的事件,填入sensors_event_t的buffer */
c = mSensorDevice->poll(reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
buffer, count);
} while (c == -EINTR);
return c;
} status_t SensorDevice::activate(void* ident, int handle, int enabled)
{
......
/* 初始化handle(sensor类型, 如ID_A)对应的info */
status_t SensorDevice::activate(void* ident, int handle, int enabled);
......
if (enabled) {
/* 如果ident客户端不存在 */
if (isClientDisabledLocked(ident)) {
return INVALID_OPERATION;
} /* 该客户端存在 */
if (info.batchParams.indexOfKey(ident) >= ) {
/* 只有一个客户端,第一个连接的 */
if (info.numActiveClients() == ) {
// This is the first connection, we need to activate the underlying h/w sensor.
actuateHardware = true;
}
}
} else {
/* ident移除成功(disable) */
if (info.removeBatchParamsForIdent(ident) >= ) {
/* 如果这是最后一个移除(disable)的客户端 */
if (info.numActiveClients() == ) {
// This is the last connection, we need to de-activate the underlying h/w sensor.
actuateHardware = true;
} else { }
}
/* 如果被disable,则直接返回 */
if (isClientDisabledLocked(ident)) {
return NO_ERROR;
}
} /* 如果是第一次激活(enable)或最后一个禁止(disable)sensor的
* 在这种情况下就根据handle(sensor类型)和enabled值,调用activate
* 来enable/disable对应的sensor
*/
if (actuateHardware) {
err = mSensorDevice->activate(
reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), handle, enabled);
}
} status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
int64_t maxBatchReportLatencyNs) {
......
/* 初始化handle(sensor类型, 如ID_A)对应的info */
Info& info(mActivationCount.editValueFor(handle)); /* 如果这个ident(key)不存在 */
if (info.batchParams.indexOfKey(ident) < ) {
BatchParams params(flags, samplingPeriodNs, maxBatchReportLatencyNs);
/* 则添加添加这个(ident, params) (key-value)对 */
info.batchParams.add(ident, params);
} else {
/* 如果存在,则更新这个ident */
// A batch has already been called with this ident. Update the batch parameters.
info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs);
} BatchParams prevBestBatchParams = info.bestBatchParams;
/* 为这个sensor找到所有最小的采样频率和事件上报最大延迟 */
// Find the minimum of all timeouts and batch_rates for this sensor.
info.selectBatchParams(); /* 如果最小的采样频率和事件上报最大延迟相对于上一次发生了变化 */
// If the min period or min timeout has changed since the last batch call, call batch.
if (prevBestBatchParams != info.bestBatchParams) {
......
err = mSensorDevice->batch(mSensorDevice, handle, info.bestBatchParams.flags,
info.bestBatchParams.batchDelay,
info.bestBatchParams.batchTimeout); }
......
} /*
关于mSensorDevice->batch(SensorDevice::batch()基于它封装一层,相当于他的实例)的作用,
相关的说明是: Sets a sensor’s parameters, including sampling frequency and maximum
report latency. This function can be called while the sensor is
activated, in which case it must not cause any sensor measurements to
be lost: transitioning from one sampling rate to the other cannot cause
lost events, nor can transitioning from a high maximum report latency to
a low maximum report latency.
See the Batching sensor results page for details:
http://source.android.com/devices/sensors/batching.html 意思是这是一个设置每个sensor的一些参数,包括采样频率,最大事件上报延迟,这个
函数可以在sensor被激活/使能时被调用,在这种情况下不能造成任何的sensor的测量
据丢失,如从一个采样率转换到另一个采样率的时候不能造成事件丢失,或从一个最大
上报延迟转换到另一个较低的最大上报延迟都不能造成事件丢失。 也就是说每个传感器都应该有一个batch,这个batch是负责调整采样频率和最大上报事
件延迟的参数,例如,在sensor激活的时候,可以调整一次这些参数。
*/ status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs)
{
......
Info& info( mActivationCount.editValueFor(handle)); /* 如果存在的sensor不是工作在continuous模式,那么setDelay()应该返回一个错误
* 在batch模式下调用setDelay()是没用的
*/
// If the underlying sensor is NOT in continuous mode, setDelay() should return an error.
// Calling setDelay() in batch mode is an invalid operation.
if (info.bestBatchParams.batchTimeout != ) {
return INVALID_OPERATION;
} /* 到了这里,说明sensor工作的continuous模式 */
/* 获得这个客户端对应的index */
ssize_t index = info.batchParams.indexOfKey(ident);
/* 根据这个index找到对应的batchParams值 */
BatchParams& params = info.batchParams.editValueAt(index);
/* 设置这个batchParams对应的batchDelay采样频率 */
params.batchDelay = samplingPeriodNs;
/* 保存batchParams到bestBatchParams */
info.selectBatchParams();
/* 实际上是调用了sensors_poll_context_t::setDelay */
return mSensorDevice->setDelay(reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
handle, info.bestBatchParams.batchDelay);
} status_t SensorDevice::flush(void* ident, int handle) {
......
/* 刷数据 */
return mSensorDevice->flush(mSensorDevice, handle);
} bool SensorDevice::isClientDisabled(void* ident) {
/* 上锁 */
Mutex::Autolock _l(mLock);
/* 返回客户端状态 */
return isClientDisabledLocked(ident);
} bool SensorDevice::isClientDisabledLocked(void* ident) {
/* 获取ident (key-value对)对应的索引,索引存在(>=0),返回true,
* 否则,返回false。即用于判断该客户端是否disable
*/
return mDisabledClients.indexOf(ident) >= ;
} void SensorDevice::enableAllSensors() {
for (size_t i = ; i< mActivationCount.size(); ++i) {
Info& info = mActivationCount.editValueAt(i);
......
const int sensor_handle = mActivationCount.keyAt(i);
......
/* 激活sensor_handle sensor */
err = mSensorDevice->activate(
reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
sensor_handle, );
/* 设置相应的采样频率 */
err = mSensorDevice->setDelay(
reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
sensor_handle, info.bestBatchParams.batchDelay);
}
} void SensorDevice::disableAllSensors() {
......
/* 逐个sensor disable */
for (size_t i = ; i< mActivationCount.size(); ++i) {
/* 获得一个sensor对应的info */
const Info& info = mActivationCount.valueAt(i);
// Check if this sensor has been activated previously and disable it.
if (info.batchParams.size() > ) {
/* 获得sensor类型 */
const int sensor_handle = mActivationCount.keyAt(i);
......
/* 禁止该sensor */
mSensorDevice->activate(
reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
sensor_handle, );
// Add all the connections that were registered for this sensor to the disabled
// clients list.
/* 禁止所有注册了这个sensor的client */
for (size_t j = ; j < info.batchParams.size(); ++j) {
mDisabledClients.add(info.batchParams.keyAt(j));
}
}
}
} status_t SensorDevice::injectSensorData(const sensors_event_t *injected_sensor_event) {
......
/* 增加一个sensor到mSensorDevice */
return mSensorDevice->inject_sensor_data(mSensorDevice, injected_sensor_event);
} status_t SensorDevice::setMode(uint32_t mode) {
......
/* 操作模式设置 */
return mSensorModule->set_operation_mode(mode);
} int SensorDevice::Info::numActiveClients() {
SensorDevice& device(SensorDevice::getInstance()); /* 检查batchParams容器中所有ident是否被disable
* 返回未被disable(即active/enable)的个数
*/
for (size_t i = ; i < batchParams.size(); ++i) {
/* 该ident未被disable */
if (!device.isClientDisabledLocked(batchParams.keyAt(i))) {
++num;
}
} return num;
} status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags,
int64_t samplingPeriodNs,
int64_t maxBatchReportLatencyNs) {
{
/* 从容器中找到indent(key)对应的index */
ssize_t index = batchParams.indexOfKey(ident);
......
/* 从容器中找到index索引对应的BatchParams
* 修改该BatchParams的采样频率和事件上报
* 最大延迟
*/
BatchParams& params = batchParams.editValueAt(index);
params.flags = flags;
/* 设置采样频率 */
params.batchDelay = samplingPeriodNs;
/* 事件上报最大延迟 */
params.batchTimeout = maxBatchReportLatencyNs;
......
} void SensorDevice::Info::selectBatchParams() {
BatchParams bestParams(, -, -);
SensorDevice& device(SensorDevice::getInstance());
/* 设置容器中所有未被disable(active/enable)的元素(ident)的值 */
for (size_t i = ; i < batchParams.size(); ++i) {
/* 如果该元素(ident)被disable,则继续查找下一个元素(ident) */
if (device.isClientDisabledLocked(batchParams.keyAt(i))) continue;
/* 获得该索引对应的元素的value (batchParams)值 */
BatchParams params = batchParams.valueAt(i);
if (bestParams.batchDelay == - || params.batchDelay < bestParams.batchDelay) {
/* 如果最新设置采样频率的值小于上一次的,采用最新的值 */
bestParams.batchDelay = params.batchDelay;
}
if (bestParams.batchTimeout == - || params.batchTimeout < bestParams.batchTimeout) {
/* 如果最新事件上报最大延迟的值小于上一次的,采用最新的值 */
bestParams.batchTimeout = params.batchTimeout;
}
} /*
* 这些参数只能往小调
*/ /* 保存到bestBatchParams */
bestBatchParams = bestParams;
}
到这里,基本代码已经分析完了,简单总结一下这个文件主要做了什么工作:
1. 加载.so库,sensors_module_t结构体中获得相关参数
2. 在.so库的基础上,再一次封装activate,setDelay,pollEvents等方法,
目的是为了支持更多的客户端(client)访问。如:struct Info结构体,
每一个sensor都对应有这样一个结构体,该结构体中有两比较重要的成员
是BatchParams bestBatchParams 和
KeyedVector<void*, BatchParams> batchParams。每一个client对应着
一个batchParams,每个client对应的都会传入一个参数到void *,与
BatchParams关联,从BatchParams中选择合适的参数保存到bestBatchParams
中。
3. 这个模块中在.so库的基础上增加了一些方法,但这里是连载前一篇博客
http://www.cnblogs.com/hackfun/p/7327320.html, 在前一篇博客中没
有实现一些flush,batch,inject_sensor_data的方法,因为
struct sensors_poll_device_t结构体重没有提供这些方法,而
struct sensors_poll_device_1结构体才提供这些方法,因此在下一篇
关于sensor service的博客中暂且忽略这些方法是使用
Android sensor 系统框架 (二)的更多相关文章
- Android sensor 系统框架 (一)
这几天深入学习了Android sensor框架,以此博客记录和分享分析过程,其中难免会有错误的地方,欢迎指出! 这里主要分析KERNEL->HAL->JNI这3层的流程.主要从以下几方面 ...
- Android动画学习(一)——Android动画系统框架简介
2015-11-09补充:Drawable Animation极有可能是Frame Animation 这几天在找工作,面试的时候被问到了Android动画,之前完全没接触过这部分,直接给懵了,当然其 ...
- 11.1 Android显示系统框架_framebuffer原理及改进
1. Android显示系统框架Android Graphic UI with GPU Hardware Accelerationhttps://community.nxp.com/docs/DOC- ...
- Android的系统框架
Android的系统架构采用了分层架构的思想,如图1所示.从上层到底层共包括四层,分别是应用程序程序层.应用框架层.系统库和Android运行时和Linux内核. 图1:Android系统架构图 每 ...
- Android Http请求框架二:xUtils 框架网络请求
一:对Http不了解的请看 Android Http请求框架一:Get 和 Post 请求 二.正文 1.xUtils 下载地址 github 下载地址 : https://github.com/w ...
- Android的系统框架的深入认识
Android采用层次化系统架构,官方公布的标准架构如下图所示.Android由底层往上分为4个主要功能层,分别是linux内核层(Linux Kernel),系统运行时库层(Libraries和An ...
- [置顶] Android Sensor系统剖析(4.0)(下)
Author:Harish_hu@qq.com 由于现在电脑上只有4.0的代码,考虑到代码差别也不大,所以下部分,就基于4.0来分析. 3:SensorManager 上一部分说过,开机后,syst ...
- 11.5 Android显示系统框架_Vsync机制_黄油计划_三个方法改进显示系统
5. Vsync机制5.1 黄油计划_三个方法改进显示系统vsync, triple buffering, vsync虚拟化 参考文档:林学森 <深入理解Android内核设计思想>第2版 ...
- 11.2 Android显示系统框架_android源码禁用hwc和GPU
2. 修改tiny4412_Android源码禁用hwc和gpu(厂家不会提供hwc和gpu的源代码,没有源代码就没法分析了,因此在这里禁用该功能并用软件库实现)最终源码: git clone htt ...
随机推荐
- Ubuntu16.04再次装机记
个人的吐槽 整个国庆假期(9天),基本上都在搭建PHP环境中耗费了. 是这样的——来大学报到前,想着大学里用个Dev-C++应该够了,于是把Ubuntu删了,腾出了100G的空间.到了CSU,加了团委 ...
- PatentTips - Hamming distance comparison
BACKGROUND INFORMATION In a typical data processing environment, data may be transmitted in multiple ...
- 用API中的raf复制文件图片等及系统找不到指定的文件的解决办法
该运行是在eclipse中进行的操作,小白的基础理解,如有不妥之处,请大佬们指正.QQ:1055802635 package raf; import java.io.IOException;impor ...
- idea常用快捷键汇总
自动导入或补全 Ctrl+空格,代码提示自动提示待输入项 Ctrl+Shift+空格,自动补全代码语句 Ctrl+Alt+空格,类名自动完成 Ctrl+Shift + Enter,语句完成(完成当前语 ...
- 混合图(dizzy.pas/cpp/c)
混合图(dizzy.pas/cpp/c) [题目描述] Hzwer神犇最近又征服了一个国家,然后接下来却也遇见了一个难题. Hzwer的国家有n个点,m条边,而作为国王,他十分喜欢游览自己的国家.他一 ...
- Java中DAO/DTO/PO/VO/BO/QO/POJO
ORM:是Object Relational Mapping(对象关系映射)的缩写. 通俗点讲,就是将对象与关系数据库绑定,用对象来表示关系数据.在O/R/M的世界里,有两个基本的也是重要的东东需要了 ...
- ASM instance正常启动,但是用sqlplus 连不上的问题
首先,这是oracle 11g 11.0.2.3 版本.这是一个神奇的问题. asm instance启动正常,但是用sqlplus 去连接的时候会显示如下: [oracle@racnode1 ~]$ ...
- A Complete Guide to Usage of ‘usermod’ command– 15 Practical Examples with Screenshots
https://www.tecmint.com/usermod-command-examples/ -------------------------------------------------- ...
- Java中集合List,Map和Set的差别
Java中集合List,Map和Set的差别 1.List和Set的父接口是Collection.而Map不是 2.List中的元素是有序的,能够反复的 3.Map是Key-Value映射关系,且Ke ...
- linux RHEL 修改hostname 不需要重启机器
1. 修改/etc/sysconfig/network 中的hostname HOSTNAME=newhostname 运行命令起作用: /etc/rc.d/rc.sysinit 2. 修改/ect/ ...