连载上一篇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 系统框架 (二)的更多相关文章

  1. Android sensor 系统框架 (一)

    这几天深入学习了Android sensor框架,以此博客记录和分享分析过程,其中难免会有错误的地方,欢迎指出! 这里主要分析KERNEL->HAL->JNI这3层的流程.主要从以下几方面 ...

  2. Android动画学习(一)——Android动画系统框架简介

    2015-11-09补充:Drawable Animation极有可能是Frame Animation 这几天在找工作,面试的时候被问到了Android动画,之前完全没接触过这部分,直接给懵了,当然其 ...

  3. 11.1 Android显示系统框架_framebuffer原理及改进

    1. Android显示系统框架Android Graphic UI with GPU Hardware Accelerationhttps://community.nxp.com/docs/DOC- ...

  4. Android的系统框架

    Android的系统架构采用了分层架构的思想,如图1所示.从上层到底层共包括四层,分别是应用程序程序层.应用框架层.系统库和Android运行时和Linux内核.  图1:Android系统架构图 每 ...

  5. Android Http请求框架二:xUtils 框架网络请求

    一:对Http不了解的请看 Android Http请求框架一:Get 和 Post 请求 二.正文 1.xUtils 下载地址 github 下载地址  : https://github.com/w ...

  6. Android的系统框架的深入认识

    Android采用层次化系统架构,官方公布的标准架构如下图所示.Android由底层往上分为4个主要功能层,分别是linux内核层(Linux Kernel),系统运行时库层(Libraries和An ...

  7. [置顶] Android Sensor系统剖析(4.0)(下)

    Author:Harish_hu@qq.com 由于现在电脑上只有4.0的代码,考虑到代码差别也不大,所以下部分,就基于4.0来分析.  3:SensorManager 上一部分说过,开机后,syst ...

  8. 11.5 Android显示系统框架_Vsync机制_黄油计划_三个方法改进显示系统

    5. Vsync机制5.1 黄油计划_三个方法改进显示系统vsync, triple buffering, vsync虚拟化 参考文档:林学森 <深入理解Android内核设计思想>第2版 ...

  9. 11.2 Android显示系统框架_android源码禁用hwc和GPU

    2. 修改tiny4412_Android源码禁用hwc和gpu(厂家不会提供hwc和gpu的源代码,没有源代码就没法分析了,因此在这里禁用该功能并用软件库实现)最终源码: git clone htt ...

随机推荐

  1. 公众号开发 jsp中<a>问题

    在开发微信公众号时,使用了jQuery mobile这个框架,但是在jsp页面中使用<a>发现点击跳转不成功,这就很奇怪了,网上搜索发现大家基本上用js来代替<a>跳转功能: ...

  2. java 源码分析1 -String

    1. String的本质是一个 char数组,实现了CharSequence 接口, /** The value is used for character storage. */ private f ...

  3. log4j.properties的简单配置和使用

    log4j.properties  // 日志文件名不能随便写, 是properties文件 log4j.rootLogger=INFO, Console //表示INFO级别 输出到控制台 #Con ...

  4. Spring Web Flow 入门demo(二)与业务结合 附源代码

    第一部分demo仅仅介绍了简单的页面跳转,接下来我们要实现与业务逻辑相关的功能. 业务的逻辑涉及到数据的获取.传递.保存.相关的业务功能函数的调用等内容,这些功能的实现都可用Java 代码来完毕,但定 ...

  5. 自己定义控件:onDraw 方法实现仿 iOS 的开关效果

    概述 本文主要解说怎样在 Android 下实现高仿 iOS 的开关按钮,并不是是在 Android 自带的 ToggleButton 上改动,而是使用 API 提供的 onDraw.onMeasur ...

  6. Android从源码看ListView的重用机制

    不管是android还是iOS,列表视图应该是最复杂的控件了.android中的listview从命名能够看出是个一维数组,而iOS中的tableview则是二维数组.但事实上须要注意的地方是差点儿相 ...

  7. XCode 7 高速切换代码窗体和文档窗体

    XCode 7 高速切换代码窗体和文档窗体 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 ...

  8. Android studio 解决setText中文乱码问题

    我在用Android Studio编译器的时候,总会遇到非常多乱码的问题.第一个乱码问题是在Layout文件中面定义了EditText.在代码中须要将获取到的内容填充到EditText里面,这时候假设 ...

  9. Wireshark 抓包遇到 you don’t have permission to capture on that device mac 错误的解决方案

    Wireshark 抓包遇到 you don’t have permission to capture on that device mac 错误的解决方案 上次有篇博客讲了如何利用wireshark ...

  10. LeetCode 811. Subdomain Visit Count (子域名访问计数)

    题目标签:HashMap 题目给了我们一组域名,让我们把每一个域名,包括它的子域名,计数. 遍历每一个域名,取得它的计数,然后把它的所有子域名和它自己,存入hashmap,域名作为key,计数作为va ...