- 一. bring up 流程
- 前提
- 1.Google原生框架编译
- 2. manifest.xml文件配置
- 3. 驱动调试
- 3.1 添加driver
- 3.2 添加dts
- 3.3TA移植
- 3.3.1 修改配置文件
- 4.修改原生openHAL
- 二.调试方法:
1.服务器拉取代码,可编译,可烧录,烧录后,设备可正常启动,TP和屏的能正常使用 2.FAE已经提供软件代码1.Google原生框架编译
Android原生的配置不会编译指纹相关的原生bin和库文件,需要在bengal.mk中添加打包的配置。具体操作:
验证生效后,adb shell进入手机
ps -A|grep fingerprint
可以查看到这个服务android.hardware.biometrics.fingerprint@2.1-service
文件路径:device/qcom/bengal/manifest.xml
添加如下配置:
hardware/interfaces/compatibility_matrices/compatibility_matrix.legacy.xml
hardware/interfaces /compatibility_matrices/compatibility_matrix.4.xml
hardware/interfaces /compatibility_matrices/compatibility_matrix.5.xml
添加内容如下:
配置成功后,可以在/vendor/etc/vintf/manifest.xml中查看,也可以adb pull /vendor/etc/vintf/manifest.xml 拉到本地查看
将FAE提供的driver代码copy到kernel/msm-4.19下
上图为供应商提供的代码
第三部:添加相应的Makefile 和 Kconfig
一级一级的添加,先在drivers/Makefile 中添加
drivers/Kconfig中添加
drivers/fps/focaltech/Kconfig 中添加
drivers/fps/focaltech/Makefile中添加
arch/arm64/configs/vendor/bengal-perf_defconfig
arch/arm64/configs/vendor/bengal_defconfig 中添加
找到此项目中相对应的设备树文件,此项目中设计到两个文件
vendor/qcom/proprietary/devicetree-4.19/qcom/DrDoom/sm6115-fps.dtsi
vendor/qcom/proprietary/devicetree-4.19/qcom/DrStrange/sm4250-fps.dtsi
烧录:adb reboot bootloader
fastboot flash boot boot.img
fastboot flash dtbo dtbo.img
fastboot reboot
重新开机后,查看设备节点有没有生成
这里我们看到当前节点的权限是rw------- 为了能够让上层调用,我们需要给这个节点添加权限:修改文件 /vendor/qcom/bengal / init.target.rc
为了方便测试,我们也可以直接adb修改手机文件
adb pull vendor/etc/init/hw/init.target.rc
修改完过后再push进去
adb push init.target.rc vendor/etc/init/hw/
重启后查看节点权限是否修改成功。
设备节点生成,驱动部分移植完毕。
3.3TA移植此项目的tz平台是: TZ.XF.5.1
路径 target/vendor/qcom/non-hlos/TZ.XF.5.1
直接将供应商给的文件放入 trustzone_images 文件夹下
路径:
build/ms/build_config_deploy.xml
build/ms/build_config_deploy_kamorta.xml
添加内容
文件目录:hardware/interface/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
通过hw_get_module_t来找到注册的硬件对象。达到兼容多个模组
hardware/libhardware/hardware.c
static const char *variant_keys[] = {
“ro.hardware”,
“ro.product.board”,
“ro.board.platform”,
“ro.arch”
};
// 由上面定义的字符串数组可知,HAL_VARIANT_KEYS_COUNT的值为4
struct constint HAL_VARIANT_KEYS_COUNT =
(sizeof(variant_keys)/sizeof(variant_keys[0]));
int hw_get_module(const char *id, const struct hw_module_t **module)
{
// 调用3个参数的hw_get_module_by_class函数
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 status;
int i;
// 声明一个hw_module_t指针变量hmi
const struct hw_module_t hmi = NULL;
char prop[PATH_MAX};
char path[PATH_MAX];
char name[PATH_MAX];
// 由前面调用函数可知,inst = NULL,执行else部分,
// 将硬件id名拷贝到name数组里
if(inst)
snprintf(name, PATH_MAX, “%s.%s”, class_id, inst);
else
strlcpy(name, class_id, PATH_MAX);
// i 循环5次
for(i=0; iif(i /
从系统属性里依次查找前面定义的4个属性的值,找其中一个后,
执行后面代码,找不到,进入else部分执行
/
if(property_get(variant_keys[i], prop, NULL) == 0){
continue;
}
/
找到一个属性值prop后,拼写path的值为:
/vendor/lib/hw/硬件id名.prop.so
/
snprintf(path, sizeof(path), “%s/%s.%s.so”,
HAL_LIBRARY_PATH2, name, prop);
if(access(path, R_OK) ==0) break;
/ 如果path指向有效的库文件,退出for循环,
如果vendor/lib/hw目录下没有库文件,
查找/system/lib/hw目录下有没有:硬件id名.prop.so的库文件,
/
snprintf(path, sizeof(path), “%s/%s.%s.so”,
HAL_LIBRARY_PATH1, name, prop);
if(access(path, R_OK) == 0) break;
} else {
/ 如果4个系统属性都没有定义,则使用默认的库名:
/system/lib/hw/硬件id名.default.so
/
snprintf(path, sizeof(path), “%s/%s.default.so”,
HAL_LIBRARY_PATH1, name);
If(access(path, R_OK) == 0) break;
}
}
status = -ENOENT;
if(istatus = load(class_id, path, module);
/
加载前面查找到的so库。。
*/
}
return status;
}
static int load(const char *id, counst char *path,
const struct hw_module_t **pHmi){
void handle;
struct hw_module_t * hmi;
// 通过dlopen打开so库
handle = dlopen(path, RTLD_NOW);
// sym的值为”HMI”,这个名字还有印象吗?
const char * sym = HAL_MODULE_INFO_SYM_AS_STR;
/ 通过dlsym从打开的库里查找”HMI”这个符号,如果在so代码里有定义的函数名
或变量名为HMI,dlsym返回其地址hmi,将该地址转化成hw_module_t类型,
即,硬件对象,这招够狠,“杀鸡取卵”
*/
hmi = (struct hw_module_t )dlsym(handle, sym);
/
判断找到的硬件对象的id是否和要查找的id名一致,不一致出错退出
/
if(strcmp(id, hmi->) != 0){
// 出错退出处理
}
/ 将库的句柄保存到hmi硬件对象的dso成员里 /
hmi->dso = handle;
/
将硬件对象地址送给 load 函数者,
最终将硬件对象返回到了 hw_get_module 的调用者
*/
*pHmi = hmi;
// 成功返回
}
硬件对象声明的结构体代码被编译成了so库,由于该结构体声明为const类型,被so库包含在其静态代码段里。
要找到硬件对象,首先要找到其对应的so库,再通过 dlopen,dlsym 这种“杀鸡取卵”的方式找到硬件对象。
在声明结构体led_module_t时,其名字统一定义为了HMI,而这么做的目的就是为了通过dlsym来查找led HAL Stub源码生成的so库里的”HMI”符号。现在很明显了,我们写的HAL Stub代码最终要编译so库文件,并且库文件名为:xxxx.default.so,并且库的所在目录为:/system/lib/hw/。
/system/lib/hw 下是库又是怎么来的呢?
其实是来自vendor/qcom/proprietary/fingerprint/focaltech/lib
有兴趣的话可以继续看看该库的格式结构,方便理解上面load是怎么实现的
参考大神博客,参考链接如下:
https://outfox.blog.csdn.net/article/details/8074549
做到这步,指纹需要的代码就已经全部移植了,就可以验证指纹功能了;但有个条件,需要先关闭selinux 命令是adb shell setenforce 0,当然也可以在代码中关闭,此项目中用命令关闭就可验证功能。命令如下:
adb reboot
adb wair-for-device shell setenforce 0
由于adb服务启动的比较早,会在指纹服务启动之前启动,所以指纹服务启动之前,我们可以用setenforce命令来关闭selinux,被指纹营造一个selinux关闭的环境。
正常情况下, 会在设置安全的菜单中看到指纹选项,可以在设置中进行指纹的录入和解锁测试。如果设置中没有指纹选项出现。则需要抓取log进行分析,命令如下:
adb reboot
log分析从openHal开始进行分析,如果出现如下log
上层无法识别到指纹设备导致无指纹选项
修改farmeworks下
指纹启动流程详细分析参考大佬博客介绍
https://blog.csdn.net/weixin_43943188/article/details/88321101



