技术标签: 北斗gps android hal层so库代码
Android-Gnss/GPS HAL层实现直通式修改为绑定式示例
为了能够让Android O之前的版本升级到Android O,Android设计了Passthrough模式,经过转换,可以方便的使用已经存在代码,不需要重新编写相关的HAL。
HIDL分为两种模式:Passthrough:翻译成直通式HAL。Binderized:翻译成绑定式HAL
一个编译成so库,供System分区的进程和应用直接加载调用,两者在同一个进程中,这种叫直通式 HAL(passthrough)模式,
另外一种是直接编译成一个daemon可运行的服务,然后System分区的进程通过HwBinder的IPC通信方式来调用,两者在各自独立的进程中,这种称为绑定式HAL(Binderized)模式。
直通式与绑定式最大的区别就是直通模式没有一个独立运行的服务进程,而绑定模式是作为一个独立运行的服务相当于Deamon进程在运行。
直通模式是将android 8.0之前的版本的module 封装起来,供System以上的服务进行调用,上层直接调用 HIDL_FETCH_XXX 来调用此接口的。
调用时都是通过 HIDL 工具生成的 getService() 来调用的,
getService() --> getServiceInternal() --> getRawServiceInternal();
然后后面的处理有所不同
直通模式,先通过 getPassthroughServiceManager(),获取IServiceManager的句柄
getPassthroughServiceManager() {
return new PassthroughServiceManager();
}
然后再get得到对应的服务,
get() {
openLibs() {
// 遍历so文件尝试查找 HIDL_FETCH_ 对应的接口并 registerPassthroughClient();
const std::string sym = "HIDL_FETCH_" + ifaceName;
function(void* handle, const std::string &lib, const std::string &sym) {
IBase* (*generator)(const char* name);
*(void **)(&generator) = dlsym(handle, sym.c_str());//返回值是void*,指向函数的地址,供调用使用
//generator 即 HIDL_FETCH_ 函数地址
if(!generator) {
const char* error = dlerror();
dlclose(handle);
return true;
}
ret = (*generator)(name.c_str()); //ret即 HIDL_FETCH_ 函数 返回的实例
if (ret == nullptr) {
dlclose(handle);
return true; // this module doesn't provide this instance name
}
// Actual fqname might be a subclass.
// This assumption is tested in vts_treble_vintf_test
using ::android::hardware::details::getDescriptor;
std::string actualFqName = getDescriptor(ret.get());
CHECK(actualFqName.size() > 0);
registerReference(actualFqName, name);
return false;
}
}
return ret; //ret即 HIDL_FETCH_ 函数 返回的实例
}
绑定模式就直接通过IServiceManager->get的方法去获取,直接对Binder驱动的操作来完成数据交换;
先来看一下 Gnss/GPS HAL service 直通式的实现方式
直接提供 HIDL_FETCH_IGnss 接口,该接口返回Gnss的实例对象;
IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
hw_module_t* module;
IGnss* iface = nullptr;
int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0) {
hw_device_t* device;
err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
if (err == 0) {
iface = new Gnss(reinterpret_cast(device));
} else {
ALOGE("gnssDevice open %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
}
} else {
ALOGE("gnss hw_get_module %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
}
return iface;
}
直通式是通过 HIDL_FETCH_IGnss() 直接获取到Gnss实例对象,然后直接在framework的进程空间操作(在framework的进程空间openLibs并获取到实例对象进行调用);
绑定式可以用两种方式来绑定服务,第一种通过 defaultPassthroughServiceImplementation 的调用来注册服务,另外一种是直接调用RegisterAsService来注册服务。
方式一
using android::hardware::gnss::V1_0::IGnss;
using android::hardware::defaultPassthroughServiceImplementation;
int main() {
android::ProcessState::initWithDriver("/dev/vndbinder");
return defaultPassthroughServiceImplementation();
}
其中 defaultPassthroughServiceImplementation 的定义在 system\libhidl\transport\include\hidl\LegacySupport.h
template
__attribute__((warn_unused_result))
status_t defaultPassthroughServiceImplementation(std::string name, size_t maxThreads = 1) {
configureRpcThreadpool(maxThreads, true); //配置binder线程个数
status_t result = registerPassthroughServiceImplementation(name);
if (result != OK) {
return result;
}
joinRpcThreadpool();
return 0;
}
template
__attribute__((warn_unused_result))
status_t registerPassthroughServiceImplementation(
std::string name = "default") {
sp service = Interface::getService(name, true /* getStub */); //从当前进程空间中拿到接口类对象
if (service == nullptr) {
ALOGE("Could not get passthrough implementation for %s/%s.",
Interface::descriptor, name.c_str());
return EXIT_FAILURE;
}
LOG_FATAL_IF(service->isRemote(), "Implementation of %s/%s is remote!",
Interface::descriptor, name.c_str());
status_t status = service->registerAsService(name);//通过IServicemanager的add 接口,添加到服务列表中
if (status == OK) {
ALOGI("Registration complete for %s/%s.",
Interface::descriptor, name.c_str());
} else {
ALOGE("Could not register service %s/%s (%d).",
Interface::descriptor, name.c_str(), status);
}
return status;
}
其中 registerAsService() 是通过hidl工具生成的
::android::status_t IDemo::registerAsService(const std::string &serviceName){
::android::hardware::details::onRegistration("[email protected]", "IDemo", serviceName);
const ::android::sp<::android::hidl::manager::v1_0::iservicemanager> sm = ::android::hardware::defaultServiceManager();
::android::hardware::Return ret = sm->add(serviceName.c_str(), this);
return ret.isOk() && ret ? ::android::OK :: android::UNKNOWN_ERROR;
}
方式二
首先增加如下头文件
#include
#include
#include
#include "Gnss.h"
参考原来直通式接口 HIDL_FETCH_IGnss() 中的实现,
同样需要new一个Gnss实例; 绑定式需要注册为服务即调用方法 registerAsService();
参考代码如下
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::gnss::V1_0::implementation::Gnss;
int main() {
configureRpcThreadpool(4, true);
Gnss *gnssHalService = nullptr;
hw_module_t* module;
int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0) {
hw_device_t* device;
err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
if (err == 0) {
gnssHalService = new Gnss(reinterpret_cast(device));
} else {
ALOGE("gnssDevice open %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
}
} else {
ALOGE("gnss hw_get_module %s failed: %d", GPS_HARDWARE_MODULE_ID, err);
}
if (gnssHalService == nullptr) {
return -1;
}
auto status = gnssHalService->registerAsService();
if (android::OK != status)
{
ALOGW("%s: Failed to register Gnss HAL implementation", __func__);
return -1;
}
ALOGI("Gnss registerAsService OK.");
joinRpcThreadpool();
return status; joinRpcThreadpool shouldn't exit
}
以上修改是绑定+so的实现方式,仍然需要打开一个so文件,不过是在hal service中打开so并运行的;
也可以将so中的实现一起整合到hal service中,不再编译单独的so文件;
springmvc静态资源配置多个location路径,使用逗号隔开,示例:优先加载文件夹中的assets目录下的资源,如果找不到再到classpath中找<mvc:resources location="/assets/,classpath:/assets/" mapping="/assets/**" />...
一、简答1.不用中间变量交换两个变量a、b的值。void exchang(void *a , void *b){ *a = *a + *b; *b = *a - *b; *a = *a - *b; //or *b = (*a+*b)-(*a = *b )}//这种方法在计算*a+*b时有溢出的危险Orvoid exchang(void
普通的程序员仅仅是完成自己的任务,完成任务后不思进取,不再修改自己的代码,不再去想有没有更好的实现方式,而优秀的程序员(geek):素质高、逻辑思维强、注重细节、注重安全开发、效率、耐心、进取心、健康等。现在深深的体会到,不仅仅人与人的差别是巨大的,程序员与程序员之间的差别同样是很明显的。 普通的程序员仅仅是完成自己的任务,完成任务后不思进取,不再修改自己的代码,不再去想有
------- WindowsPhone 7手机开发、.Net培训、期待与您交流! -------五、(例子2续)管理员管理的知识:数据的软删除bool:IsDeleted一个表引用另一张表的时候最好引用主键DeleteById(Guid id)Insert(Operator op)public Operator[] ListAll()ToOperator
This is a multi-part message in MIME format.--------------060803070607060703020603Content-Type: text/plain; charset=ISO-8859-1; format=flowedContent-Transfer-Encoding: 7bitHi folks.I posted a relates ...
SATA Host Core可以集成到FPGA中,兼容SATA-1(1.5Gbps),SATA-2(3.0Gbps),SATA-3(6.0Gbps)工业级接口标准,为SATA设备提供一种高效且易于使用的接口。 内核特性:兼容SATA 3.0规范 支持SATA-1(1.5Gbps),SATA-2(3.0Gbps),SATA-3(6.0Gbps)操作 Phy Layer包含FPGA T...
视口空间点是规范化的并相对于摄像机的. 摄像机的左下方为 (0, 0); 右上方为 (1, 1). Z轴的位置是以世界单位衡量到摄像机的距离A world space point is defined in global coordinates (eg.Transform.position) 世界空间中是以全局坐标定义的 (例如 Transform.position)See A
2011年,美国著名的《消费者报告》在针对171款相机、摄像机以及45款智能手机测评之后,得出的结论是“用智能手机拍摄的画质无法取代相机”。但是就在一年之后,年轻的努比亚...
1.下载devdevexpress14.1破解版下载:链接: http://pan.baidu.com/s/1kU35oN1 密码: 3kgv2.如果新建的form没有继承dev的样式则:只要在项目中的Program.cs中添加如下两句即可: DevExpress.Skins.SkinManager.EnableFormSkins(); DevExpress.Skins.SkinManager.EnableMdiFormSkins();即:
d435官方给出的测量范围为0.3~10m,实际使用时可能仅为0.40~4.6m,d435在机器人上的安装高度过低导致处于盲区无法观测。不同高度深度图输出:结论:d435存在观测盲区,低于一定高度时前下方部分区域无法观测,提高d435高度即可解决问题。...
从两个有序数组中寻找他们并集的第k小元素题目:两个排好序的数组A,B,大小分别为m,n,找到两个数组中所有元素的 第k小的元素 但是这种思路有一个问题,那就是如果A中元素没有k/2-1个的时候,就没办法用上述方法判断,不过此时可以使用取A中的所有元素,取B中的前k-m个元素 也可以按比例来取,比如取A中的前(m/(m+n))*k个元素,取B中前(k-(m/(m+n))*k)个元...
function [wSum StartPos EndPos] = MST_JunH(W_Matrix, headPos)% W_Matrix' = W_Matrix : 表示权值矩阵% headPos : 表示树头在W_Matrix的位置% wSum : 表示得到的最小生成树的权值总和% CopyRight : JunH 20130411[row col] = size(W_