摘要:本节主要来讲解Android10.0 JAVA层的HIDL服务创建和JAVA层的Client验证
阅读本文大约需要花费15分钟。
文章首发微信公众号:IngresGe
专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!
欢迎关注我的公众号!
[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析
[Android取经之路] 系列文章:
《系统启动篇》
- Android系统架构
- Android是怎么启动的
- Android 10.0系统启动之init进程
- Android10.0系统启动之Zygote进程
- Android 10.0 系统启动之SystemServer进程
- Android 10.0 系统服务之ActivityMnagerService
- Android10.0系统启动之Launcher(桌面)启动流程
- Android10.0应用进程创建过程以及Zygote的fork流程
- Android 10.0 PackageManagerService(一)工作原理及启动流程
- Android 10.0 PackageManagerService(二)权限扫描
- Android 10.0 PackageManagerService(三)APK扫描
- Android 10.0 PackageManagerService(四)APK安装流程
《日志系统篇》
- Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
- Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
- Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
- Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现
《Binder通信原理》:
- Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
- Android10.0 Binder通信原理(二)-Binder入门篇
- Android10.0 Binder通信原理(三)-ServiceManager篇
- Android10.0 Binder通信原理(四)-Native-C\C++实例分析
- Android10.0 Binder通信原理(五)-Binder驱动分析
- Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
- Android10.0 Binder通信原理(七)-Framework binder示例
- Android10.0 Binder通信原理(八)-Framework层分析
- Android10.0 Binder通信原理(九)-AIDL Binder示例
- Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
- Android10.0 Binder通信原理(十一)-Binder总结
《HwBinder通信原理》
- HwBinder入门篇-Android10.0 HwBinder通信原理(一)
- HIDL详解-Android10.0 HwBinder通信原理(二)
- HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
- HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
- HwServiceManager篇-Android10.0 HwBinder通信原理(五)
- Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
- Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
- JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
- JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
- HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
- HwBinder原理总结-Android10.0 HwBinder通信原理(十一)
《编译原理》
- 编译系统入门篇-Android10.0编译系统(一)
- 编译环境初始化-Android10.0编译系统(二)
- make编译过程-Android10.0编译系统(三)
- Image打包流程-Android10.0编译系统(四)
- Kati详解-Android10.0编译系统(五)
1. 概述
上一节,我们写了Native层的HIDL服务和客户端进程验证,这一节我们准备写一个JAVA层的HIDL服务和客户端进行验证。
本节会直接写一个APP用来与HIDL服务进行通信。
1.1 JAVA层的HwBinder架构
1.2 HwBinder通信原理
2. 示例说明
Server进程目录结构:
Server:
hal_demo
│
java
├─src
│ └─com
│ └─android
│ └─demo
│ └─Server.java
├─Android.bp
└─hidldemo_service_test
Client进程目录结构:
Client:
hidl_demo\app\src\main
├─java
│ └─com
│ └─android
│ └─hidldemo
│ └─MainActivity.java
├─res
├─Android.bp
└─AndroidManifest.xml
3.Java的HIDL服务
3.1 创建一个HIDL java服务的目录,并实现服务代码
命令:
vim vendor/ingres/hal_demo/java/src/com/android/demo/Server.java
code:
package com.android.demo;
import android.os.HwBinder;
import android.os.IBinder;
import android.os.IHwBinder;
import android.os.RemoteException;
import android.util.Log;
import vendor.ingres.demo.V1_0.IDemo;
class Demo extends IDemo.Stub {
public String getHelloString(String name) throws android.os.RemoteException {
String result = "Hello, " + name;
return result;
}
}
public class Server {
static final String TAG = "HIDLDemoService";
public static void main(String args[]){
Log.d(TAG, "start");
//1.启动HwBinder线程池
HwBinder.configureRpcThreadpool(1, true);
Demo demo = new Demo();
try {
//2.注册HIDL服务
demo.registerAsService("default");
Log.d(TAG, "success to register demo service");
} catch (RemoteException ex) {
Log.e(TAG, "exception, fail to register demo service");
}
//3.把当前的进程加入HwBinder的线程池进行循环
HwBinder.joinRpcThreadpool();
}
}
2.2 配置Android.bp
命令:
vim vendor/ingres/hal_demo/java/Android.bp
Code:
java_test {
name: "hidldemo_service",
srcs: ["**/*.java"],
static_libs: [
"vendor.ingres.demo-V1.0-java"
],
}
2.3 编译
命令:
mmm vendor/ingres/hal_demo/java/
生成文件:
\out\target\product\kona\testcases\hidldemo_service\arm64\hidldemo_service.jar
2.4 服务启动 可执行程序
命令:
vim vendor/ingres/hal_demo/java/hidldemo_service_test
code:
base=/data
export CLASSPATH=$base/framework/hidldemo_service.jar
exec app_process $base/framework com.android.demo.Server "$@"
3. 通过AS写一个简单的Activity Demo
activity_main.xml
code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/getHelloBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
tools:layout_editor_absoluteX="97dp"
tools:layout_editor_absoluteY="179dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
3.1.把AS的工程移植到Android工程中
1)mkdir -p vendor/ingres/hidl_demo
2)拷贝AS的工程到hidl_demo的目录中
3.2.工程实现:
1)创建Android.bp
vim vendor/ingres/hidl_demo/app/src/main/Android.bp
code:
android_app {
name: "hidldemo",
srcs: ["**/*.java"],
platform_apis: true,
certificate: "platform",
resource_dirs: ["res"],
manifest: "AndroidManifest.xml",
static_libs: [
"androidx-constraintlayout_constraintlayout",
"androidx-constraintlayout_constraintlayout-solver",
"androidx.appcompat_appcompat",
"vendor.ingres.demo-V1.0-java"
],
optimize: {
enabled: false,
},
dex_preopt: {
enabled: false,
},
}
2)实现hal服务的调用
修改以下文件:
vendor/ingres/hidl_demo/app/src/main/java/com/android/hidldemo/MainActivity.java
code:
package com.android.hidldemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import vendor.ingres.demo.V1_0.IDemo;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
static final String TAG = "HIDLDemoClient";
private static final String SERVICE_NAME = "demo";
private IDemo mHidlService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
Button getHelloBtn = (Button) findViewById(R.id.getHelloBtn);
getHelloBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.getHelloBtn:
Log.d(TAG, "start to click");
try {
//1.获取demo的HIDL服务,不会等待HIDL服务是否起来
mHidlService = IDemo.getService(true);
if (mHidlService == null) {
Log.e(TAG, "fail to get demo service");
} else {
Log.d(TAG, "success to get demo service");
//2.调用hidl的接口
String result = mHidlService.getHelloString("IngresGe");
Log.d(TAG, "HIDL return:" + result);
}
} catch (RemoteException ex) {
Log.e(TAG, "exception, fail to get demo service");
}
break;
}
}
}
遇到的编译问题:
vendor/ingres/hidl_demo/app/src/main/java/com/android/hidldemo/MainActivity.java:36: error: cannot access IHwInterface
mHidlService = IDemo.getService(true);
^
class file for android.os.IHwInterface not found
原因:
Android.bp里添加 sdk_version: "current", 后不能使用 @hide API
解决办法:
从Android.bp中去除 sdk_version: "current"
4. 测试
结合上一节Native层的HIDL服务,我这里准备进行两种验证:
1) JAVA层HIDL服务 + JAVA层Client
2) Native层HIDL 服务 + JAVA层Client
4.1 JAVA 层HIDL服务+ JAVA层client
1).安装编译好的hidldemo.apk到手机中
2).把 hidldemo_service.jar push到 /data/framework中
adb push xxx/hidldemo_service.jar /data/framework
3).把 hidldemo_service_test push 到 /data/nativetest64 中
adb push xxx/hidldemo_service_test /data/nativetest64
4).启动服务
./data/nativetest64/hidldemo_service_test
5).打开hidldemo app,点击button
log展示:
服务启动:
07-13 10:07:25.963 11209 11209 D HIDLDemoService: start
07-13 10:07:25.967 11209 11209 D HIDLDemoService: success to register demo service
Client接口调用成功:
07-13 10:52:16.371 14214 14214 D HIDLDemoClient: start to click
07-13 10:52:16.375 14214 14214 D HIDLDemoClient: success to get demo service
07-13 10:52:16.375 14214 14214 D HIDLDemoClient: HIDL return:Hello, IngresGe
4.2 C++ 层HIDL服务+ JAVA层client:
接上一节的C++ HIDL服务
1.安装编译好的hidldemo.apk到手机中
2.启动Native层的hal服务:
./vendor/bin/hw/./vendor.ingres.demo@1.0-service
3.打开hidldemo app,点击button
log展示:
Client接口调用成功:
07-13 11:12:26.902 9060 9060 D HIDLDemoClient: start to click
07-13 11:12:26.902 9060 9060 D HIDLDemoClient: success to get demo service
07-13 11:12:26.902 9060 9060 D HIDLDemoClient: HIDL return:Hello, IngresGe
注:
我在使用时是关闭了selinux进行的验证,真正使用时,还需要配置Selinux
我的微信公众号:IngresGe