硬件访问服务

前面完成了HAL往下的理解学习,下面就应该是service相关的了。老罗的书上直接就开始带领着写service相关的代码了,但自己还是尚未搞明白。上网了解了一下,没有弄得太明白,(此点暂时留白),暂且先沿着这个路线继续向下吧。service到这里首先是AIDL接口,先对此做一了解。

1. 是什么

AIDL: Android Interface Definition Language,安卓接口定义语言,是一门语言,有特定的语法和使用场景。

2. 用来做什么

AIDL主要用来生成用于IPC的代码,也就是不是用AIDL的代码,而是使用通过这种语言生成的一个实例的代码。这个代码主要用来进行进程间通信。而进程间通信有多种方式,根据场景不同就会选用不同的方式,比如binder方式、Message、AIDL。AIDL主要用于多进程并发的进程间通信。

3. 怎么用

•服务端创建一个AIDL文件,将暴露给客户端的接口在里面声明
•在service中实现这些接口
•客户端绑定服务端,并将onServiceConnected()得到的IBinder转为AIDL生成的IInterface实例
•通过得到的实例调用其暴露的方法

写一个简单的学习测试实例。
在frameworks/base/core/java/android/os/目录下新建IFregService.aidl文件,用来描述我们的service提供的接口。

package android.os;

interface IFregService {
        void setVal(int val);
        int getVal();
}

在frameworks/base/Android.mk中加入此文件,搜索 LOCAL_SRC_FILES 变量,在合适的位置插入此文件的声明。

[frank@frank-laptop workingdir]$ mmm frameworks/base/
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.3
TARGET_PRODUCT=aosp_arm
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
TARGET_CPU_VARIANT=generic
HOST_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-4.4.0-96-generic-x86_64-with-Ubuntu-16.04-xenial
HOST_BUILD_TYPE=release
BUILD_ID=JWR66V
OUT_DIR=out
============================================
make: Entering directory `/home/mydata3/workingdir'
target Java: framework (out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes)
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Copying: out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes-jarjar.jar
Copying: out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/emma_out/lib/classes-jarjar.jar
Copying: out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
Copying: out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/noproguard.classes.jar
target Dex: framework
Copying: out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/noproguard.classes.dex
target Jar: framework (out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/javalib.jar)
Dexpreopt Boot Jar: out/target/product/generic/dex_bootjars/system/framework/framework.odex
Processing target/product/generic/dex_bootjars/system/framework/framework.jar
Done!
Install: out/target/product/generic/system/framework/framework.odex
Install: out/target/product/generic/system/framework/framework.jar
make: Leaving directory `/home/mydata3/workingdir'

在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os目录下生成两个文件 IFregService.java IFregService.P。(这个两个文件具体怎么用,还不知道)
此文件中定义了IFregService类,继承于android.os.IInterface类

public interface IFregService extends android.os.IInterface

这里还定义了其他的一些方法,我们主要关心的是自定义的两个接口。这里定义了两个接口,就是暴露给client调用的两个接口,下面就是要具体实现这两个接口。
在framework/base/service/core/java/com/android/server/下新建FregService.java文件,也就是创建FregService类,这个类继承了上面生成的文件

public int getVal() {
        if(mPtr == 0) {
           Slog.e(TAG, "Freg service is not initialized.");
           return 0;    
        }

        return getVal_native(mPtr);
}

注意,这里还是java文件,要通过jni方法来调用到c/c++接口了。
这个文件编写完成后,重新编译services模块,mmm frameworks/base/services/java/

下来就是jni相关文件,在frameworks/base/services/jni目录下。注意,此时已经到c++文件了,可以调用c/c++接口了,这样就可以调用到HAL层的代码了。
关于JNI的详细学习可以参考JNI学习

这个文件编写完成后,修改frameworks/base/services/jni/Android.mk文件,加入此文件。然后执行命令mmm frameworks/base/services/jni/重新编译jni库,就可以得到新的libandroid_servers.so库。新库中就包含有自定义的jni接口。

Install: out/target/product/generic/system/lib/libandroid_servers.so

这里有个疑问:关于jniRegisterNativeMethods接口的调用及参数。

jniRegisterNativeMethods(env, "com/android/server/FregService", method_table, NELEM(method_table));

Android系统的硬件访问服务通常是在系统进程System中启动的,而系统进程System是由应用程序孵化器进程Zygote负责启动的。由于Zygote是在系统启动时启动的,因此,把硬件访问服务运行在系统System中,就实现了开机自动启动。
这里有个问题,之前在写freg驱动时,没有编译进内核,而是以ko的形式编译的,在system中的启动脚本中做的insmod操作,那就要看是否在Zygote进程启动之前,如果是,则这里启动没有问题,如果不是,估计会出现服务加载失败的问题。

把硬件访问服务运行在System中,修改frameworks/base/services/java/com/android/server/SystemServer.java文件,仿照其他服务加载形式,添加FregServer服务。

///add freg service
            try {
                Slog.i(TAG, "Freg service.");
                ServiceManager.addService("freg", new FregService());
            } catch (Throwable e) {
                Slog.e(TAG, "Failure starting Freg Service", e);
            }

这里有个疑问:ServiceManager.addService接口的调用及参数。

修改完成后重新编译service模块。
mmm frameworks/base/services/java

make: Entering directory `/home/mydata3/workingdir'
target Java: services (out/target/common/obj/JAVA_LIBRARIES/services_intermediates/classes)
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Copying: out/target/common/obj/JAVA_LIBRARIES/services_intermediates/classes-jarjar.jar
Copying: out/target/common/obj/JAVA_LIBRARIES/services_intermediates/emma_out/lib/classes-jarjar.jar
Copying: out/target/common/obj/JAVA_LIBRARIES/services_intermediates/classes.jar
Copying: out/target/common/obj/JAVA_LIBRARIES/services_intermediates/noproguard.classes.jar
target Dex: services
Copying: out/target/common/obj/JAVA_LIBRARIES/services_intermediates/noproguard.classes.dex
target Jar: services (out/target/common/obj/JAVA_LIBRARIES/services_intermediates/javalib.jar)
Dexpreopt Boot Jar: out/target/product/generic/dex_bootjars/system/framework/services.odex
Processing target/product/generic/dex_bootjars/system/framework/services.jar
Done!
Install: out/target/product/generic/system/framework/services.odex
Install: out/target/product/generic/system/framework/services.jar
make: Leaving directory `/home/mydata3/workingdir'

新编译出的services.jar文件就包含了硬件访问服务FregService,并且在系统启动时,会被运行在系统进程System中。

重新编译system.img,重启系统,发现不能正常启动,虚拟机停在“android”画面,adb logcat有异常消息打印。通过/data/tombstones/下的文件,发现时zygote进程异常。

pid: 6615, tid: 6615, name: UNKNOWN  >>> zygote <<<

在logcat中查看到
这里写图片描述
看样子是依赖关系的问题,上网查找解决方法。
详细解释见模拟器启动异常
重新make systemimage命令,(时间比较长),可以运行正常。
参考博文:
Android:学习AIDL,这一篇文章就够了
Android应用程序访问linux驱动第三步:实现并向系统注册Service

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值