#framework—> Vendor Interface —> hal
###Vendor Interface:
`Android O` 新增加的一个机制,用于将`framework` 与 `hal` 分开,便于在系统升级时,`OEM` 厂商 跳过`SoC` 厂商,先对`framework`进行升级。例如:
framework
与 hal
是紧耦合的存在于 system.img
中,因此进行版本升级时需要: OEM
厂商适配framework
,SoC
厂商适配hal
, 之后将修改打包到system.img
,生成OTA
升级包,推送到手机进行OTA
升级。
framework
与hal
进行了解耦, framework
存在于system.img
,hal
存在于vendor.img
,进行版本升级时,分为两次升级:
framework
升级: OEM
厂商适配 framework
,将修改打包到system.img
, 生成OTA
升级包,推送到手机进行OTA
升级(framework
发生改变,hal
层未变)。
hal
升级:SoC
厂商适配 hal
, 将修改打包到vendor.img
, 生成OTA
升级包,推送到手机进行OTA
升级(framework
发生改变,hal
层发生改变)。
OEM
厂商在8.0 之前,通过2 次升级的方式,也可以达到快速升级的目的啊。hal
层的修改打包到 vendor.img
就可以达到 目的,为什么要出一个 Vendor Interface
机制呢。在8.0 之前如果想要通过 2次升级的方式,达到快速升级的目的,需要进行的为:
a、 framework
升级: OEM
厂商 将原有的所有 hal
的实现、修改 分别找出,合入到新版本的代码中, 编译出 system.img
,生成OTA
包,推送升级
b、hal
升级: SoC
厂商 将适配后的hal
释放给 OEM
厂商, 在编译一个system.img
, 生成OTA
包,推送升级.
因为hal
的实现,分布在不同的位置,也有的是直接提供的so
库, OEM
厂商需要一个个找出替换,然后编译成包,进行升级。 等SoC
厂商释放出修改后,OEM
厂商需要在一个个替换会去,然后编译成包,进行二次升级, OEM
厂商工作量较大,且过程过于繁琐,容易出错。
将hal
的修改,打包到 Vendor.img
中就可以达到 快速升级的目的,为什么要出一个 Vendor Interface
的机制呢?
8.0 之前,是在jni
中打开相关的so
库,对hal
进行操作的, framework
可以随时通过jni
对 hal
进行访问修改,它存在 framework
与 hal
耦合性较高、两者通信的接口定义不明确等问题。为了规范通信接口,将framework
与hal
进行隔离,google
引入了Vendor Interface
机制( 存疑,这只是我的理解,对不对存疑 )。
###hidl(Hardware Interface Definition Language)
:
类似aidl 的东西,framework
与 hwservice
进行数据通信的接口定义语言。
hwService
的启动以 gnss
服务为例:
gnss
服务在开机时, 通过 rc
文件启动AndroidO/hardware/interfaces/gnss/1.0/default/[email protected]
service gnss_service /vendor/bin/hw/[email protected]
class hal
user gps
group system gps radio
AndroidO/hardware/interfaces/gnss/1.0/default/service.cpp
using android::hardware::gnss::V1_0::IGnss;
using android::hardware::defaultPassthroughServiceImplementation;
int main() {
android::ProcessState::initWithDriver("/dev/vndbinder");
return defaultPassthroughServiceImplementation();
}
模式:passthrough
或者binderized
passthrough:
直通模式,创建服务 并添加到 hwservice_manager
时使用
binderized:
绑定模式,用于提供给client 使用
此处是通过调用 defaultPassthroughServiceImplementation
方法走直通模式。
AndroidO/system/libhidl/transport/include/hidl/LegacySupport.h
template
__attribute__((warn_unused_result))
status_t defaultPassthroughServiceImplementation(size_t maxThreads = 1)
{
return defaultPassthroughServiceImplementation("default", maxThreads);
}
template
__attribute__((warn_unused_result))
status_t defaultPassthroughServiceImplementation(std::string name, size_t maxThreads = 1) {
configureRpcThreadpool(maxThreads, true); //设置用于 IPC 通信的进程数
//使用直通模式,创建 gnss 服务, 并将其添加到 hwService_manager
status_t result = registerPassthroughServiceImplementation(name);
//service 端开始循环等待 client 端的连接
joinRpcThreadpool();
return 0;
}
template
__attribute__((warn_unused_result))
status_t registerPassthroughServiceImplementation(std::string name = "default") {
// 通过 hidl 的模板代码,创建 gnss 服务
sp service = Interface::getService(name, true /* getStub */);
//通过模板代码,将创建的服务,添加进入 hwService_manager 中
status_t status = service->registerAsService(name);
return status;
}
gnss
服务, 并添加到 hwService_manager
out/soong/.intermediates/hardware/interfaces/gnss/1.0/[email protected]_genc++/gen/android/hardware/gnss/1.0/GnssAll.cpp
::android::sp IGnss::getService(const std::string &serviceName, const bool getStub) {
using ::android::hardware::defaultServiceManager;
using ::android::hardware::details::waitForHwService;
using ::android::hardware::getPassthroughServiceManager;
using ::android::hardware::Return;
using ::android::sp;
using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;
sp iface = nullptr;
//获取hwService_manager 的client端 代理对象
const sp<::android::hidl::manager::V1_0::IServiceManager> sm=defaultServiceManager();
// IGnss::descriptor("[email protected]::IGnss");
// 从 /system/manifest.xml
// /vendor/manifest.xml
//获取 gnss 通信的 类型
// system/hwservicemanager/Vintf.cpp ---> /system/libvintf/VintfObject.cpp
Return transportRet = sm->getTransport(IGnss::descriptor, serviceName);
Transport transport = transportRet;
//判断是直通模式 还是 代理模式
const bool vintfHwbinder = (transport == Transport::HWBINDER);
const bool vintfPassthru = (transport == Transport::PASSTHROUGH);
//代理模式,会从hwservice_manager 中获取 service 的代理对象,并返回
for (int tries = 0; !getStub && (vintfHwbinder || (vintfLegacy && tries == 0)); tries++) {
if (vintfHwbinder && tries > 0) {
waitForHwService(IGnss::descriptor, serviceName);
}
Return> ret =
sm->get(IGnss::descriptor, serviceName);
sp<::android::hidl::base::V1_0::IBase> base = ret;
Return> castRet = IGnss::castFrom(base, true /* emitError */);
iface = castRet;
return iface;
}
//直通模式, 创建service 对象,并返回, 此处 getStub 的传入值为true,所以此处走的是直通模式
if (getStub || vintfPassthru || vintfLegacy) {
const sp<::android::hidl::manager::V1_0::IServiceManager> pm = getPassthroughServiceManager();
if (pm != nullptr) {
Return> ret =
pm->get(IGnss::descriptor, serviceName);
if (ret.isOk()) {
sp<::android::hidl::base::V1_0::IBase> baseInterface = ret;
if (baseInterface != nullptr) {
iface = new BsGnss(IGnss::castFrom(baseInterface));
}
}
}
}
return iface;
}
const char* IGnss::descriptor("[email protected]::IGnss");
getPassthroughServiceManager
获取直通模式的 PassthroughServiceManager
AndroidO/system/libhidl/transport/ServiceManagement.cpp
sp getPassthroughServiceManager() {
return getPassthroughServiceManager1_1();
}
sp getPassthroughServiceManager1_1() {
static sp manager(new PassthroughServiceManager());
return manager;
}
pm->get(IGnss::descriptor, serviceName)
由 PassthroughServiceManager
获取 service
的代理对象IGnss::descriptor
: "[email protected]::IGnss"
serviceName
: "default"
get
方法 调用 openLibs
方法来 打开对应 so
库, 实例化 servcie
对象
Return> get(const hidl_string& fqName,
const hidl_string& name) override {
sp ret = nullptr;
//调用openLibs 函数,并传入一个匿名函数,此函数会在 openLibs中回调,
//此匿名函数的 参数为:
//handle service 对应so库的句柄
// lib : so库对象
// sym : service对象初始化的入口方法
//此匿名方法的作用: 使用handle句柄找出so文件中sym方法, 然后调用此方法,创建出service对象
openLibs(fqName, [&](void* handle, std::string &lib, std::string &sym) {
IBase* (*generator)(const char* name);
// 找到 service 对象 初始化的入口方法 sym
*(void **)(&generator) = dlsym(handle, sym.c_str());
//调用 入口方法,创建初始化 service 对象
ret = (*generator)(name.c_str());
//将此 service的信息 注册到 hwservice_manager 中
registerReference(fqName, name);
return false;
});
return ret;
}
openLibs
打开指定 so
库,获取初始化函数,创建 service
对象fqName
: "[email protected]::IGnss"
std::function
: get
中传入的匿名方法
struct PassthroughServiceManager : IServiceManager1_1 {
static void openLibs(const std::string& fqName,
std::function eachLib) {
size_t idx = fqName.find("::");
//packageAndVersion :[email protected]
//packageAndVersion 用于组成so库文件名
std::string packageAndVersion = fqName.substr(0, idx);
//ifaceName : IGnss
//用于组成 service 的初始化函数名
std::string ifaceName = fqName.substr(idx + strlen("::"));
//prefix : [email protected]
// prefix : so 库文件名
const std::string prefix = packageAndVersion + "-impl";
//sym :HIDL_FETCH_IGnss
//sym : 初始化函数名
const std::string sym = "HIDL_FETCH_" + ifaceName;
const int dlMode = RTLD_LAZY;
void *handle = nullptr;
//会从一下目录搜索对应 service 的so 库
std::vector paths = {
/odm/lib64/hw/ HAL_LIBRARY_PATH_ODM,
/vendor/lib64/hw/ HAL_LIBRARY_PATH_VENDOR,
/system/lib64/vndk-sp/hw/ HAL_LIBRARY_PATH_VNDK_SP,
/system/lib64/hw/ HAL_LIBRARY_PATH_SYSTEM};
// 遍历 paths 查找名为prefix 的 so库
for (const std::string& path : paths) {
std::vector libs = search(path, prefix, ".so");
for (const std::string &lib : libs) {
const std::string fullPath = path + lib;
if (path != HAL_LIBRARY_PATH_SYSTEM) {
handle = android_load_sphal_library(fullPath.c_str(), dlMode);
} else {
//打开查找到的so 库文件
handle = dlopen(fullPath.c_str(), dlMode);
}
//调用get方法中传入的匿名方法
//handle :打开so库的句柄文件
//lib : so库对象
//sym : service初始化方法的方法名
if (!eachLib(handle, lib, sym)) {
return;
}
}
}
}
service
对象在get
—>openLibs
中会 找到 service
的入口方法(方法名一般为:HIDL_FETCH_***
), 然后调用此方法初始化构建 service
对象
AndroidO/hardware/interfaces/gnss/1.0/default/Gnss.cpp
IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
hw_module_t* module;
IGnss* iface = nullptr;
//打开service 对应的模块,并获取module结构体,
// 在此处对应的为 gps 模块
//GPS_HARDWARE_MODULE_ID gps
int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0) {
hw_device_t* device;
// 如果正确打开对应模块,并获取到了 module 结构体,那么调用模块内对应的open 方法,获取 device 驱动对象
err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
if (err == 0) {
//使用device 对象,构建出 Gnss service对象
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);
}
//将Gnss service 对象返回给 openLibs 函数
return iface;
}
通过 hw_get_module
方法,打开对应模块的so库
/hardware/libhardware/hardware.c
id
: 在此处为 gps
module
: 需要初始化的 模块对象
int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
int i = 0;
char prop[PATH_MAX] = {0};
char path[PATH_MAX] = {0};
char name[PATH_MAX] = {0};
char prop_name[PATH_MAX] = {0};
//此处 inst 为 null, 将name cpy为 gsp
if (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
else
strlcpy(name, class_id, PATH_MAX);
//拼接 prop_name 为: ro.hardware.gps
//从property 中查找 此配置项, 如果存在调用 hw_module_exists 获取 module 对应的so库
snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
if (property_get(prop_name, prop, NULL) > 0) {
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* static const char *variant_keys[] = {
"ro.hardware",
"ro.product.board",
"ro.board.platform",
"ro.arch"
}; */
//遍历 HAL_VARIANT_KEYS_COUNT ,查找他们的配置项,如果存在对应配置项,根据hw_module_exists 获取 module 对应的so
// 此配置项一般为 product 名
for (i=0 ; i
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
#define HAL_LIBRARY_PATH3 "/odm/lib/hw"
// 此函数会在 以上三个路径中,进行判断 指定 so库 是否存在
//gps 对应的为 HAL_LIBRARY_PATH/gps.subname.so
static int hw_module_exists(char *path, size_t path_len, const char *name, char *subname)
{
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH3, name, subname);
if (access(path, R_OK) == 0)
return 0;
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, subname);
if (access(path, R_OK) == 0)
return 0;
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, subname);
if (access(path, R_OK) == 0)
return 0;
return -ENOENT;
}
######9. 模块内部的初始化
int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
最后调用到模块内部为:
AndroidO/hardware/qcom/gps/msm8960/loc_api/libloc_api_50001/gps.c
首先将 HAL_MODULE_INFO_SYM
初始化到 module
:
struct hw_module_t HAL_MODULE_INFO_SYM = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = 1,
.hal_api_version = 0,
.id = GPS_HARDWARE_MODULE_ID,
.name = "loc_api GPS Module",
.author = "Qualcomm USA, Inc.",
.methods = &gps_module_methods, };
static struct hw_module_methods_t gps_module_methods = {
.open = open_gps
};
然后调用module
的open
方法,此处对应的 为 gps_module_methods
中的open_gps
方法,
在此方法中,会构建出一个dev
对象,并将它赋值为 传入的hw_device_t
结构体
static int open_gps(const struct hw_module_t* module, char const* name,
struct hw_device_t** device)
{
struct gps_device_t *dev = (struct gps_device_t *) malloc(sizeof(struct gps_device_t));
memset(dev, 0, sizeof(*dev));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (struct hw_module_t*)module;
dev->get_gps_interface = gps__get_gps_interface;
*device = (struct hw_device_t*)dev;
return 0;
}
在之后 使用 hw_device_t
结构体 构建出gnss
服务对象,gnss
的初始化方法中会调用 dev
的get_gps_interface
方法,获取hal
的方法接口对象:
gnss
服务对象的初始化 err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
iface = new Gnss(reinterpret_cast(device));
gnss
获取hal
的方法接口对象
~/source/AndroidO/hardware/interfaces/gnss/1.0/default/Gnss.cpp
Gnss::Gnss(gps_device_t* gnssDevice) : mDeathRecipient(new GnssHidlDeathRecipient(this)) {
//获取所有的方法接口对象
mGnssIface = gnssDevice->get_gps_interface(gnssDevice);
}
get_gps_interface
在hal
层的实现为:
extern "C" const GpsInterface* get_gps_interface()
{
unsigned int target = TARGET_DEFAULT;
loc_eng_read_config();
target = get_target();
if( getTargetGnssType(target) == GNSS_GSS ) {
gps_conf.CAPABILITIES &= ~(GPS_CAPABILITY_MSA | GPS_CAPABILITY_MSB);
gss_fd = open("/dev/gss", O_RDONLY); //hal 层会通过 /dev/gss 节点操作gps
}
return &sLocEngInterface; //hal 层 对外暴露的 方法接口对象
}