android使用服务访问硬件

1、源码目录和源码功能简要说明

1、首先在下面的目录下放入IIrRemoteService.aidl这个aidl接口然后编译,主要是为了生成IIrRemoteService.java接口
frameworks\base\core\java\android\os\IIrRemoteService.aidl

2.使用命令编译mmm frameworks/base,然后会生成IIrRemoteService.java
./out/soong/.intermediates/frameworks/base/framework/android_common/gen/aidl/frameworks/base/core/java/android/os/IIrRemoteService.java

3.IrRemoteService.java是继承IIrRemoteService.java,然后实现JNI的本地调用
\frameworks\base\services\core\java\com\android\server\IrRemoteService.java
\frameworks\base\services\java\com\android\server\SystemServer.java 将IrRemoteService.java添加到Server

4.com_android_server_IrRemoteService.cpp是实现java JNI本地调用的函数,里面会加载hal层so库
frameworks\base\services\core\jni\com_android_server_IrRemoteService.cpp
frameworks\base\services\core\jni\onload.cpp //将com_android_server_IrRemoteService.cpp加载到JNI

5.hal层的实现,会生成xxx.default.so库
hardware\libhardware\modules\irremote:
hardware\libhardware\modules\irremote\ir_remote_hal.c
hardware\libhardware\modules\irremote\Android.bp

2、编译命令

mmm frameworks/base                         编译aidl接口
mmm frameworks/base/services                编译java、cpp、JNI接口
mmm hardware/libhardware/modules/irremote   生成so库
make snod  or make systemimage-nodeps       生成system.img
make vendorimage-nodeps                     生成vendor.img

3、Android app如何使用服务访问硬件

1.在Android studio要调用的app中加载frameworks的jar包名字为classes.jar
classes.jar生成的路径:out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\classes.jar

2.在app中导入android.os.IIrRemoteService
import android.os.IIrRemoteService; 

3.获取服务
private IIrRemoteService iIrRemoteService = null;
iIrRemoteService = IIrRemoteService.Stub.asInterface(ServiceManager.getService("IrRemote")); //“IrRemote”为获取的服务名字,在SystemServer.java添加服务的时候传入。

4.使用服务定义好的接口调用接口
int[] code =  iIrRemoteService.GetIrRemoteCode();

4、可能出现的问题详解

1、使用命令mmm hardware/libhardware/modules/xxx 编译xxx模块的so库的时候发现生成的so库能生成在/out/target/product/rk3399/vendor/lib/hw/xxx.default.so,但是直接编译安卓系统无法生成在/out/target/product/rk3399/vendor/lib/hw/xxx目录,而是生成在了./out/target/product/rk3399/symbols/vendor/lib/hw/这个目录,打包vendor.img的时候无法将这个模块的so库打包进入vendor.img
解决思路:发现同目录下有vibrator.default.so库,而且是能生成生vendor/lib/hw/这个目录下的,所以猜测应该是有别的地方在Android.mk将这个so库进行复制和生成在vendor/lib/hw/目录下。
我们使用grep这个命令进行搜索发现

在所有的.mk类型的文件下搜索 vibrator.default关键字
find -type f -name '*.mk' | xargs grep "vibrator.default"
搜索结果如下
./device/generic/armv7-a-neon/mini_common.mk:    vibrator.default \
./build/make/target/product/generic_no_telephony.mk:    vibrator.default \

经过搜索果然发现在generic_no_telephony.mk这个编译脚本需要将 vibrator.default加入mk文件才会生成在vendor/lib/hw/,所以我们修改generic_no_telephony.mk这个文件将xxx.default加入到了Makefile,最终能在vendor/lib/hw/生成了xxx.default.so库。

2、hw_get_module无法获取module的原因
解决思路:我们知道获取module的使用方法是

err = hw_get_module("xxx", (hw_module_t const**)&module);

用来获取模块,但是运行结果发现是获取不到模块,如果获取不到模块首要思路是在“vendor/lib/hw/”或者“vendor/lib64/hw/”或者“system/lib/hw/”等目录下搜索有没有对应的xxx.default.so库,经过排查我们发现是有这个库文件的。但是呢?我们的问题出现在一个小细节, hw_get_module这个函数的时候调用如下

err = hw_get_module("IrRemote", (hw_module_t const**)&module); 

传入的ID为“IrRemote”,但是我们的so库的名字为“irremote.default.so”,我们发现“IrRemote”和“irremote”大小写有不对应的问题,所以找不带这个so库。所以我们需要在下面这3个地方的“irremote”名字一定要相同,否则hw_get_module无法获取module。

//om_android_server_IrRemoteService.cpp open so库
err = hw_get_module("irremote", (hw_module_t const**)&module);

//hal so库定义 \hardware\libhardware\modules\irremote\ir_remote_hal.c
struct hw_module_t HAL_MODULE_INFO_SYM = {
	.tag = HARDWARE_MODULE_TAG,
    .id = "irremote",                          
    .methods = &ir_remote_module_methods,
};

Makefile
hardware\libhardware\modules\irremote\Android.bp
cc_library_shared {
    name: "irremote.default",

    // HAL module implementation stored in
    // hw/<VIBRATOR_HARDWARE_MODULE_ID>.default.so
    relative_install_path: "hw",
    proprietary: true,
    header_libs: ["libhardware_headers"],
    srcs: ["ir_remote_hal.c"],
    cflags: ["-Wno-unused-parameter"],
    shared_libs: ["liblog"],
}

Guess you like

Origin blog.csdn.net/qq_27809619/article/details/118361685