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
  










