摘要:本节主要来讲解Android10.0 JAVA层的HIDL服务创建和JAVA层的Client验证
阅读本文大约需要花费15分钟。
文章首发微信公众号:IngresGe
专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!
[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析
[Android取经之路] 系列文章:
《系统启动篇》
《日志系统篇》
《Binder通信原理》:
《HwBinder通信原理》
上一节,我们写了Native层的HIDL服务和客户端进程验证,这一节我们准备写一个JAVA层的HIDL服务和客户端进行验证。
本节会直接写一个APP用来与HIDL服务进行通信。
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
命令:
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();
}
}
命令:
vim vendor/ingres/hal_demo/java/Android.bp
Code:
java_test {
name: "hidldemo_service",
srcs: ["**/*.java"],
static_libs: [
"vendor.ingres.demo-V1.0-java"
],
}
命令:
mmm vendor/ingres/hal_demo/java/
生成文件:
\out\target\product\kona\testcases\hidldemo_service\arm64\hidldemo_service.jar
命令:
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 "$@"
activity_main.xml
code:
1)mkdir -p vendor/ingres/hidl_demo
2)拷贝AS的工程到hidl_demo的目录中
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"
结合上一节Native层的HIDL服务,我这里准备进行两种验证:
1) JAVA层HIDL服务 + JAVA层Client
2) Native层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
接上一节的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